Merge '"Decide-in-editor" package conflict resolution strategy'

Reviewed-on: #2
This commit is contained in:
Juno Takano 2024-07-20 22:04:29 +02:00
commit 915b0db08b
10 changed files with 170 additions and 34 deletions

View file

@ -1,9 +1,13 @@
0.4.1 2024-07-14: Fixes "Cancel" option not exiting on package resolution
Fixes whitespace preventing package list matches on "remove all"
0.5.0 2024-07-18: "Decide in editor" package conflict resolution strategy
Drop pipefail shell option for dash compatibility
Add numerical debug levels to the log utility function
Check for shell option support before setting
0.4.1 2024-07-14: Fix "Cancel" option not exiting on package resolution
Fix whitespace preventing package list matches on "remove all"
0.4.0 2024-07-14: "Add/remove all from configuration" resolution strategy
0.3.1 2024-07-13: Refactor, new docs page, make cache refresh lazier
0.3.0 2024-07-11: "Enter packages to install/uninstall" resolution strategy
0.2.1 2024-07-10: Rename package_resolution.sh, document package conflicts
0.2.0 2024-07-10: Implement "uninstall/instal all" package resolution strategies
0.1.1 2024-07-07: Handle missing tori.conf and invalid installation root path
0.1.0 2024-07-07: Added configuration parsing
0.1.0 2024-07-07: Add configuration parsing

View file

