Add the necessary code to install packages (uninstall and re-install still
pending). Both scripted access (packageAdd) and UI access have been tested successfully with a variation of different situations including: + Install a package with no dependencies + Install a package with dependencies that are already installed + Install a package with dependencies where some are already installed + Repeat each of the above from FTP and local Directory + Purposefully do things like try to install a package that does not exist + Try to install a package for which a dependency could not be loaded + Try to install a package that is in the INDEX bot not on the media + And many more.
This commit is contained in:
parent
f687c95d86
commit
31185df0d3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=252745
@ -34,6 +34,8 @@ hline_arrows_tab_punc_enter="Use arrows, TAB, punctuation, ENTER"
|
||||
hline_choose_help_for_more_information_on_media_types="Choose Help for more information on the various media types"
|
||||
msg_accept_continue="Accept/Continue"
|
||||
msg_accessibility_desc="Ports to help disabled users."
|
||||
msg_adding_package_as_a_dependency_from_media="Adding %s (as a dependency) from %s"
|
||||
msg_adding_package_from_media="Adding %s from %s"
|
||||
msg_afterstep_desc="Ports to support the AfterStep window manager."
|
||||
msg_all="All"
|
||||
msg_all_desc="All available packages in all categories."
|
||||
@ -174,6 +176,7 @@ msg_invalid_ipv4_address="Invalid IPv4 address"
|
||||
msg_invalid_name_server_ip_address_specified="Invalid name server IP address specified"
|
||||
msg_invalid_netmask_value="Invalid netmask value"
|
||||
msg_invalid_nfs_path_specification="Invalid NFS path specification. Must be of the form:\nhost:/full/pathname/to/FreeBSD/distdir"
|
||||
msg_io_error_while_reading_in_the_package="I/O error while reading in the %s package."
|
||||
msg_io_or_format_error_on_index_file="I/O or format error on %s file.\nPlease verify media (or path to media) and try again."
|
||||
msg_ipv4_address="IPv4 Address"
|
||||
msg_ipv4_gateway="IPv4 Gateway"
|
||||
@ -196,6 +199,7 @@ msg_length_of_specified_url_is_too_long="Length of specified URL is %u character
|
||||
msg_linux_desc="Linux programs that can run under binary compatibility."
|
||||
msg_lisp_desc="Software related to the Lisp language."
|
||||
msg_lithuania="Lithuania"
|
||||
msg_loading_of_dependent_package_failed="Loading of dependent package %s failed"
|
||||
msg_located_index_now_reading_package_data_from_it="Located INDEX, now reading package data from it..."
|
||||
msg_logging_in_to_user_at_host="Logging in to %s@%s.."
|
||||
msg_looking_up_host="Looking up host %s"
|
||||
@ -238,6 +242,7 @@ msg_no_dos_primary_partitions_found="No DOS primary partitions found! This inst
|
||||
msg_no_floppy_devices_found="No floppy devices found! Please check that your system's configuration\nis correct. For more information, consult the hardware guide in the Doc\nmenu."
|
||||
msg_no_gateway_has_been_set="No gateway has been set. You will be unable to access hosts\nnot on your local network"
|
||||
msg_no_network_devices="No network devices available!"
|
||||
msg_no_package_name_passed_in_package_variable="No package name passed in package variable"
|
||||
msg_no_packages_were_selected_for_extraction="No packages were selected for extraction."
|
||||
msg_no_such_file_or_directory="%s: %s: No such file or directory"
|
||||
msg_no_usb_devices_found="No USB devices found (try Options/Re-scan Devices)"
|
||||
@ -250,7 +255,9 @@ msg_ok="OK"
|
||||
msg_options="Options"
|
||||
msg_options_editor="Options Editor"
|
||||
msg_other="other"
|
||||
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"
|
||||
msg_packages="packages"
|
||||
msg_page_of_npages="(Page %s of %s)"
|
||||
msg_palm_desc="Software support for the Palm(tm) series."
|
||||
@ -258,6 +265,7 @@ msg_parallel_desc="Applications dealing with parallelism in computing."
|
||||
msg_pear_desc="Software related to the Pear PHP framework."
|
||||
msg_perl5_desc="Utilities/modules for the PERL5 language."
|
||||
msg_permission_denied="%s: %s: Permission denied"
|
||||
msg_pkg_add_apparently_did_not_like_the_package="pkg_add(1) apparently did not like the %s package."
|
||||
msg_plan9_desc="Software from the Plan9 operating system."
|
||||
msg_please_check_the_url_and_try_again="No such directory: %s\nplease check the URL and try again.\n"
|
||||
msg_please_enter_password="Please enter your password for sudo(8):"
|
||||
@ -301,6 +309,7 @@ msg_quick_start_how_to_use_this_menu_system="Quick start - How to use this menu
|
||||
msg_reinstall="Reinstall"
|
||||
msg_reinstall_desc="Mark this package for reinstall"
|
||||
msg_release_name="Release Name"
|
||||
msg_required_package_not_found="Warning: %s is a required package but was not found."
|
||||
msg_rerun_bsdconfig_initial_device_probe="Re-run bsdconfig initial device probe"
|
||||
msg_rescan_devices="Re-scan Devices"
|
||||
msg_reset="RESET!"
|
||||
@ -334,6 +343,7 @@ msg_slovenia="Slovenia"
|
||||
msg_snapshots_server_japan="Snapshots Server Japan"
|
||||
msg_snapshots_server_sweden="Snapshots Server Sweden"
|
||||
msg_sorry_invalid_url="Sorry, %s is an invalid URL!"
|
||||
msg_sorry_package_was_not_found_in_the_index="Sorry, package %s was not found in the INDEX."
|
||||
msg_sorry_try_again="Sorry, try again."
|
||||
msg_south_africa="South Africa"
|
||||
msg_spain="Spain"
|
||||
@ -358,8 +368,10 @@ msg_uk="UK"
|
||||
msg_ukraine="Ukraine"
|
||||
msg_ukrainian_desc="Ported software for the Ukrainian market."
|
||||
msg_unable_to_configure_device="Unable to configure the %s interface!\nThis installation method cannot be used."
|
||||
msg_unable_to_fetch_package_from_selected_media="Unable to fetch package %s from selected media.\nNo package add will be done."
|
||||
msg_unable_to_get_file_from_selected_media="Unable to get %s file from selected media.\n\nThis may be because the packages collection is not available\non the distribution media you've chosen, most likely an FTP site\nwithout the packages collection mirrored. Please verify that\nyour media, or your path to the media, is correct and try again."
|
||||
msg_unable_to_get_proper_ftp_path="Unable to get proper FTP path. FTP media not initialized."
|
||||
msg_unable_to_initialize_media_type_for_package_extract="Unable to initialize media type for package extract."
|
||||
msg_unable_to_make_directory_mountpoint="Unable to make %s directory mountpoint for %s!"
|
||||
msg_unable_to_open="Unable to open %s"
|
||||
msg_uninstall="Uninstall"
|
||||
|
@ -242,6 +242,44 @@ f_index_extract_pages()
|
||||
)"
|
||||
}
|
||||
|
||||
# f_index_search $var_to_get $name [$var_to_set]
|
||||
#
|
||||
# Search the package INDEX ($PACKAGE_INDEX by default if/when $var_to)get is
|
||||
# NULL; but should not be missing) for $name, returning the first match.
|
||||
# Matches are strict (not regular expressions) and must match the beginning
|
||||
# portion of the package name to be considered a match. If $var_to_set is
|
||||
# missing or NULL, output is sent to standard output. If a match is found,
|
||||
# returns success; otherwise failure.
|
||||
#
|
||||
f_index_search()
|
||||
{
|
||||
local __var_to_get="${1:-PACKAGE_INDEX}" __pkg_basename="$2"
|
||||
local __var_to_set="$3"
|
||||
|
||||
f_dprintf "f_index_search: Searching package data (in %s) for %s" \
|
||||
"$__var_to_get" "$__pkg_basename"
|
||||
|
||||
local __pkg=
|
||||
__pkg=$( debug= f_getvar "$__var_to_get" |
|
||||
awk -F'|' -v basename="$__pkg_basename" '
|
||||
BEGIN { n = length(basename) }
|
||||
substr($1, 0, n) == basename { print $1; exit }
|
||||
' )
|
||||
if [ ! "$__pkg" ]; then
|
||||
f_dprintf "f_index_search: No packages matching %s found" \
|
||||
"$__pkg_basename"
|
||||
return $FAILURE
|
||||
fi
|
||||
|
||||
f_dprintf "f_index_search: Found package %s" "$__pkg"
|
||||
if [ "$__var_to_set" ]; then
|
||||
setvar "$__var_to_set" "$__pkg"
|
||||
else
|
||||
echo "$__pkg"
|
||||
fi
|
||||
return $SUCCESS
|
||||
}
|
||||
|
||||
############################################################ MAIN
|
||||
|
||||
f_dprintf "%s: Successfully loaded." packages/index.subr
|
||||
|
@ -32,6 +32,8 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
|
||||
. $BSDCFG_SHARE/common.subr || exit 1
|
||||
f_dprintf "%s: loading includes..." "$0"
|
||||
f_include $BSDCFG_SHARE/dialog.subr
|
||||
f_include $BSDCFG_SHARE/device.subr
|
||||
f_include $BSDCFG_SHARE/media/common.subr
|
||||
f_include $BSDCFG_SHARE/packages/categories.subr
|
||||
f_include $BSDCFG_SHARE/packages/index.subr
|
||||
f_include $BSDCFG_SHARE/strings.subr
|
||||
@ -48,9 +50,15 @@ f_include_lang $BSDCFG_LIBE/include/messages.subr
|
||||
|
||||
############################################################ GLOBALS
|
||||
|
||||
#
|
||||
# Package extensions to try
|
||||
#
|
||||
PACKAGE_EXTENSIONS=".tbz .tbz2 .tgz"
|
||||
|
||||
#
|
||||
# Variables used to track runtime states
|
||||
#
|
||||
PACKAGES_DETECTED= # Boolean (NULL/non-NULL); detected installed packages?
|
||||
PACKAGE_CATEGORIES= # List of package categories parsed from INDEX
|
||||
SELECTED_PACKAGES= # Packages selected by user in [X]dialog(1) interface
|
||||
|
||||
@ -629,7 +637,7 @@ f_package_review()
|
||||
f_str2varname "$package" varpkg
|
||||
f_getvar _mark_$varpkg mark
|
||||
[ "$mark" = "I" ] || continue
|
||||
# XXX Install package
|
||||
f_package_add "$package" || continue
|
||||
f_package_deselect "$package"
|
||||
done
|
||||
for package in $SELECTED_PACKAGES; do
|
||||
@ -812,6 +820,236 @@ f_package_config()
|
||||
done
|
||||
}
|
||||
|
||||
# f_package_add $package_name [$depended]
|
||||
#
|
||||
# Like f_package_extract(), but assumes current media device and chases deps.
|
||||
# Note that $package_name should not contain the archive suffix (e.g., `.tbz').
|
||||
# If $depended is present and non-NULL, the package is treated as a dependency
|
||||
# (in this function, dependencies are not handled any differently, but the
|
||||
# f_package_extract() function is passed this value and it displays a different
|
||||
# message when installing a dependency versus non-dependency).
|
||||
#
|
||||
f_package_add()
|
||||
{
|
||||
local name="$1" depended="$2" status=$SUCCESS retval
|
||||
|
||||
local alert=f_show_msg no_confirm=
|
||||
f_getvar $VAR_NO_CONFIRM no_confirm
|
||||
[ "$no_confirm" ] && alert=f_show_info
|
||||
|
||||
if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; }
|
||||
then
|
||||
f_dprintf "packageAdd: %s" \
|
||||
"$msg_no_package_name_passed_in_package_variable"
|
||||
return $FAILURE
|
||||
fi
|
||||
|
||||
{ # 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_package_detect_installed
|
||||
export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[]
|
||||
fi
|
||||
# Now we have: _mark_{varpkg}=X for all installed packages
|
||||
|
||||
#
|
||||
# Since we're maintaining data structures for installed packages,
|
||||
# short-circuit the package dependency checks if the package is already
|
||||
# installed. This prevents wasted cycles, minor delays between package
|
||||
# extractions, and worst-case an infinite loop with a certain faulty
|
||||
# INDEX file.
|
||||
#
|
||||
local mark=
|
||||
f_getvar _mark_$varpkg mark && [ "$mark" = "X" ] && return $SUCCESS
|
||||
|
||||
local dep vardep rundeps=
|
||||
f_getvar _rundeps_$varpkg rundeps
|
||||
for dep in $rundeps; do
|
||||
f_str2varname "$dep" vardep
|
||||
|
||||
# Skip dependency if already installed
|
||||
mark=
|
||||
f_getvar _mark_$vardep mark && [ "$mark" = "X" ] && continue
|
||||
|
||||
# Just as-in the user-interface (opposed to scripted-use), only
|
||||
# allow packages with at least one category to be recognized.
|
||||
#
|
||||
local depcat=
|
||||
if ! f_getvar _categories_$vardep depcat || [ ! "$depcat" ]
|
||||
then
|
||||
$alert "$msg_required_package_not_found" "$dep"
|
||||
[ "$no_confirm" ] && sleep 2
|
||||
fi
|
||||
|
||||
f_package_add "$dep"
|
||||
retval=$?
|
||||
if [ $retval -ne $SUCCESS ]; then
|
||||
status=$(( $status | $retval ))
|
||||
|
||||
# XXX package could be on a future disc volume
|
||||
# XXX (not supporting multiple disc volumes yet)
|
||||
|
||||
$alert "$msg_loading_of_dependent_package_failed" \
|
||||
"$dep"
|
||||
[ "$no_confirm" ] && sleep 2
|
||||
fi
|
||||
done
|
||||
[ $status -eq $SUCCESS ] || return $status
|
||||
|
||||
#
|
||||
# Done with the deps? Try to load the real m'coy.
|
||||
#
|
||||
|
||||
f_package_extract media "$name" "$depended"
|
||||
retval=$?
|
||||
if [ $retval -ne $SUCCESS ]; then
|
||||
status=$(( $status | $retval ))
|
||||
else
|
||||
setvar _mark_$varpkg X
|
||||
fi
|
||||
|
||||
return $status
|
||||
}
|
||||
|
||||
# f_package_extract $device $name [$depended]
|
||||
#
|
||||
# Extract a package based on a namespec and media device. If $depended is
|
||||
# present and non-NULL, the notification displayed while installing the package
|
||||
# has "as a dependency" appended.
|
||||
#
|
||||
f_package_extract()
|
||||
{
|
||||
local device="$1" name="$2" depended="$3"
|
||||
|
||||
# Check to make sure it's not already there
|
||||
local varpkg mark=
|
||||
f_str2varname "$name" varpkg
|
||||
f_getvar _mark_$varpkg mark
|
||||
[ "$mark" = "X" ] && return $SUCCESS
|
||||
|
||||
if ! f_device_init $device; then
|
||||
f_show_msg \
|
||||
"$msg_unable_to_initialize_media_type_for_package_extract"
|
||||
return $FAILURE
|
||||
fi
|
||||
|
||||
# If necessary, initialize the ldconfig hints
|
||||
[ -f "/var/run/ld-elf.so.hints" ] ||
|
||||
f_quietly ldconfig /usr/lib /usr/lib/compat /usr/local/lib
|
||||
|
||||
# Make a couple paranoid locations for temp
|
||||
# files to live if user specified none
|
||||
local tmpdir
|
||||
f_getvar $VAR_PKG_TMPDIR:-/var/tmp tmpdir
|
||||
f_quietly mkdir -p -m 1777 "$tmpdir"
|
||||
|
||||
local path
|
||||
case "$name" in
|
||||
*/*) path="$name" ;;
|
||||
*)
|
||||
case "$name" in
|
||||
*-*|*_*) path="packages/All/$name" ;;
|
||||
*) path="packages/Latest/$name"
|
||||
esac
|
||||
esac
|
||||
|
||||
local fname=f_package_extract
|
||||
|
||||
# We have a path, call the device strategy routine to get the file
|
||||
local pkg_ext probe_only=1 found=
|
||||
for pkg_ext in "" $PACKAGE_EXTENSIONS; do
|
||||
if f_device_get $device "$path$pkg_ext" $probe_only; then
|
||||
path="$path$pkg_ext"
|
||||
f_dprintf "%s: found path=[%s] dev=[%s]" \
|
||||
$fname "$path" "$device"
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
local alert=f_show_msg no_confirm=
|
||||
f_getvar $VAR_NO_CONFIRM no_confirm
|
||||
[ "$no_confirm" ] && alert=f_show_info
|
||||
|
||||
if [ ! "$found" ]; then
|
||||
f_dprintf "%s: No such %s file on %s device" \
|
||||
$fname "$path" "$device"
|
||||
$alert "$msg_unable_to_fetch_package_from_selected_media" \
|
||||
"$name"
|
||||
[ "$no_confirm" ] && sleep 2
|
||||
return $FAILURE
|
||||
fi
|
||||
|
||||
local devname=
|
||||
f_struct device_$device get name devname
|
||||
if [ "$depended" ]; then
|
||||
f_show_info "$msg_adding_package_as_a_dependency_from_media" \
|
||||
"$name" "$devname"
|
||||
else
|
||||
f_show_info "$msg_adding_package_from_media" "$name" "$devname"
|
||||
fi
|
||||
|
||||
# Get package data and pipe into pkg_add(1) while providing feedback
|
||||
{
|
||||
if ! f_device_get $device "$path"; then
|
||||
$alert "$msg_io_error_while_reading_in_the_package" \
|
||||
"$name" \
|
||||
>&$DIALOG_TERMINAL_PASSTHRU_FD 2> /dev/null
|
||||
[ "$no_confirm" ] && sleep 2
|
||||
else
|
||||
f_show_info \
|
||||
"$msg_package_read_successfully_waiting_for_pkg_add" \
|
||||
"$name" >&$DIALOG_TERMINAL_PASSTHRU_FD 2> /dev/null
|
||||
fi
|
||||
} | {
|
||||
if f_debugging; then
|
||||
/usr/sbin/pkg_add -v -
|
||||
else
|
||||
f_quietly /usr/sbin/pkg_add -
|
||||
fi
|
||||
}
|
||||
if [ $? -ne $SUCCESS ]; then
|
||||
$alert "$msg_pkg_add_apparently_did_not_like_the_package" \
|
||||
"$name"
|
||||
[ "$no_confirm" ] && sleep 2
|
||||
else
|
||||
f_show_info "$msg_package_was_added_successfully" "$name"
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
return $SUCCESS
|
||||
}
|
||||
|
||||
############################################################ MAIN
|
||||
|
||||
f_dprintf "%s: Successfully loaded." packages/packages.subr
|
||||
|
@ -190,6 +190,7 @@ f_resword_new mediaSetHTTPProxy f_media_set_http_proxy
|
||||
|
||||
# packages/packages.subr
|
||||
f_resword_new configPackages f_package_config
|
||||
f_resword_new packageAdd f_package_add
|
||||
|
||||
# variable.subr
|
||||
f_resword_new installVarDefaults f_variable_set_defaults
|
||||
|
Loading…
Reference in New Issue
Block a user