Use a 'current' directory junction for the current version of apps, so that path is maintained across app updates (see #1179)

This commit is contained in:
Luke Sampson
2016-12-31 22:12:53 +11:00
parent 9f709f97d3
commit abd6d0e6c5
6 changed files with 72 additions and 3 deletions

View File

@@ -25,7 +25,13 @@ function do_uninstall($app, $global) {
echo "uninstalling $app"
run_uninstaller $manifest $architecture $dir
rm_shims $manifest $global
env_rm_path $manifest $dir $global
# If a junction was used during install, that will have been used
# as the reference directory. Othewise it will just be the version
# directory.
$refdir = unlink_current (appdir $app $global)
env_rm_path $manifest $refdir $global
env_rm $manifest $global
$appdir = appdir $app $global

View File

@@ -37,6 +37,7 @@ function install_app($app, $architecture, $global) {
pre_install $manifest $architecture
run_installer $fname $manifest $architecture $dir $global
ensure_install_dir_not_in_path $dir $global
$dir = link_current $dir
create_shims $manifest $dir $global $architecture
create_startmenu_shortcuts $manifest $dir $global
if($global) { ensure_scoop_in_path $global } # can assume local scoop is in path
@@ -597,6 +598,59 @@ function rm_shims($manifest, $global) {
}
}
# Gets the path for the 'current' directory junction for
# the specified version directory.
function current_dir($versiondir) {
$parent = split-path $versiondir
return "$parent\current"
}
# Creates or updates the directory junction for [app]/current,
# pointing to the specified version directory for the app.
#
# Returns the 'current' junction directory if in use, otherwise
# the version directory.
function link_current($versiondir) {
if(!(get_config USE_JUNCTIONS)) { return $versiondir }
$currentdir = current_dir $versiondir
write-host "linking $(friendly_path $currentdir) => $(friendly_path $versiondir)"
if($currentdir -eq $versiondir) {
abort "error: version 'current' is not allowed!"
}
if(test-path $currentdir) {
# remove the junction
cmd /c rmdir $currentdir
}
cmd /c mklink /j $currentdir $versiondir | out-null
return $currentdir
}
# Removes the directory junction for [app]/current which
# points to the current version directory for the app.
#
# Returns the 'current' junction directory (if it exists),
# otherwise the normal version directory.
function unlink_current($versiondir) {
if(!(get_config USE_JUNCTIONS)) { return $versiondir }
$currentdir = current_dir $versiondir
if(test-path $currentdir) {
write-host "unlinking $(friendly_path $currentdir)"
# remove the junction
cmd /c rmdir $currentdir
return $currentdir
}
return $appdir
}
# to undo after installers add to path so that scoop manifest can keep track of this instead
function ensure_install_dir_not_in_path($dir, $global) {
$path = (env 'path' $global)

View File

@@ -9,7 +9,7 @@ function versions($app, $global) {
$appdir = appdir $app $global
if(!(test-path $appdir)) { return @() }
sort_versions (gci $appdir -dir | % { $_.name })
sort_versions (gci $appdir -dir -attr !reparsePoint | % { $_.name })
}
function version($ver) {

View File

@@ -26,6 +26,7 @@ $manifest = installed_manifest $app $version
$install = install_info $app $version
$architecture = $install.architecture
$dir = link_current $dir
create_shims $manifest $dir $false $architecture
env_add_path $manifest $dir
env_set $manifest $dir

View File

@@ -11,6 +11,7 @@
. "$psscriptroot\..\lib\shortcuts.ps1"
. "$psscriptroot\..\lib\versions.ps1"
. "$psscriptroot\..\lib\getopt.ps1"
. "$psscriptroot\..\lib\config.ps1"
reset_aliases
@@ -61,7 +62,13 @@ foreach($app in $apps) {
run_uninstaller $manifest $architecture $dir
rm_shims $manifest $global
rm_startmenu_shortcuts $manifest $global
env_rm_path $manifest $dir $global
# If a junction was used during install, that will have been used
# as the reference directory. Othewise it will just be the version
# directory.
$refdir = unlink_current $dir
env_rm_path $manifest $refdir $global
env_rm $manifest $global
try { rm -r $dir -ea stop -force }

View File

@@ -148,6 +148,7 @@ function update($app, $global, $quiet = $false, $independent) {
pre_install $manifest $architecture
run_installer $fname $manifest $architecture $dir $global
ensure_install_dir_not_in_path $dir
$dir = link_current $dir
create_shims $manifest $dir $global $architecture
env_add_path $manifest $dir $global
env_set $manifest $dir $global