feat(exp-update): add --default-choice option (#2915)

This commit is contained in:
Celestial.y
2026-01-23 08:06:39 +08:00
committed by GitHub
2 changed files with 148 additions and 118 deletions
+36 -29
View File
@@ -113,7 +113,16 @@ safe_read() {
echo -n "$prompt" echo -n "$prompt"
# Try to read from terminal with better detection # First, try reading from stdin (supports piped input like "yes 1 |")
if read -r -t 0.1 input_value 2>/dev/null; then
# Successfully read from stdin (piped input)
if [[ -n "$input_value" ]]; then
printf -v "$varname" '%s' "$input_value"
return 0
fi
fi
# If stdin had no data, try interactive terminal
if [[ -t 0 ]]; then if [[ -t 0 ]]; then
# stdin is a terminal # stdin is a terminal
read -r input_value read -r input_value
@@ -339,7 +348,14 @@ handle_file_conflict() {
local home_file="$2" local home_file="$2"
local filename=$(basename "$home_file") local filename=$(basename "$home_file")
local dirname=$(dirname "$home_file") local dirname=$(dirname "$home_file")
local choice=""
local default_val="${DEFAULT_CHOICE:-6}" # Use DEFAULT_CHOICE or 6 (skip) as fallback
# In non-interactive mode, use default directly (acts like pressing Enter)
if [[ "$NON_INTERACTIVE" == true ]]; then
choice="$default_val"
log_info "Using choice $choice for: $home_file"
else
echo -e "\n${STY_YELLOW}Conflict detected:${STY_RST} $home_file" echo -e "\n${STY_YELLOW}Conflict detected:${STY_RST} $home_file"
echo "Repository version differs from your local version." echo "Repository version differs from your local version."
echo echo
@@ -355,27 +371,34 @@ handle_file_conflict() {
echo echo
while true; do while true; do
if ! safe_read "Enter your choice (1-8): " choice "6"; then if ! safe_read "Enter your choice (1-8 or name) [${default_val}]: " choice "$default_val"; then
echo echo
log_warning "Failed to read input. Skipping file." log_warning "Failed to read input. Skipping file."
return return
fi fi
# Validate choice
if [[ "$choice" =~ ^[1-8]$ ]] || [[ "$choice" =~ ^(replace|keep|old|new|diff|skip|ignore|backup)$ ]]; then
break
else
echo "Invalid choice. Please enter 1-8 or a valid name (replace, keep, old ...)."
fi
done
fi
case $choice in case $choice in
1) 1|replace)
if [[ "$DRY_RUN" == true ]]; then if [[ "$DRY_RUN" == true ]]; then
log_info "[DRY-RUN] Would replace $home_file with repository version" log_info "[DRY-RUN] Would replace $home_file with repository version"
else else
cp -p "$repo_file" "$home_file" cp -p "$repo_file" "$home_file"
log_success "Replaced $home_file with repository version" log_success "Replaced $home_file with repository version"
fi fi
break
;; ;;
2) 2|keep)
log_info "Keeping local version of $home_file" log_info "Keeping local version of $home_file"
break
;; ;;
3) 3|old)
if [[ "$DRY_RUN" == true ]]; then if [[ "$DRY_RUN" == true ]]; then
log_info "[DRY-RUN] Would backup local file to ${filename}.old and update with repository version" log_info "[DRY-RUN] Would backup local file to ${filename}.old and update with repository version"
else else
@@ -383,18 +406,16 @@ handle_file_conflict() {
cp -p "$repo_file" "$home_file" cp -p "$repo_file" "$home_file"
log_success "Backed up local file to ${filename}.old and updated with repository version" log_success "Backed up local file to ${filename}.old and updated with repository version"
fi fi
break
;; ;;
4) 4|new)
if [[ "$DRY_RUN" == true ]]; then if [[ "$DRY_RUN" == true ]]; then
log_info "[DRY-RUN] Would save repository version as ${filename}.new, keep local file" log_info "[DRY-RUN] Would save repository version as ${filename}.new, keep local file"
else else
cp -p "$repo_file" "${dirname}/${filename}.new" cp -p "$repo_file" "${dirname}/${filename}.new"
log_success "Saved repository version as ${filename}.new, kept local file" log_success "Saved repository version as ${filename}.new, kept local file"
fi fi
break
;; ;;
5) 5|diff)
show_diff "$home_file" "$repo_file" show_diff "$home_file" "$repo_file"
echo echo
echo "After reviewing the diff, choose:" echo "After reviewing the diff, choose:"
@@ -420,11 +441,9 @@ handle_file_conflict() {
cp -p "$repo_file" "$home_file" cp -p "$repo_file" "$home_file"
log_success "Replaced $home_file with repository version" log_success "Replaced $home_file with repository version"
fi fi
break
;; ;;
k) k)
log_info "Keeping local version of $home_file" log_info "Keeping local version of $home_file"
break
;; ;;
b) b)
if [[ "$DRY_RUN" == true ]]; then if [[ "$DRY_RUN" == true ]]; then
@@ -434,7 +453,6 @@ handle_file_conflict() {
cp -p "$repo_file" "$home_file" cp -p "$repo_file" "$home_file"
log_success "Backed up local file to ${filename}.old and updated" log_success "Backed up local file to ${filename}.old and updated"
fi fi
break
;; ;;
n) n)
if [[ "$DRY_RUN" == true ]]; then if [[ "$DRY_RUN" == true ]]; then
@@ -443,11 +461,9 @@ handle_file_conflict() {
cp -p "$repo_file" "${dirname}/${filename}.new" cp -p "$repo_file" "${dirname}/${filename}.new"
log_success "Saved repository version as ${filename}.new" log_success "Saved repository version as ${filename}.new"
fi fi
break
;; ;;
s) s)
log_info "Skipping $home_file" log_info "Skipping $home_file"
break
;; ;;
i) i)
local relative_path_to_home="${home_file#$HOME/}" local relative_path_to_home="${home_file#$HOME/}"
@@ -457,7 +473,6 @@ handle_file_conflict() {
echo "$relative_path_to_home" >>"$XDG_UPDATE_IGNORE_FILE" echo "$relative_path_to_home" >>"$XDG_UPDATE_IGNORE_FILE"
log_success "Added '$relative_path_to_home' to $XDG_UPDATE_IGNORE_FILE and skipped." log_success "Added '$relative_path_to_home' to $XDG_UPDATE_IGNORE_FILE and skipped."
fi fi
break
;; ;;
B) B)
if backup_file "$home_file"; then if backup_file "$home_file"; then
@@ -466,18 +481,16 @@ handle_file_conflict() {
log_success "Replaced $home_file with repository version" log_success "Replaced $home_file with repository version"
fi fi
fi fi
break
;; ;;
*) *)
echo "Invalid choice. Please try again." log_info "Skipping $home_file"
;; ;;
esac esac
;; ;;
6) 6|skip)
log_info "Skipping $home_file" log_info "Skipping $home_file"
break
;; ;;
7) 7|ignore)
local relative_path_to_home="${home_file#$HOME/}" local relative_path_to_home="${home_file#$HOME/}"
if [[ "$DRY_RUN" == true ]]; then if [[ "$DRY_RUN" == true ]]; then
log_info "[DRY-RUN] Would add '$relative_path_to_home' to $XDG_UPDATE_IGNORE_FILE" log_info "[DRY-RUN] Would add '$relative_path_to_home' to $XDG_UPDATE_IGNORE_FILE"
@@ -485,22 +498,16 @@ handle_file_conflict() {
echo "$relative_path_to_home" >>"$XDG_UPDATE_IGNORE_FILE" echo "$relative_path_to_home" >>"$XDG_UPDATE_IGNORE_FILE"
log_success "Added '$relative_path_to_home' to $XDG_UPDATE_IGNORE_FILE and skipped." log_success "Added '$relative_path_to_home' to $XDG_UPDATE_IGNORE_FILE and skipped."
fi fi
break
;; ;;
8) 8|backup)
if backup_file "$home_file"; then if backup_file "$home_file"; then
if [[ "$DRY_RUN" != true ]]; then if [[ "$DRY_RUN" != true ]]; then
cp -p "$repo_file" "$home_file" cp -p "$repo_file" "$home_file"
log_success "Replaced $home_file with repository version" log_success "Replaced $home_file with repository version"
fi fi
fi fi
break
;;
*)
echo "Invalid choice. Please enter 1-8."
;; ;;
esac esac
done
} }
# Function to check if PKGBUILD has changed # Function to check if PKGBUILD has changed
+25 -2
View File
@@ -15,7 +15,10 @@ Options:
-h, --help Show this help message -h, --help Show this help message
-s, --skip-notice Skip notice about script being untested -s, --skip-notice Skip notice about script being untested
--non-interactive --non-interactive
Run without prompting for user input Set default choice for file conflicts
replace: Replace local keep: Keep local old: Backup as .old
new: Save as .new diff: Show diff skip: Skip
ignore: Add to ignore backup: Backup and replace
This script updates your dotfiles by: This script updates your dotfiles by:
1. Auto-detecting repository structure (dots/ prefix or direct) 1. Auto-detecting repository structure (dots/ prefix or direct)
@@ -35,7 +38,7 @@ Ignore file patterns support:
# `man getopt` to see more # `man getopt` to see more
para=$(getopt \ para=$(getopt \
-o hfpnvs \ -o hfpnvs \
-l help,force,packages,dry-run,verbose,skip-notice,non-interactive \ -l help,force,packages,dry-run,verbose,skip-notice,non-interactive,default-choice: \
-n "$0" -- "$@") -n "$0" -- "$@")
[ $? != 0 ] && echo "$0: Error when getopt, please recheck parameters." && exit 1 [ $? != 0 ] && echo "$0: Error when getopt, please recheck parameters." && exit 1
##################################################################################### #####################################################################################
@@ -58,6 +61,7 @@ DRY_RUN=false
VERBOSE=false VERBOSE=false
SKIP_NOTICE=false SKIP_NOTICE=false
NON_INTERACTIVE=false NON_INTERACTIVE=false
DEFAULT_CHOICE=""
eval set -- "$para" eval set -- "$para"
while true ; do while true ; do
@@ -81,6 +85,25 @@ while true ; do
--non-interactive) NON_INTERACTIVE=true;shift --non-interactive) NON_INTERACTIVE=true;shift
log_info "Non-interactive mode enabled" log_info "Non-interactive mode enabled"
;; ;;
--default-choice)
case "$2" in
replace) DEFAULT_CHOICE="1" ;;
keep) DEFAULT_CHOICE="2" ;;
old) DEFAULT_CHOICE="3" ;;
new) DEFAULT_CHOICE="4" ;;
diff) DEFAULT_CHOICE="5" ;;
skip) DEFAULT_CHOICE="6" ;;
ignore) DEFAULT_CHOICE="7" ;;
backup) DEFAULT_CHOICE="8" ;;
*)
log_error "Invalid --default-choice value: $2"
log_error "Valid values: replace, keep, old, new, diff, skip, ignore, backup"
exit 1
;;
esac
shift 2
log_info "Default conflict choice set to: $DEFAULT_CHOICE"
;;
## Ending ## Ending
--) break ;; --) break ;;