mirror of
https://github.com/ScoopInstaller/Scoop.git
synced 2026-09-30 01:05:58 +00:00
**Data matters, please review** This is a rework of #2891 #2890 and #2882 . This will also fix #2724 and fix #2900 , close #2779 **Introduction** I add a function called `unlink_persist_data($dir)`, which recursively unlink all junction/hard link in the given directory. This affects some sub-commands which have interaction with junction/hard link: - `scoop-install`: the persisting logic has been improved as follow: 1. if there are data in the `persist` folder, also in app(`source`) folder, rename that one located in app folder (e.g. app's default setting files) with a `original` suffix, then create link from `persist` to app 2. if there are data in the `persist` folder, but no in app(`source`) folder, just create link from `persist` to app 3. if there is no data in the `persist` folder (e.g. fresh install), but there are data in app(`source`) folder (e.g. app's default setting files), we will just use that default setting files as the first-time persisting. So move that files from app folder to `persist` folder, then create link from `persist` to app 4. But what if if there is neither data in the `persist` folder (e.g. fresh install), nor in the app(`source`) folder (e.g. setting files will be created after first startup, like `Everthing.db`). We need to create empty persisting target in the `persist` folder. But by default we can't know if a persisting target is a file or a directory (e.g. `conf.d`). So we create a directory by default, and to avoid this, manifest maintainers should use `pre_install` to manually create the source file before persisting. - `scoop-reset`: `reset` command uses the logic of `install`, but there is a problem: before re-persisting data, there have been `junction/hard link` in the app(`source`) folder. It will throw an exception of file exists #2724 . To fix this, we should unlink all old link before re-persisting, using `unlink_persist_data`. - `scoop-uninstall`: `Remove-Item` can not remove `NTFS junction`, we need to unlink all persistting data, before uninstalling/deleting an app, but keeping persisting data. - `scoop-cleanup`: like `uninstall`, `Remove-Item` can not remove `NTFS junction`, we need to unlink all persistting data, before deleting old versions of an app. Before PR #2882 , it use `fsutil.exe` to unlink junction, which is not friendly to restricted users (#2832 and #2881 ). Beyond the logic improvement, there is a new feature now: it supports sub-folder data persisting, like: ```json { "homepage": "https://scoop.sh", "description": "A dummy manifest for scoop tests.", "license": "Freeware", "version": "1.1.0", "url": "https://get.scoop.sh", "pre_install": [ "if (!(test-path \"$dir\\dummy.txt\")) { new-item -force \"$dir\\dummy.txt\" -itemtype file | out-null }", "if (!(test-path \"$dir\\dummydir\")) { new-item \"$dir\\dummydir\" -itemtype directory | out-null }", "if (!(test-path \"$dir\\subdir\")) { new-item \"$dir\\subdir\" -itemtype directory | out-null }", "if (!(test-path \"$dir\\subdir\\subdummydir\")) { new-item \"$dir\\subdir\\subdummydir\" -itemtype directory | out-null }", "if (!(test-path \"$dir\\subdir\\subdummy.txt\")) { new-item -force \"$dir\\subdir\\subdummy.txt\" -itemtype file | out-null }", ], "persist": [ "dummy.txt", "dummydir", "subdir\\subdummydir", "subdir\\subdummy.txt" ] } ``` So no need to strip directories of source for target anymore. To participate in the code review and tests, go visit https://github.com/h404bi/scoop-persist-test for test cases.
86 lines
2.4 KiB
PowerShell
86 lines
2.4 KiB
PowerShell
# Usage: scoop reset <app>
|
|
# Summary: Reset an app to resolve conflicts
|
|
# Help: Used to resolve conflicts in favor of a particular app. For example,
|
|
# if you've installed 'python' and 'python27', you can use 'scoop reset' to switch between
|
|
# using one or the other.
|
|
|
|
. "$psscriptroot\..\lib\core.ps1"
|
|
. "$psscriptroot\..\lib\manifest.ps1"
|
|
. "$psscriptroot\..\lib\help.ps1"
|
|
. "$psscriptroot\..\lib\getopt.ps1"
|
|
. "$psscriptroot\..\lib\install.ps1"
|
|
. "$psscriptroot\..\lib\versions.ps1"
|
|
. "$psscriptroot\..\lib\config.ps1"
|
|
. "$psscriptroot\..\lib\shortcuts.ps1"
|
|
|
|
reset_aliases
|
|
$opt, $apps, $err = getopt $args
|
|
if($err) { "scoop reset: $err"; exit 1 }
|
|
|
|
if(!$apps) { error '<app> missing'; my_usage; exit 1 }
|
|
|
|
if($apps -eq '*') {
|
|
$local = installed_apps $false | ForEach-Object { ,@($_, $false) }
|
|
$global = installed_apps $true | ForEach-Object { ,@($_, $true) }
|
|
$apps = @($local) + @($global)
|
|
}
|
|
|
|
$apps | ForEach-Object {
|
|
($app, $global) = $_
|
|
|
|
$app, $bucket, $version = parse_app $app
|
|
|
|
if(($global -eq $null) -and (installed $app $true)) {
|
|
# set global flag when running reset command on specific app
|
|
$global = $true
|
|
}
|
|
|
|
if($app -eq 'scoop') {
|
|
# skip scoop
|
|
return
|
|
}
|
|
|
|
if(!(installed $app)) {
|
|
error "'$app' isn't installed"
|
|
return
|
|
}
|
|
|
|
if ($null -eq $version) {
|
|
$version = current_version $app $global
|
|
}
|
|
|
|
$manifest = installed_manifest $app $version $global
|
|
# if this is null we know the version they're resetting to
|
|
# is not installed
|
|
if ($manifest -eq $null) {
|
|
error "'$app ($version)' isn't installed"
|
|
return
|
|
}
|
|
|
|
if($global -and !(is_admin)) {
|
|
warn "'$app' ($version) is a global app. You need admin rights to reset it. Skipping."
|
|
return
|
|
}
|
|
|
|
write-host "Resetting $app ($version)."
|
|
|
|
$dir = resolve-path (versiondir $app $version $global)
|
|
$original_dir = $dir
|
|
$persist_dir = persistdir $app $global
|
|
|
|
$install = install_info $app $version $global
|
|
$architecture = $install.architecture
|
|
|
|
$dir = link_current $dir
|
|
create_shims $manifest $dir $global $architecture
|
|
create_startmenu_shortcuts $manifest $dir $global $architecture
|
|
env_add_path $manifest $dir
|
|
env_set $manifest $dir $global
|
|
# unlink all potential old link before re-persisting
|
|
unlink_persist_data $original_dir
|
|
persist_data $manifest $original_dir $persist_dir
|
|
persist_permission $manifest $global
|
|
}
|
|
|
|
exit 0
|