@ -29,12 +29,8 @@ scan_packages() {
user_packages="$(get_user_packages)"
if [ "$system_packages" = "$user_packages" ]; then
log debug "packages match"
log debug "Packages match"
else
log debug "packages mismatch"
log debug "system:\n$system_packages"
log debug "user:\n$user_packages"
log user "System and configuration packages differ"
resolve_packages
fi

View file

@ -7,4 +7,5 @@
. "$TORI_ROOT/src/package/package_conflict_resolution.sh"
. "$TORI_ROOT/src/package/package_tracking.sh"
. "$TORI_ROOT/src/package/validate_input_packages.sh"
. "$TORI_ROOT/src/package/package_conflict_input_parser.sh"
. "$TORI_ROOT/src/package/update_package_cache.sh"

View file

@ -0,0 +1,80 @@
package_conflict_input_parser() {
local packages="$1"
local conflict_type="$2"
local input="$TMP_DIR/package_conflict_input"
local input_choices="$TMP_DIR/package_conflict_input_choices"
local choices=
local packages_to_install=
local packages_to_uninstall=
local packages_to_track=
local packages_to_untrack=
help_text_generator "$conflict_type" > "$input"
echo "$packages" | sed 's/ /\n/g' | while read -r package; do
echo "skip $package" >> "$input"
done
$EDITOR "$input"
choices="$(cat "$input" | grep -v '^#' | grep '.')"
echo "$choices" > "$input_choices"
# validation
while read -r action package; do
validate_input_packages "$package"
if [ "$action" = install ] || [ "$action" = i ]; then
packages_to_install="$packages_to_install $package"
elif [ "$action" = uninstall ] || [ "$action" = u ]; then
packages_to_uninstall="$packages_to_uninstall $package"
elif [ "$action" = add ] || [ "$action" = a ]; then
packages_to_track="$packages_to_track $package"
elif [ "$action" = remove ] || [ "$action" = r ]; then
packages_to_untrack="$packages_to_untrack $package"
elif [ "$action" = skip ] || [ "$action" = s ]; then
log debug "[package_conflict_input_parser] Skipped: $package"
else
log user "Invalid action provided for $package: $action"
fi
done < "$input_choices"
# actual system or configuration change
if [ -n "$packages_to_install" ]; then
package_manager install "$packages_to_install"
fi
if [ -n "$packages_to_uninstall" ]; then
package_manager uninstall "$packages_to_uninstall"
fi
if [ -n "$packages_to_track" ]; then
track_packages "$packages_to_track"
fi
if [ -n "$packages_to_untrack" ]; then
untrack_packages "$packages_to_untrack"
fi
}
help_text_generator() {
local conflict_type="$1"
echo "# Options:"
if [ "$conflict_type" == not_installed ]; then
echo "# [i]nstall Install package to system"
echo "# [r]emove Remove from configuration"
elif [ "$conflict_type" == not_on_configuration ]; then
echo "# [u]ninstall Uninstall package from system"
echo "# [a]dd Add to configuration"
else
debug fatal "Invalid conflict type provided: $conflict_type"
return 1
fi
echo "# [s]kip Do not take any action"
echo -e "\n# Providing just the value between brackets is sufficient"
echo -e "# Replace 'skip' below with the desired option\n"
}

View file

@ -57,6 +57,8 @@ not_on_configuration_dialog() {
if validate_input_packages "$input_packages"; then
track_packages "$input_packages"
fi
elif [ "$strategy" = 5 ]; then
package_conflict_input_parser "$conflicted_packages" 'not_on_configuration'
else
log debug "[resolve_packages] Unexpected input: $strategy"
not_on_configuration_dialog "$conflicted_packages"
@ -97,6 +99,8 @@ not_installed_dialog() {
read -r -p "Enter space-separated packages to remove from the configuation: " input_packages
log debug "Input: input_packages = $input_packages"
untrack_packages "$input_packages"
elif [ "$strategy" = 5 ]; then
package_conflict_input_parser "$conflicted_packages" 'not_installed'
else
log debug "[resolve_packages] Unexpected input: $strategy"
not_installed_dialog "$conflicted_packages"

View file

@ -8,9 +8,9 @@ package_manager() {
local args__get_manually_installed
local args__get_available
set_opts +
set_opts off
local args__user_args="$2"
set_opts -
set_opts on
if [ "$OS" = "FreeBSD" ]; then
manager="pkg"

View file

@ -9,10 +9,10 @@ track_packages() {
untrack_packages() {
local packages="$1"
log debug "[untrack_packages] Removing packages: $packages"
log info "[untrack_packages] Removing packages: $packages"
echo "$packages" | xargs | sed 's/ /\n/g' | while read -r package; do
sed -i '' "/^[[:space:]]*$package[[:space:]]*$/d" "$CONFIG_ROOT/packages"
log debug "[untrack_packages] Executed removal for $package with exit code $?"
log info "[untrack_packages] Executed removal for $package with exit code $?"
done
}

View file

@ -1,7 +1,7 @@
update_package_cache() {
set_opts +
set_opts off
local argument="$1"
set_opts -
set_opts on
if [ -f "$PACKAGE_CACHE" ]; then
local last_update="$(date -r "$PACKAGE_CACHE" +%Y-%m-%d)"

View file

@ -4,21 +4,73 @@ log() {
local level="$1"
local message="$2"
if [ $level = fatal ]; then
printf "[tori] $(date "+%H:%M:%S"): $message\n" 1>&2
elif [ $level = user ]; then
printf "[tori] $(date "+%H:%M:%S"): $message\n" 1>&2
elif [ -n "$DEBUG" ] && [ $level = debug ]; then
printf "$(date "+%H:%M:%N") $message\n" 1>&2
print_user_message() {
echo "[tori] $(date "+%H:%M:%S"): $1" 1>&2
}
print_debug_message() {
echo "$(date "+%H:%M:%N") $1" 1>&2
}
if [ -z "$DEBUG" ]; then
DEBUG=3
elif ! echo "$DEBUG" | grep -q '^[[:number:]]$'; then
echo "[log] Warning: DEBUG should always be set to a number. Assuming DEBUG=3 (warn)"
DEBUG=3
fi
if [ -z "$DEBUG_DISABLED_WARNING" ] && [ "$DEBUG" -eq 0 ]; then
echo "[log] Warning: Setting DEBUG=0 disables all logging except for user messages"
echo " Use a value beween 1 (fatal) and 5 (debug). The default level is 3 (warn)"
DEBUG_DISABLED_WARNING=1
elif [ "$DEBUG" -gt 5 ]; then
echo "[log] Warning: Assuming DEBUG maximum level of 5 (debug) over provided level $DEBUG"
DEBUG=5
fi
if [ "$level" = user ]; then
print_user_message "$message"
elif [ "$DEBUG" -ge 1 ] && [ "$level" = fatal ]; then
print_user_message "$message"
elif [ "$DEBUG" -ge 2 ] && [ "$level" = error ]; then
print_user_message "$message"
elif [ "$DEBUG" -ge 3 ] && [ "$level" = warn ]; then
print_user_message "$message"
elif [ "$DEBUG" -ge 4 ] && [ "$level" = info ]; then
print_debug_message "$message"
elif [ "$DEBUG" -ge 5 ] && [ "$level" = debug ]; then
print_debug_message "$message"
fi
}
set_opts() {
sign="$1"
local target="$1"
local sign=
set "${sign}o" errexit
set "${sign}o" nounset
set "${sign}o" pipefail
if [ "$target" = on ]; then
sign='-'
elif [ "$target" = off ]; then
sign='+'
else
log fatal "Invalid set_opts target: $target. Expected on or off"
return 1
fi
set_opt() {
local opt="$1"
if set -o | grep -q "^$opt[[:space:]]"; then
set "${sign}o" "$opt"
log debug "[set_opts] Set: $(set -o | grep "^$opt[[:space:]]")"
else
log fatal "Unsupported shell: no $opt option support"
return 1
fi
}
set_opt errexit
set_opt nounset
set_opt pipefail
}
prepare_directories() {

19
tori
View file

@ -2,31 +2,31 @@
main() {
# paths
VERSION="0.4.1 2024-07-14"
VERSION="0.5.0 2024-07-18"
TORI_ROOT="$HOME/.local/share/tori"
CONFIG_ROOT="$HOME/.config/tori"
TMP_DIR="/tmp/tori"
CACHE_DIR="$HOME/.cache/tori"
check_core_paths
. "$TORI_ROOT/src/index.sh"
# state
# os-independent state
DEBUG=$DEBUG
DEBUG_DISABLED_WARNING=
## user input
argument="$1"
parameter="$2"
set_opts -
# import source
## global constants
check_core_paths
. "$TORI_ROOT/src/index.sh"
set_opts on
## os-dependent state
OS="$(get_operating_system)"
PACKAGE_CACHE="$CACHE_DIR/${OS}_packages.cache"
## global state
base_files=
bkp_files=
user_packages=
@ -69,7 +69,6 @@ check_core_paths() {
exit 1
fi
[ -n "$DEBUG" ] && echo "TORI_ROOT: $TORI_ROOT"
}
main "$1" "$2"