#!@SHELL@ : ${RCM_LIB:=$(dirname "$0")/../share/rcm} . "$RCM_LIB/rcm.sh" print_ln_v() { $PRINT "handle_file_ln \"$1\" \"$2\"" } print_cp_v() { $PRINT "handle_file_cp \"$1\" \"$2\"" } print_rm_v() { : } link_or_copy() { $DEBUG "link_or_copy $1" local sigil="$1" if [ "x$sigil" = "xX" ]; then echo "$CP" else echo "$LN" fi } print_generated_preface() { cat < '\$2'" \$MKDIR -p "\$(\$DIRNAME "\$2")" \$CP -R "\$1" "\$2" } handle_file_ln() { if [ -e "\$2" ]; then printf "%s " "overwrite \$2? [yN]" read overwrite case "\$overwrite" in y) \$RM -rf "\$2" ;; *) echo "skipping \$2" return ;; esac fi verbose "'\$1' -> '\$2'" \$MKDIR -p "\$(\$DIRNAME "\$2")" \$LN -sf "\$1" "\$2" } PREFACE } link_file() { local src="$1" local dest="$2" local sigil="$3" if [ -h "$dest" ]; then $RM -f "$dest" fi action="$(link_or_copy "$sigil")" $DEBUG "$action $src $dest" $action "$src" "$dest" } replace_file() { local src="$1" local dest="$2" local sigil="$3" $DEBUG replace_file "$1" "$2" $3 $RM -rf "$dest" link_file "$src" "$dest" "$sigil" } is_identical() { diff -c "$1" "$2" > /dev/null 2>&1 } is_linked() { local src="$1" local dest="$2" if [ -h "$dest" ]; then local link_dest=$(readlink $dest) [ "$link_dest" = "$src" ] else return 1 fi } handle_dir() { local dest="$1" $DEBUG "handle_dir $dest" $MKDIR -p "$(dirname "$dest")" } handle_file() { local generate="$1" local src="$2" local dest="$3" local sigil="$4" $DEBUG "handle_file $1 $2 $3 $4" if [ "$generate" -ne 1 -a -e "$dest" ]; then if is_identical "$src" "$dest"; then if [ "x$sigil" != "xX" ] && ! is_linked "$src" "$dest"; then $VERBOSE "replacing identical but unlinked $dest" replace_file "$src" "$dest" "$sigil" else $VERBOSE "identical $dest" fi elif [ $REPLACE_ALL -eq 1 ]; then replace_file "$src" "$dest" "$sigil" else $PROMPT "overwrite ${dest}? [ynaq]" read overwrite case "$overwrite" in a) REPLACE_ALL=1 replace_file "$src" "$dest" "$sigil" ;; y) replace_file "$src" "$dest" "$sigil" ;; q) exit 1 ;; *) $VERBOSE "skipping $dest" ;; esac fi else link_file "$src" "$dest" "$sigil" fi } show_help() { local exit_code=${1:-0} $PRINT "Usage: rcup [-CfhiKkqVv] [-B HOSTNAME] [-d DOT_DIR] [-I EXCL_PAT] [-S EXCL_PAT] [-s EXCL_PAT] [-t TAG] [-U EXCL_PAT] [-u EXCL_PAT] [-x EXCL_PAT]" $PRINT "see rcup(1) and rcm(7) for more details" exit $exit_code } handle_command_line() { local arg_tags= local verbosity=0 local version=0 local run_hooks=1 local dotfiles_dirs= local files= local excludes= local includes= local always_copy=0 local symlink_dirs= local never_symlink_dirs= local hostname= local generate=0 local args="$*" local undotted= local never_undotted= REPLACE_ALL=0 GENERATE= while getopts :CVqvfghikKI:x:S:s:U:u:t:d:B: opt; do case "$opt" in B) hostname="$OPTARG" ;; C) always_copy=1 ;; d) dotfiles_dirs="$(append_variable "$dotfiles_dirs" "$OPTARG")" ;; f) REPLACE_ALL=1 ;; g) generate=1 ;; h) show_help ;; i) REPLACE_ALL=0 ;; I) includes="$(append_variable "$includes" "$OPTARG")" ;; k) run_hooks=1 ;; K) run_hooks=0 ;; q) verbosity=$(($verbosity - 1)) ;; t) arg_tags="$(append_variable "$arg_tags" "$OPTARG")" ;; S) symlink_dirs="$(append_variable "$symlink_dirs" "$OPTARG")" ;; s) never_symlink_dirs="$(append_variable "$never_symlink_dirs" "$OPTARG")";; U) undotted="$(append_variable "$undotted" "$OPTARG")" ;; u) never_undotted="$(append_variable "$never_undotted" "$OPTARG")" ;; v) verbosity=$(($verbosity + 1)) ;; V) version=1 ;; x) excludes="$(append_variable "$excludes" "$OPTARG")" ;; ?) show_help 64 ;; esac done shift $(($OPTIND-1)) LN="ln_v" CP="cp_v" RM="rm_v" if [ $always_copy -eq 1 ]; then LN="$CP" fi if [ "$generate" -eq 1 ]; then LN="print_ln_v" CP="print_cp_v" RM="print_rm_v" print_generated_preface $args fi GENERATE="$generate" handle_common_flags rcup $version $verbosity hostname="$(determine_hostname "$hostname")" tags="${arg_tags:-$TAGS}" DOTFILES_DIRS="${dotfiles_dirs:-$DOTFILES_DIRS}" RUN_HOOKS=$run_hooks files= for file; do files="$files $(encode "$file")" done for tag in $tags; do LS_ARGS="$LS_ARGS -t \"$tag\"" done for dotfiles_dir in "$DOTFILES_DIRS"; do LS_ARGS="$LS_ARGS -d \"$dotfiles_dir\"" done for exclude in "$excludes"; do LS_ARGS="$LS_ARGS -x \"$exclude\"" done for include in "$includes"; do LS_ARGS="$LS_ARGS -I \"$include\"" done for symlink_dir in "$symlink_dirs"; do LS_ARGS="$LS_ARGS -S \"$symlink_dir\"" done for never_symlink_dir in "$never_symlink_dirs"; do LS_ARGS="$LS_ARGS -s \"$never_symlink_dir\"" done for undot in "$undotted"; do LS_ARGS="$LS_ARGS -U \"$undot\"" done for never_undot in "$never_undotted"; do LS_ARGS="$LS_ARGS -u \"$never_undot\"" done LS_ARGS="$LS_ARGS -B \"$hostname\" $files" $DEBUG "LS_ARGS: $LS_ARGS" } LS_ARGS=-F handle_command_line "$@" : ${DOTFILES_DIRS:=$DOTFILES_DIRS $DEFAULT_DOTFILES_DIR} run_hooks pre up dests_and_srcs="$(eval "lsrc $LS_ARGS")" saved_ifs="$IFS" IFS=' ' for dest_and_src in $dests_and_srcs; do IFS=: set -- $dest_and_src IFS="$saved_ifs" dest="$1" src="$2" sigil="$3" if is_nested "$dest"; then handle_dir "$dest" fi handle_file "$GENERATE" "$src" "$dest" "$sigil" done IFS="$saved_ifs" run_hooks post up