diff options
| author | Martin Guzman <55927935+brockar@users.noreply.github.com> | 2026-01-24 19:45:52 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-24 19:45:52 -0300 |
| commit | 6b9ef5fb2219ccbb3d42adb4b691c466991efc9f (patch) | |
| tree | 74b141beda34510f7c44d5e82d2c6ed54c6bfbac /scripts | |
| parent | 035724daaf362eac452a781e20144cf893ed274f (diff) | |
| parent | d2fbf319bc3b09e4345dea390b85d328eb0318c0 (diff) | |
Merge pull request #931 from JaKooLit/development
Development to main: Fix upgrade bug
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/lib_copy.sh | 299 | ||||
| -rw-r--r-- | scripts/lib_update.sh | 14 |
2 files changed, 242 insertions, 71 deletions
diff --git a/scripts/lib_copy.sh b/scripts/lib_copy.sh index fa1231c5..331c6906 100644 --- a/scripts/lib_copy.sh +++ b/scripts/lib_copy.sh @@ -12,25 +12,30 @@ copy_phase1() { echo -n "${CAT:-[ACTION]} Do you want to replace ${YELLOW:-}$DIR2${RESET:-} config? (y/n): " read DIR1_CHOICE case "$DIR1_CHOICE" in - [Yy]*) BACKUP_DIR=$(get_backup_dirname) - mv "$DIRPATH" "$DIRPATH-backup-$BACKUP_DIR" 2>&1 | tee -a "$log" - echo -e "${NOTE:-[NOTE]} - Backed up $DIR2 to $DIRPATH-backup-$BACKUP_DIR." 2>&1 | tee -a "$log" - cp -r "config/$DIR2" "$HOME/.config/$DIR2" 2>&1 | tee -a "$log" - echo -e "${OK:-[OK]} - Replaced $DIR2 with new configuration." 2>&1 | tee -a "$log" - if [ "$DIR2" = "rofi" ]; then - if [ -d "$DIRPATH-backup-$BACKUP_DIR/themes" ]; then - for file in "$DIRPATH-backup-$BACKUP_DIR/themes"/*; do - [ -e "$file" ] || continue - cp -n "$file" "$HOME/.config/rofi/themes/" >>"$log" 2>&1 || true - done || true - fi - if [ -f "$DIRPATH-backup-$BACKUP_DIR/0-shared-fonts.rasi" ]; then - cp "$DIRPATH-backup-$BACKUP_DIR/0-shared-fonts.rasi" "$HOME/.config/rofi/0-shared-fonts.rasi" >>"$log" 2>&1 - fi - fi - break ;; - [Nn]*) echo -e "${NOTE:-[NOTE]} - Skipping ${YELLOW:-}$DIR2${RESET:-}" 2>&1 | tee -a "$log"; break ;; - *) echo -e "${WARN:-[WARN]} - Invalid choice. Please enter Y or N." ;; + [Yy]*) + BACKUP_DIR=$(get_backup_dirname) + mv "$DIRPATH" "$DIRPATH-backup-$BACKUP_DIR" 2>&1 | tee -a "$log" + echo -e "${NOTE:-[NOTE]} - Backed up $DIR2 to $DIRPATH-backup-$BACKUP_DIR." 2>&1 | tee -a "$log" + cp -r "config/$DIR2" "$HOME/.config/$DIR2" 2>&1 | tee -a "$log" + echo -e "${OK:-[OK]} - Replaced $DIR2 with new configuration." 2>&1 | tee -a "$log" + if [ "$DIR2" = "rofi" ]; then + if [ -d "$DIRPATH-backup-$BACKUP_DIR/themes" ]; then + for file in "$DIRPATH-backup-$BACKUP_DIR/themes"/*; do + [ -e "$file" ] || continue + cp -n "$file" "$HOME/.config/rofi/themes/" >>"$log" 2>&1 || true + done || true + fi + if [ -f "$DIRPATH-backup-$BACKUP_DIR/0-shared-fonts.rasi" ]; then + cp "$DIRPATH-backup-$BACKUP_DIR/0-shared-fonts.rasi" "$HOME/.config/rofi/0-shared-fonts.rasi" >>"$log" 2>&1 + fi + fi + break + ;; + [Nn]*) + echo -e "${NOTE:-[NOTE]} - Skipping ${YELLOW:-}$DIR2${RESET:-}" 2>&1 | tee -a "$log" + break + ;; + *) echo -e "${WARN:-[WARN]} - Invalid choice. Please enter Y or N." ;; esac done else @@ -49,47 +54,52 @@ copy_waybar() { echo -n "${CAT:-[ACTION]} Do you want to replace ${YELLOW:-}$DIRW${RESET:-} config? (y/n): " read DIR1_CHOICE case "$DIR1_CHOICE" in - [Yy]*) BACKUP_DIR=$(get_backup_dirname) - cp -r "$DIRPATHw" "$DIRPATHw-backup-$BACKUP_DIR" 2>&1 | tee -a "$log" - echo -e "${NOTE:-[NOTE]} - Backed up $DIRW to $DIRPATHw-backup-$BACKUP_DIR." 2>&1 | tee -a "$log" - rm -rf "$DIRPATHw" && cp -r "config/$DIRW" "$DIRPATHw" 2>&1 | tee -a "$log" - for file in "config" "style.css"; do - symlink="$DIRPATHw-backup-$BACKUP_DIR/$file" - target_file="$DIRPATHw/$file" - if [ -L "$symlink" ]; then - symlink_target=$(readlink "$symlink") - if [ -f "$symlink_target" ]; then - rm -f "$target_file" && cp -f "$symlink_target" "$target_file" - fi - fi - done - for dir in "$DIRPATHw-backup-$BACKUP_DIR/configs"/*; do - [ -e "$dir" ] || continue - if [ -d "$dir" ]; then - target_dir="$HOME/.config/waybar/configs/$(basename "$dir")" - [ -d "$target_dir" ] || cp -r "$dir" "$HOME/.config/waybar/configs/" - fi - done - for file in "$DIRPATHw-backup-$BACKUP_DIR/configs"/*; do - [ -e "$file" ] || continue - target_file="$HOME/.config/waybar/configs/$(basename "$file")" - [ -e "$target_file" ] || cp "$file" "$HOME/.config/waybar/configs/" - done || true - for file in "$DIRPATHw-backup-$BACKUP_DIR/style"/*; do - [ -e "$file" ] || continue - if [ -d "$file" ]; then - target_dir="$HOME/.config/waybar/style/$(basename "$file")" - [ -d "$target_dir" ] || cp -r "$file" "$HOME/.config/waybar/style/" - else - target_file="$HOME/.config/waybar/style/$(basename "$file")" - [ -e "$target_file" ] || cp "$file" "$HOME/.config/waybar/style/" - fi - done || true - BACKUP_FILEw="$DIRPATHw-backup-$BACKUP_DIR/UserModules" - [ -f "$BACKUP_FILEw" ] && cp -f "$BACKUP_FILEw" "$DIRPATHw/UserModules" - break ;; - [Nn]*) echo -e "${NOTE:-[NOTE]} - Skipping ${YELLOW:-}$DIRW${RESET:-} config replacement." 2>&1 | tee -a "$log"; break ;; - *) echo -e "${WARN:-[WARN]} - Invalid choice. Please enter Y or N." ;; + [Yy]*) + BACKUP_DIR=$(get_backup_dirname) + cp -r "$DIRPATHw" "$DIRPATHw-backup-$BACKUP_DIR" 2>&1 | tee -a "$log" + echo -e "${NOTE:-[NOTE]} - Backed up $DIRW to $DIRPATHw-backup-$BACKUP_DIR." 2>&1 | tee -a "$log" + rm -rf "$DIRPATHw" && cp -r "config/$DIRW" "$DIRPATHw" 2>&1 | tee -a "$log" + for file in "config" "style.css"; do + symlink="$DIRPATHw-backup-$BACKUP_DIR/$file" + target_file="$DIRPATHw/$file" + if [ -L "$symlink" ]; then + symlink_target=$(readlink "$symlink") + if [ -f "$symlink_target" ]; then + rm -f "$target_file" && cp -f "$symlink_target" "$target_file" + fi + fi + done + for dir in "$DIRPATHw-backup-$BACKUP_DIR/configs"/*; do + [ -e "$dir" ] || continue + if [ -d "$dir" ]; then + target_dir="$HOME/.config/waybar/configs/$(basename "$dir")" + [ -d "$target_dir" ] || cp -r "$dir" "$HOME/.config/waybar/configs/" + fi + done + for file in "$DIRPATHw-backup-$BACKUP_DIR/configs"/*; do + [ -e "$file" ] || continue + target_file="$HOME/.config/waybar/configs/$(basename "$file")" + [ -e "$target_file" ] || cp "$file" "$HOME/.config/waybar/configs/" + done || true + for file in "$DIRPATHw-backup-$BACKUP_DIR/style"/*; do + [ -e "$file" ] || continue + if [ -d "$file" ]; then + target_dir="$HOME/.config/waybar/style/$(basename "$file")" + [ -d "$target_dir" ] || cp -r "$file" "$HOME/.config/waybar/style/" + else + target_file="$HOME/.config/waybar/style/$(basename "$file")" + [ -e "$target_file" ] || cp "$file" "$HOME/.config/waybar/style/" + fi + done || true + BACKUP_FILEw="$DIRPATHw-backup-$BACKUP_DIR/UserModules" + [ -f "$BACKUP_FILEw" ] && cp -f "$BACKUP_FILEw" "$DIRPATHw/UserModules" + break + ;; + [Nn]*) + echo -e "${NOTE:-[NOTE]} - Skipping ${YELLOW:-}$DIRW${RESET:-} config replacement." 2>&1 | tee -a "$log" + break + ;; + *) echo -e "${WARN:-[WARN]} - Invalid choice. Please enter Y or N." ;; esac done else @@ -187,9 +197,140 @@ compose_overlay_from_backup() { fi } +cleanup_duplicate_userconfigs() { + local current_version="$1" + local log="$2" + + if [ -z "$current_version" ]; then + return + fi + + # Run de-dupe only for existing installs up to and including v2.3.19. + # For v2.3.20 and newer, the underlying duplication bug is fixed and + # this cleanup is no longer needed (and might mask future issues). + if version_gte "$current_version" "2.3.20"; then + echo "${INFO:-[INFO]} Skipping UserConfigs duplicate cleanup for detected version v$current_version (>= 2.3.20)." 2>&1 | tee -a "$log" + return + fi + + echo "${INFO:-[INFO]} Running UserConfigs duplicate cleanup for detected version v$current_version (<= 2.3.19)." 2>&1 | tee -a "$log" + + local HYPR_DIR="$HOME/.config/hypr" + local BASE_DIR="$HYPR_DIR/configs" + local USER_DIR="$HYPR_DIR/UserConfigs" + + local STARTUP_BASE="$BASE_DIR/Startup_Apps.conf" + local STARTUP_USER="$USER_DIR/Startup_Apps.conf" + local WINDOW_BASE="$BASE_DIR/WindowRules.conf" + local WINDOW_USER="$USER_DIR/WindowRules.conf" + local KEYBINDS_BASE="$BASE_DIR/Keybinds.conf" + local KEYBINDS_USER="$USER_DIR/UserKeybinds.conf" + + # Startup_Apps: strip exec-once lines from UserConfigs that are exact + # duplicates of the base Startup_Apps.conf. + if [ -f "$STARTUP_BASE" ] && [ -f "$STARTUP_USER" ]; then + local tmp_startup + local backup_startup + backup_startup="$STARTUP_USER.backup-dupfix-$(date +%Y%m%d-%H%M%S)" + tmp_startup=$(mktemp) + awk ' + function trim(s){ gsub(/^[ \t]+|[ \t]+$/, "", s); return s } + FNR==NR { + if ($0 ~ /^[ \t]*exec-once[ \t]*=/) { + line=trim($0) + base[line]=1 + } + next + } + { + if ($0 ~ /^[ \t]*exec-once[ \t]*=/) { + line=trim($0) + if (line in base) next + } + print + } + ' "$STARTUP_BASE" "$STARTUP_USER" >"$tmp_startup" + if ! cmp -s "$STARTUP_USER" "$tmp_startup"; then + cp "$STARTUP_USER" "$backup_startup" + mv "$tmp_startup" "$STARTUP_USER" + echo "${NOTE:-[NOTE]} - Removed duplicate Startup_Apps entries matching base config." 2>&1 | tee -a "$log" + else + rm -f "$tmp_startup" + fi + fi + + # WindowRules: strip windowrule/layerrule lines from UserConfigs that + # are exact duplicates of the base WindowRules.conf. + if [ -f "$WINDOW_BASE" ] && [ -f "$WINDOW_USER" ]; then + local tmp_window + local backup_window + backup_window="$WINDOW_USER.backup-dupfix-$(date +%Y%m%d-%H%M%S)" + tmp_window=$(mktemp) + awk ' + function trim(s){ gsub(/^[ \t]+|[ \t]+$/, "", s); return s } + FNR==NR { + if ($0 ~ /^[ \t]*(windowrule|layerrule)[ \t]*=/) { + line=trim($0) + base[line]=1 + } + next + } + { + if ($0 ~ /^[ \t]*(windowrule|layerrule)[ \t]*=/) { + line=trim($0) + if (line in base) next + } + print + } + ' "$WINDOW_BASE" "$WINDOW_USER" >"$tmp_window" + if ! cmp -s "$WINDOW_USER" "$tmp_window"; then + cp "$WINDOW_USER" "$backup_window" + mv "$tmp_window" "$WINDOW_USER" + echo "${NOTE:-[NOTE]} - Removed duplicate WindowRules entries matching base config." 2>&1 | tee -a "$log" + else + rm -f "$tmp_window" + fi + fi + + # Keybinds: strip bind* lines from UserKeybinds.conf that are exact + # duplicates of the base Keybinds.conf. Comments and unbinds are kept. + if [ -f "$KEYBINDS_BASE" ] && [ -f "$KEYBINDS_USER" ]; then + local tmp_keybinds + local backup_keybinds + backup_keybinds="$KEYBINDS_USER.backup-dupfix-$(date +%Y%m%d-%H%M%S)" + tmp_keybinds=$(mktemp) + awk ' + function trim(s){ gsub(/^[ \t]+|[ \t]+$/, "", s); return s } + FNR==NR { + # Match any Hyprland bind variant: bindd, bindmd, bindld, binded, + # bindlnd, bindeld, etc. + if ($0 ~ /^[ \t]*bind[a-z]*[ \t]*=/) { + line=trim($0) + base[line]=1 + } + next + } + { + if ($0 ~ /^[ \t]*bind[a-z]*[ \t]*=/) { + line=trim($0) + if (line in base) next + } + print + } + ' "$KEYBINDS_BASE" "$KEYBINDS_USER" >"$tmp_keybinds" + if ! cmp -s "$KEYBINDS_USER" "$tmp_keybinds"; then + cp "$KEYBINDS_USER" "$backup_keybinds" + mv "$tmp_keybinds" "$KEYBINDS_USER" + echo "${NOTE:-[NOTE]} - Removed duplicate UserKeybinds entries matching base Keybinds.conf." 2>&1 | tee -a "$log" + else + rm -f "$tmp_keybinds" + fi + fi +} restore_user_configs() { local log="$1" local express_mode="$2" + local old_version="$3" local DIRPATH="$HOME/.config/hypr" local BACKUP_DIR @@ -201,29 +342,32 @@ restore_user_configs() { exit 1 fi + # In express mode we still want to run the de-dupe logic, but we skip + # the interactive restoration prompts so the workflow stays non-blocking. + local SKIP_RESTORE_PROMPTS=0 if [ -d "$BACKUP_DIR_PATH" ] && [ "$express_mode" -eq 1 ]; then echo "${NOTE:-[NOTE]} Express mode: skipping UserConfigs restoration prompts." 2>&1 | tee -a "$log" - return + SKIP_RESTORE_PROMPTS=1 fi - if [ -d "$BACKUP_DIR_PATH" ] && [ "$express_mode" -eq 0 ]; then + if [ -d "$BACKUP_DIR_PATH" ] && [ "$SKIP_RESTORE_PROMPTS" -eq 0 ]; then local VERSION_FILE VERSION_FILE=$(find "$DIRPATH" -maxdepth 1 -name "v*.*.*" | head -n 1) local CURRENT_VERSION="999.9.9" - if [ -n "$VERSION_FILE" ]; then - CURRENT_VERSION=$(basename "$VERSION_FILE" | sed 's/^v//') + if [ -n "$old_version" ]; then + CURRENT_VERSION="$old_version" fi local TARGET_VERSION="2.3.19" echo -e "${NOTE:-[NOTE]} Restoring previous ${MAGENTA:-}User-Configs${RESET:-}... " 2>&1 | tee -a "$log" - printf "${WARNING:-}\ - █▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█\n\ - NOTES for RESTORING PREVIOUS CONFIGS\n\ - █▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█\n\n\ - The 'UserConfigs' directory is for all your personal settings.\n\ - Files in this directory will override the default configurations,\n\ - so your customizations are not lost when you update.\n\ + printf "${WARNING:-}\\ + █▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█\\n\\ + NOTES for RESTORING PREVIOUS CONFIGS\\n\\ + █▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█\\n\\n\\ + The 'UserConfigs' directory is for all your personal settings.\\n\\ + Files in this directory will override the default configurations,\\n\\ + so your customizations are not lost when you update.\\n\\ " >&2 if version_gte "$CURRENT_VERSION" "$TARGET_VERSION"; then @@ -281,6 +425,19 @@ restore_user_configs() { done fi fi + + # Always run de-dupe based on the installed dotfiles version so that + # express mode and standard mode behave consistently. Prefer the + # pre-upgrade version (old_version) if provided so we still clean up + # legacy duplicates when upgrading to a newer release that no longer + # needs the fix. + local detected_version="$old_version" + if [ -z "$detected_version" ]; then + detected_version=$(get_installed_dotfiles_version) + fi + if [ -n "$detected_version" ]; then + cleanup_duplicate_userconfigs "$detected_version" "$log" + fi } restore_user_scripts() { diff --git a/scripts/lib_update.sh b/scripts/lib_update.sh index 0a70dff0..be0b8a0a 100644 --- a/scripts/lib_update.sh +++ b/scripts/lib_update.sh @@ -77,6 +77,20 @@ run_repo_update() { echo " Pull status : $( [ $pull_status -eq 0 ] && echo success || echo failure )" | tee -a "$log_file" echo "----------------------------------------" | tee -a "$log_file" + # Also run the UserConfigs duplicate cleanup for existing installs, + # using the same version gating as the main copy workflow (<= v2.3.19). + if declare -f get_installed_dotfiles_version >/dev/null 2>&1 \ + && declare -f cleanup_duplicate_userconfigs >/dev/null 2>&1; then + local installed_version + installed_version=$(get_installed_dotfiles_version) + if [ -n "$installed_version" ]; then + echo "${INFO:-[INFO]} Checking for duplicate UserConfigs entries after repo update (detected v$installed_version)..." | tee -a "$log_file" + cleanup_duplicate_userconfigs "$installed_version" "$log_file" + else + echo "${NOTE:-[NOTE]} Skipping UserConfigs duplicate cleanup; installed version could not be detected." | tee -a "$log_file" + fi + fi + read -n1 -s -r -p "Press any key to return to the main menu..." echo |
