Update backup logic in 3.files-exp.sh

This commit is contained in:
clsty
2025-10-30 09:00:11 +08:00
parent 649be3741c
commit bd8daf4015
+31 -184
View File
@@ -24,200 +24,47 @@ function warning_rsync_normal(){
printf "${STY_RST}"
}
function backup_clashing_targets(){
# For dirs/files under target_dir, only backup those which clashes with the ones under source_dir
# Deal with arguments
local source_dir="$1"
local target_dir="$2"
local backup_dir="$3"
# Find clash dirs/files, save as clash_list
local clash_list=()
local source_list=($(ls -A "$source_dir"))
local target_list=($(ls -A "$target_dir"))
declare -A target_map
for i in "${target_list[@]}"; do
target_map["$i"]=1
done
for i in "${source_list[@]}"; do
if [[ -n "${target_map[$i]}" ]]; then
clash_list+=("$i")
fi
done
# Construct args_includes for rsync
for i in "${clash_list[@]}"; do
current_target=$target_dir/$i
if [[ -d $current_target ]]; then
args_includes+=(--include="$current_target/")
args_includes+=(--include="$current_target/**")
else
args_includes+=(--include="$current_target")
fi
done
args_includes+=(--exclude="*")
x mkdir -p $backup_dir
x rsync -av --progress "${args_includes[@]}" "$target_dir/" "$backup_dir/"
function backup_configs(){
backup_clashing_targets dots/.config $XDG_CONFIG_HOME "${BACKUP_DIR}/.config"
backup_clashing_targets dots/.local/share $XDG_DATA_HOME "${BACKUP_DIR}/.local/share"
printf "${STY_BLUE}Backup into \"${BACKUP_DIR}\" finished.${STY_RST}\n"
}
function ask_backup_configs(){
showfun backup_clashing_targets
printf "${STY_RED}"
printf "Would you like to backup clashing dirs/files under \"$XDG_CONFIG_HOME\" and \"$XDG_DATA_HOME\" to \"$BACKUP_DIR\"?"
read -p "[y/N] " backup_confirm
case $backup_confirm in
[yY][eE][sS]|[yY])
showfun backup_clashing_targets
v backup_clashing_targets dots/.config $XDG_CONFIG_HOME "${BACKUP_DIR}/.config"
v backup_clashing_targets dots/.local/share $XDG_DATA_HOME "${BACKUP_DIR}/.local/share"
;;
*) echo "Skipping backup..." ;;
esac
printf "${STY_RST}"
while true;do
echo " y = Yes, backup"
echo " n/s = No, skip to next"
local p; read -p "====> " p
case $p in
[yY]) echo -e "${STY_BLUE}OK, doing backup...${STY_RST}" ;local backup=true;break ;;
[nNsS]) echo -e "${STY_BLUE}Alright, skipping...${STY_RST}" ;local backup=false;break ;;
*) echo -e "${STY_RED}Please enter [y/n].${STY_RST}";;
esac
done
if $backup;then backup_configs;fi
}
function auto_backup_configs(){
# Backup when $BACKUP_DIR does not exist
if [[ ! -d "$BACKUP_DIR" ]]; then backup_configs;fi
}
# =============================================================================
# CONFIGURATION FUNCTIONS
# =============================================================================
#####################################################################################
showfun auto_get_git_submodule
v auto_get_git_submodule
# User preference wizard
wizard_update_preferences() {
echo -e "${STY_CYAN}=== Dotfiles Customization ===${STY_RESET}"
# Get current preferences
current_shell=$(yq '.user_preferences.shell // "fish"' "$CONFIG_FILE")
current_terminal=$(yq '.user_preferences.terminal // "kitty"' "$CONFIG_FILE")
current_keybindings=$(yq '.user_preferences.keybindings // "default"' "$CONFIG_FILE")
echo "Current preferences:"
echo " Shell: $current_shell"
echo " Terminal: $current_terminal"
echo " Keybindings: $current_keybindings"
echo
# Shell selection
echo "Which shell do you prefer?"
echo "1) fish (default)"
echo "2) zsh"
read -p "Enter choice [1-2]: " shell_choice
case "$shell_choice" in
1|"") shell="fish" ;;
2) shell="zsh" ;;
*) echo "Invalid choice, using fish"; shell="fish" ;;
esac
# Terminal selection
echo
echo "Which terminal do you prefer?"
echo "1) kitty (default)"
echo "2) foot"
read -p "Enter choice [1-2]: " terminal_choice
case "$terminal_choice" in
1|"") terminal="kitty" ;;
2) terminal="foot" ;;
*) echo "Invalid choice, using kitty"; terminal="kitty" ;;
esac
# Keybindings selection
echo
echo "Which keybinding style do you prefer?"
echo "1) default (arrow keys)"
echo "2) vim (H/J/K/L)"
read -p "Enter choice [1-2]: " keybind_choice
case "$keybind_choice" in
1|"") keybindings="default" ;;
2) keybindings="vim" ;;
*) echo "Invalid choice, using default"; keybindings="default" ;;
esac
# Update YAML in-place
yq -i ".user_preferences.shell = \"$shell\"" "$CONFIG_FILE"
yq -i ".user_preferences.terminal = \"$terminal\"" "$CONFIG_FILE"
yq -i ".user_preferences.keybindings = \"$keybindings\"" "$CONFIG_FILE"
echo
echo "Preferences updated!"
}
# In case some dirs does not exists
v mkdir -p $XDG_BIN_HOME $XDG_CACHE_HOME $XDG_CONFIG_HOME $XDG_DATA_HOME/icons
# Get user preference
get_pref() {
yq -r ".user_preferences.$1" "$CONFIG_FILE"
}
# Check if pattern should be processed based on user preferences
should_process_pattern() {
local pattern="$1"
local condition=$(echo "$pattern" | yq '.condition // "true"')
# If no condition or condition is "true", always process
if [[ "$condition" == "true" ]]; then
return 0
fi
# Extract the preference type and value from condition
local type=$(echo "$condition" | yq '.type')
local value=$(echo "$condition" | yq '.value')
[[ "$(get_pref "$type")" == "$value" ]]
}
# Compare hashes of files/directories, return true if they are the same, false otherwise
files_are_same() {
local path1="$1"
local path2="$2"
# Check if paths exist
if [[ ! -e "$path1" || ! -e "$path2" ]]; then
return 1
fi
# For directories, use find + md5sum to compare recursively
# For files, use md5sum directly
if [[ -d "$path1" && -d "$path2" ]]; then
# Compare directory contents using find and md5sum
local hash1=$(find "$path1" -type f -exec md5sum {} \; | sort -k 2 | md5sum | awk '{print $1}')
local hash2=$(find "$path2" -type f -exec md5sum {} \; | sort -k 2 | md5sum | awk '{print $1}')
[[ "$hash1" == "$hash2" ]]
elif [[ -f "$path1" && -f "$path2" ]]; then
# Compare file hashes
local hash1=$(md5sum "$path1" | awk '{print $1}')
local hash2=$(md5sum "$path2" | awk '{print $1}')
[[ "$hash1" == "$hash2" ]]
else
# One is a file, one is a directory - different types
return 1
fi
}
# Find next backup number
get_next_backup_number() {
local base_path="$1"
local counter=1
while [[ -e "${base_path}.old.${counter}" ]]; do
((counter++))
done
echo $counter
}
# =============================================================================
# MAIN EXECUTION
# =============================================================================
# Ensure directories exist
v mkdir -p $XDG_BIN_HOME $XDG_CACHE_HOME $XDG_CONFIG_HOME $XDG_DATA_HOME
# Handle backup
case $ask in
false) sleep 0 ;;
*) ask_backup_configs ;;
esac
if [[ ! "${SKIP_BACKUP}" == true ]]; then
case $ask in
false) auto_backup_configs ;;
*) ask_backup_configs ;;
esac
fi
# Run user preference wizard
case $ask in