Add the necessary code to uninstall packages (re-install still pending).

Both scripted access (packageDelete) and UI access have been tested
successfully with a variation of different situations including:
+ Uninstall a package which no other installed package depends
+ Uninstall multiple packages which no other installed packages depend
+ Uninstall multiple packages which depend on each other
+ Similar to above but when ordered removal requires tracing dependencies
+ Purposefully do things like uninstall a package that is not installed
+ Try to uninstall a package which other installed packages still depend
+ Try to uninstall multiple packages which other installed packages depend
+ And many more.
This commit is contained in:
Devin Teske 2013-07-05 06:52:07 +00:00
parent 12a9a52070
commit 542dd84bad
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=252775
3 changed files with 135 additions and 1 deletions

View File

@ -255,6 +255,9 @@ msg_ok="OK"
msg_options="Options"
msg_options_editor="Options Editor"
msg_other="other"
msg_pkg_delete_failed="Warning: pkg_delete of %s failed.\n Run with debugging for details."
msg_package_is_needed_by_other_installed_packages="Warning: Package %s is needed by\n %d other installed package%s."
msg_package_not_installed_cannot_delete="Warning: package %s not installed\n No package can be deleted."
msg_package_read_successfully_waiting_for_pkg_add="Package %s read successfully - waiting for pkg_add(1)"
msg_package_temp="Package Temp"
msg_package_was_added_successfully="Package %s was added successfully"
@ -376,6 +379,7 @@ msg_unable_to_make_directory_mountpoint="Unable to make %s directory mountpoint
msg_unable_to_open="Unable to open %s"
msg_uninstall="Uninstall"
msg_uninstall_desc="Mark this package for deletion"
msg_uninstalling_package_waiting_for_pkg_delete="Uninstalling %s package - waiting for pkg_delete(1)"
msg_unknown="unknown"
msg_unknown_user="Unknown user: %s"
msg_url_was_not_found="%s was not found, maybe directory or release-version are wrong?"

View File

@ -656,7 +656,7 @@ f_package_review()
debug= f_getvar _mark_$varpkg mark
[ "$mark" = "U" ] || continue
f_dprintf "%s: Uninstalling %s package" $fname "$package"
# XXX Uninstall package
f_package_delete "$package" || continue
f_package_deselect "$package"
done
@ -1057,6 +1057,135 @@ f_package_extract()
return $SUCCESS
}
# f_package_delete $name
#
# Delete package by full $name (lacks archive suffix; e.g., `.tbz').
#
f_package_delete()
{
local name="$1"
local fname=f_package_delete
if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; }
then
f_dprintf "packageDelete: %s" \
"$msg_no_package_name_passed_in_package_variable"
return $FAILURE
fi
f_dprintf "%s: name=[%s]" $fname "$name"
[ "$name" ] || return $FAILURE
{ # Verify and initialize device media if-defined
f_media_verify &&
f_device_init media &&
f_index_initialize packages/INDEX
} || return $FAILURE
# Now we have (indirectly via f_index_read()):
# CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg}
# PACKAGE_CATEGORIES _npkgs
local varpkg
f_str2varname "$name" varpkg
# Just as-in the user-interface (opposed to scripted-use), only allow
# packages with at least one category to be recognized.
#
local pkgcat=
if ! f_getvar _categories_$varpkg pkgcat || [ ! "$pkgcat" ]; then
# $pkg may be a partial name, search the index (this is slow)
f_index_search PACKAGE_INDEX "$name" name
if [ ! "$name" ]; then
f_show_msg \
"$msg_sorry_package_was_not_found_in_the_index" \
"$name"
return $FAILURE
fi
f_str2varname "$name" varpkg
fi
# If invoked through the scripted interface, we likely have not yet
# detected the installed packages -- something we should do only once.
#
if [ ! "$PACKAGES_DETECTED" ]; then
f_dprintf "%s: Detecting installed packages" $fname
f_package_detect_installed
export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[]
fi
# Now we have: _mark_{varpkg}=X for all installed packages
#
# Return failure if the package is not already installed.
#
local pkgmark=
f_getvar _mark_$varpkg pkgmark
if ! [ "$pkgmark" -a ! "${pkgmark#[XUR]}" ]; then
f_show_msg "$msg_package_not_installed_cannot_delete" "$name"
return $FAILURE
fi
#
# Check for dependencies
#
local pkgsel depc=0 udeps=
for pkgsel in $SELECTED_PACKAGES; do
local mark=
f_str2varname $pkgsel varpkg
debug= f_getvar _mark_$varpkg mark
[ "$mark" -a ! "${mark#[XUR]}" ] || continue
local dep rundeps=
debug= f_getvar _rundeps_$varpkg rundeps
for dep in $rundeps; do
if [ "$dep" = "$name" ]; then
# Maybe this package is marked for deletion too
if [ "$mark" = "U" ]; then
udeps="$udeps $pkgsel"
else
depc=$(( $depc + 1 ))
fi
break
fi
done
done
if [ $depc -gt 0 ]; then
local grammatical_s=
[ $depc -gt 1 ] && grammatical_s=s
f_show_msg \
"$msg_package_is_needed_by_other_installed_packages" \
"$name" "$depc" "$grammatical_s"
return $FAILURE
fi
#
# Chase dependencies that are marked for uninstallation
#
for pkgsel in $udeps; do
f_dprintf "%s: Uninstalling dependecy %s (marked for delete)" \
$fname "$pkgsel"
f_package_delete "$pkgsel"
done
#
# OK to perform the delete (no other packages depend on it)...
#
f_show_info "$msg_uninstalling_package_waiting_for_pkg_delete" "$name"
if f_debugging; then
pkg_delete -v "$name"
else
f_quietly pkg_delete "$name"
fi
if [ $? -ne $SUCCESS ]; then
f_show_msg "$msg_pkg_delete_failed" "$name"
return $FAILURE
else
f_dprintf "%s: pkg_delete(1) of %s successful" $fname "$name"
f_str2varname "$name" varpkg
setvar _mark_$varpkg ""
fi
}
############################################################ MAIN
f_dprintf "%s: Successfully loaded." packages/packages.subr

View File

@ -195,6 +195,7 @@ f_resword_new configPCNFSD f_config_pcnfsd
# packages/packages.subr
f_resword_new configPackages f_package_config
f_resword_new packageAdd f_package_add
f_resword_new packageDelete f_package_delete
# variable.subr
f_resword_new installVarDefaults f_variable_set_defaults