greatly improved upgrade system

This commit is contained in:
fatalerrors
2026-04-01 17:20:49 +02:00
parent ac66e896dd
commit 08e9e6c799

View File

@@ -39,24 +39,27 @@ export UPDT_URL="$BASE_URL/raw/branch/master"
export ARCH_URL="$BASE_URL/archive/master.tar.gz" export ARCH_URL="$BASE_URL/archive/master.tar.gz"
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Check for profile updates # Check whether a newer profile version is available
# Usage: check_updates [-q] # Usage: check_updates [-q]
# If -q is specified, the function will operate in quiet mode (internal use only) # If -q is specified, the function will operate in quiet mode (internal use only)
check_updates() check_updates()
{ {
local quiet=0 local quiet=0 result=5 PARSED
local PARSED=$(getopt -o hq --long help,quiet -n 'check_updates' -- "$@") local vfile="" lastver=""
PARSED=$(getopt -o hq --long help,quiet -n 'check_updates' -- "$@")
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"check_updates --help\" to display usage." disp E "Invalid options, use \"check_updates --help\" to display usage."
return 1 return 2
fi fi
eval set -- "$PARSED" eval set -- "$PARSED"
while true; do while true; do
case "$1" in case "$1" in
-h|--help) -h|--help)
printf "check_updates: Check for new versions.\n\n" printf "check_updates: Check whether a newer profile version is available.\n\n"
printf "Usage: check_updates\n" printf "Usage: check_updates [-q|--quiet]\n"
printf "This command only checks availability; it does not modify the installation.\n"
return 0 return 0
;; ;;
-q|--quiet) -q|--quiet)
@@ -73,28 +76,35 @@ check_updates()
esac esac
done done
(( $quiet != 1 )) && disp I "Checking for updates..." (( quiet != 1 )) && disp I "Checking for updates..."
local vfile="/tmp/version"
wget "$UPDT_URL/version" -O $vfile >/dev/null 2>&1 || { vfile=$(mktemp /tmp/profile_version.XXXXXX) || {
disp E "Can't download version file, impossible to proceed!" disp E "Failed to create a temporary file."
return 4
}
dwl "$UPDT_URL/version" "$vfile" >/dev/null 2>&1 || {
rm -f "$vfile"
disp E "Cannot download version file; unable to continue."
return 5 return 5
} }
if [[ -s $vfile ]]; then if [[ -s $vfile ]]; then
local lastver=$(cat $vfile) lastver=$(<"$vfile")
if [[ $lastver != $PROFVERSION ]]; then if [[ "$lastver" != "$PROFVERSION" ]]; then
disp I "You have version $PROFVERSION installed. Version $lastver is available." disp I "Installed: $PROFVERSION. Available: $lastver."
(( $quiet != 1 )) && disp I "You should upgrade to last version when possible." (( quiet != 1 )) && disp I "You should upgrade when possible."
result=1 result=1
else else
(( $quiet != 1 )) && disp I "Your version is up-to-date." (( quiet != 1 )) && disp I "Your version is up-to-date."
result=0 result=0
fi fi
rm -f $vfile rm -f "$vfile"
else else
disp E "Impossible to read temporary file, impossible to proceed." rm -f "$vfile"
disp E "Temporary file is unreadable; unable to continue."
fi fi
unset lastver vfile
return $result return $result
} }
export -f check_updates export -f check_updates
@@ -102,23 +112,63 @@ export -f check_updates
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Apply update to profile # Apply the available profile upgrade
# Usage: profile_upgrade # Usage: profile_upgrade [options]
profile_upgrade() profile_upgrade()
{ {
local PARSED=$(getopt -o h --long help -n 'profile_upgrade' -- "$@") local PARSED
local check_rc=0 dry_run=0 force_git=0 switch_to_git=0
local archive_file="" tmpbase="" use_archive=0 branch=""
local tmpdir="" archive="" extracted_root=""
PARSED=$(getopt -o hf:t:nFb:g --long help,file:,tmpdir:,dry-run,force,branch:,switch-to-git -n 'profile_upgrade' -- "$@")
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
printf "Invalid options, use \"profile_upgrade --help\" to display usage." disp E "Invalid options, use \"profile_upgrade --help\" to display usage."
return 1 return 2
fi fi
eval set -- "$PARSED" eval set -- "$PARSED"
while true; do while true; do
case "$1" in case "$1" in
-h|--help) -h|--help)
printf "profile_upgrade: Upgrade the profile to the latest version.\n\n" printf "profile_upgrade: Apply the available profile upgrade.\n\n"
printf "Usage: profile_upgrade\n" printf "Usage: profile_upgrade [options]\n\n"
printf "Options:\n"
printf "\t-h, --help\t\tDisplay this help screen\n"
printf "\t-f, --file ARCHIVE\tUse a local archive file for the upgrade\n"
printf "\t-t, --tmpdir DIR\tCreate the temporary working directory under DIR\n"
printf "\t-b, --branch NAME\tUse NAME as the target Git branch\n"
printf "\t-g, --switch-to-git\tReplace current install with a fresh Git clone\n"
printf "\t-n, --dry-run\t\tDisplay what would be done without changing anything\n"
printf "\t-F, --force\t\tDiscard local changes before upgrading\n\n"
printf "If the profile is installed from Git, the upgrade uses 'git pull'.\n"
printf "Otherwise, it downloads or applies an archive and refreshes the files.\n"
return 0 return 0
;; ;;
-f|--file)
archive_file="$2"
use_archive=1
shift 2
;;
-t|--tmpdir)
tmpbase="$2"
shift 2
;;
-b|--branch)
branch="$2"
shift 2
;;
-g|--switch-to-git)
switch_to_git=1
shift
;;
-n|--dry-run)
dry_run=1
shift
;;
-F|--force)
force_git=1
shift
;;
--) --)
shift shift
break break
@@ -130,59 +180,229 @@ profile_upgrade()
esac esac
done done
if check_updates -q; then if (( ! use_archive && ! switch_to_git )); then
disp "No update available." check_updates -q
check_rc=$?
if (( check_rc == 0 )); then
disp I "No update available."
return 0 return 0
elif (( check_rc > 1 )); then
disp E "Unable to check whether an update is available."
return "$check_rc"
fi
fi fi
if [[ -s $MYPATH/profile.sh ]]; then if [[ ! -s $MYPATH/profile.sh ]]; then
disp E "Installation path detection failed, cannot upgrade automatically." disp E "Install path detection failed; cannot upgrade automatically."
return 1 return 1
fi fi
if [[ -d $MYPATH/.git ]] && (( use_archive )) && (( ! force_git )); then
disp E "Refusing archive upgrade on a Git install without --force."
return 1
fi
if (( switch_to_git )); then
command -v git >/dev/null 2>&1 || {
disp E "Git is required to switch this install to a Git clone."
return 3
}
if (( dry_run )); then
disp I "[dry-run] rm -rf \"$MYPATH\"/.git"
disp I "[dry-run] git clone "$BASE_URL" \"$MYPATH\""
[[ -n "$branch" ]] && disp I "[dry-run] git -C \"$MYPATH\" checkout "$branch""
return 0
fi
if [[ -d $MYPATH/.git ]]; then if [[ -d $MYPATH/.git ]]; then
disp W "Git repository already present; no switch is needed."
else
local backup_dir="${MYPATH}.pre-git.$$.bak"
mv "$MYPATH" "$backup_dir" || {
disp E "Failed to move current install out of the way."
return 3
}
git clone "$BASE_URL" "$MYPATH" || {
disp E "Git clone failed; previous install kept in $backup_dir."
mv "$backup_dir" "$MYPATH" 2>/dev/null || true
return 3
}
[[ -n "$branch" ]] && (
cd "$MYPATH" && git checkout "$branch"
) || true
disp I "Switched installation to Git source."
disp I "Previous install kept in $backup_dir."
return 0
fi
fi
if [[ -d $MYPATH/.git ]] && (( ! use_archive )); then
disp I "Git installation detected, applying git pull." disp I "Git installation detected, applying git pull."
pushd "$MYPATH" || { command -v git >/dev/null 2>&1 || {
disp E "Git is required for this upgrade but is not available."
return 3
}
pushd "$MYPATH" >/dev/null || {
disp E "Failed to change directory to $MYPATH." disp E "Failed to change directory to $MYPATH."
return 3 return 3
} }
git pull || { git rev-parse --is-inside-work-tree >/dev/null 2>&1 || {
disp E "Git pull failed, upgrade not applyed." disp E "Install directory is not a valid Git working tree."
popd popd >/dev/null || return 1
return 2 return 3
} }
disp I "Successfully upgraded using git." if ! git diff --quiet || ! git diff --cached --quiet || [[ -n $(git ls-files --others --exclude-standard) ]]; then
popd if (( force_git )); then
disp W "Force mode: local Git changes and untracked files will be lost."
if (( dry_run )); then
disp I "[dry-run] git fetch --all --prune"
disp I "[dry-run] git reset --hard HEAD"
disp I "[dry-run] git clean -fd"
else else
disp I "No Git detected. Downloading and applying upgrade from archive..." git fetch --all --prune || {
local tmpdir="/tmp/profile_upg.$$" disp E "Git fetch failed, upgrade not applied."
mkdir -p "$tmpdir" || { popd >/dev/null || return 1
disp E "Failed to create temporary directory."
return 4 return 4
} }
git reset --hard HEAD || {
disp E "Git reset failed, upgrade not applied."
popd >/dev/null || return 1
return 4
}
git clean -fd || {
disp E "Git clean failed, upgrade not applied."
popd >/dev/null || return 1
return 4
}
fi
else
disp W "The Git working tree contains local changes."
disp W "Consider committing or stashing them before upgrading, or use --force."
disp W "Upgrade may fail if the changes conflict with the upgrade."
fi
fi
if [[ -n "$branch" ]]; then
if (( dry_run )); then
disp I "[dry-run] git fetch origin $branch"
disp I "[dry-run] git checkout $branch"
else
git fetch origin "$branch" || {
disp E "Git fetch failed for branch $branch."
popd >/dev/null || return 1
return 2
}
git checkout "$branch" || {
disp E "Git checkout failed for branch $branch."
popd >/dev/null || return 1
return 2
}
fi
fi
local archive="$tmpdir/profile.tar.gz" if (( dry_run )); then
wget -q "$ARCH_URL" -O "$archive" || { if [[ -n "$branch" ]]; then
disp E "Failed to download archive." disp I "[dry-run] git pull origin $branch"
rm -rf "$tmpdir" else
disp I "[dry-run] git pull"
fi
else
if [[ -n "$branch" ]]; then
git pull origin "$branch" || {
disp E "Git pull failed, upgrade not applied."
popd >/dev/null || return 1
return 2
}
else
git pull || {
disp E "Git pull failed, upgrade not applied."
popd >/dev/null || return 1
return 2
}
fi
disp I "Successfully upgraded using git."
fi
popd >/dev/null || return 1
else
if (( use_archive )); then
[[ -r "$archive_file" ]] || {
disp E "Local archive '$archive_file' is missing or unreadable."
return 4
}
disp I "Using local archive $archive_file."
else
disp W "No Git repo found. Git is the recommended source."
disp I "Applying upgrade from archive..."
fi
if [[ -n "$tmpbase" ]]; then
if (( dry_run )); then
disp I "[dry-run] mkdir -p \"$tmpbase\""
disp I "[dry-run] mktemp -d \"$tmpbase/profile_upg.XXXXXX\""
tmpdir="$tmpbase/profile_upg.DRYRUN"
else
mkdir -p "$tmpbase" || {
disp E "Failed to create temporary directory base $tmpbase."
return 5 return 5
} }
tmpdir=$(mktemp -d "$tmpbase/profile_upg.XXXXXX") || {
disp E "Failed to create temp working directory under $tmpbase."
return 5
}
fi
else
if (( dry_run )); then
disp I "[dry-run] mktemp -d /tmp/profile_upg.XXXXXX"
tmpdir="/tmp/profile_upg.DRYRUN"
else
tmpdir=$(mktemp -d /tmp/profile_upg.XXXXXX) || {
disp E "Failed to create temporary directory."
return 5
}
fi
fi
tar -xzf "$archive" -C "$tmpdir" || { if (( use_archive )); then
disp E "Archive extraction failed." archive="$archive_file"
else
archive="$tmpdir/profile.tar.gz"
if (( dry_run )); then
disp I "[dry-run] dwl \"$ARCH_URL\" \"$archive\""
else
dwl "$ARCH_URL" "$archive" || {
disp E "Failed to download archive."
rm -rf "$tmpdir" rm -rf "$tmpdir"
return 6 return 6
} }
fi
fi
disp I "Installing new version..." if (( dry_run )); then
cp -r "$tmpdir"/profile/* "$MYPATH"/ || { disp I "[dry-run] tar -xzf \"$archive\" -C \"$tmpdir\""
disp E "Failed to copy new files to $MYPATH." disp I "[dry-run] cp -a <extracted_profile>/. \"$MYPATH\"/"
else
tar -xzf "$archive" -C "$tmpdir" || {
disp E "Archive extraction failed."
rm -rf "$tmpdir" rm -rf "$tmpdir"
return 7 return 7
} }
disp I "Upgrade complete. You should now logout and login again." extracted_root=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d ! -name '.*' | head -n 1)
if [[ -z "$extracted_root" ]]; then
disp E "Could not find extracted profile files."
rm -rf "$tmpdir" rm -rf "$tmpdir"
return 8
fi
disp I "Installing new version..."
cp -a "$extracted_root"/. "$MYPATH"/ || {
disp E "Failed to copy new files into $MYPATH."
rm -rf "$tmpdir"
return 9
}
disp I "Upgrade complete. Please log out and log in again."
rm -rf "$tmpdir"
fi
fi fi
} }
export -f profile_upgrade export -f profile_upgrade