summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bsdconfig/share
diff options
context:
space:
mode:
authordteske <dteske@FreeBSD.org>2013-07-05 06:52:07 +0000
committerdteske <dteske@FreeBSD.org>2013-07-05 06:52:07 +0000
commitf53995138b4a591d14ebadc723e8258c91b0a0dd (patch)
treed449e0bce9e001b2c2abc3f558acae42700f47de /usr.sbin/bsdconfig/share
parentd9933606bc7a2a4ec773896e40fe74eccb14b8d2 (diff)
downloadFreeBSD-src-f53995138b4a591d14ebadc723e8258c91b0a0dd.zip
FreeBSD-src-f53995138b4a591d14ebadc723e8258c91b0a0dd.tar.gz
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.
Diffstat (limited to 'usr.sbin/bsdconfig/share')
-rwxr-xr-xusr.sbin/bsdconfig/share/packages/packages.subr131
-rw-r--r--usr.sbin/bsdconfig/share/script.subr1
2 files changed, 131 insertions, 1 deletions
diff --git a/usr.sbin/bsdconfig/share/packages/packages.subr b/usr.sbin/bsdconfig/share/packages/packages.subr
index 73c4bb8..9337f5c 100755
--- a/usr.sbin/bsdconfig/share/packages/packages.subr
+++ b/usr.sbin/bsdconfig/share/packages/packages.subr
@@ -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
diff --git a/usr.sbin/bsdconfig/share/script.subr b/usr.sbin/bsdconfig/share/script.subr
index 5574863..72ff8f3 100644
--- a/usr.sbin/bsdconfig/share/script.subr
+++ b/usr.sbin/bsdconfig/share/script.subr
@@ -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
OpenPOWER on IntegriCloud