summaryrefslogtreecommitdiff
path: root/bin/rcup.in
diff options
context:
space:
mode:
Diffstat (limited to 'bin/rcup.in')
-rwxr-xr-xbin/rcup.in188
1 files changed, 188 insertions, 0 deletions
diff --git a/bin/rcup.in b/bin/rcup.in
new file mode 100755
index 0000000..849a0f7
--- /dev/null
+++ b/bin/rcup.in
@@ -0,0 +1,188 @@
+#!@SHELL@
+
+: ${RCM_LIB:=$(dirname "$0")/../share/rcm}
+. "$RCM_LIB/rcm.sh"
+
+link_or_copy() {
+ $DEBUG "link_or_copy $1"
+ local sigil="$1"
+
+ if [ "x$sigil" = "xX" ]; then
+ echo "cp_v"
+ else
+ echo "$LN"
+ fi
+}
+
+link_file() {
+ local src="$1"
+ local dest="$2"
+ local sigil="$3"
+
+ if [ -h "$dest" ]; then
+ rm_v -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_v -rf "$dest"
+ link_file "$src" "$dest" "$sigil"
+}
+
+is_nested() {
+ echo "$1" | sed "s:$DEST_DIR/::" | grep -q '/'
+}
+
+is_identical() {
+ diff -q -s "$1" "$2" > /dev/null
+}
+
+handle_dir() {
+ local dest="$1"
+
+ $DEBUG "handle_dir $1"
+
+ dirname "$dest" | xargs $MKDIR -p
+}
+
+handle_file() {
+ local src="$1"
+ local dest="$2"
+ local sigil="$3"
+
+ $DEBUG "handle_file $1 $2 $3"
+
+ if [ -e "$dest" ]; then
+ if is_identical "$src" "$dest"; then
+ $VERBOSE "identical $dest"
+ 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 [-CVqvfhikK] [-I EXCL_PAT] [-x EXCL_PAT] [-t TAG] [-d DOT_DIR]"
+ $PRINT "see rcup(1) and rcm(5) 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=
+ REPLACE_ALL=0
+
+ while getopts CVqvfhikKI:x:S:t:d: opt; do
+ case "$opt" in
+ C) always_copy=1 ;;
+ d) dotfiles_dirs="$dotfiles_dirs $OPTARG" ;;
+ f) REPLACE_ALL=1 ;;
+ h) show_help ;;
+ i) REPLACE_ALL=0 ;;
+ I) includes="$includes $OPTARG" ;;
+ k) run_hooks=1 ;;
+ K) run_hooks=0 ;;
+ q) verbosity=$(($verbosity - 1)) ;;
+ t) arg_tags="$arg_tags $OPTARG" ;;
+ S) symlink_dirs="$symlink_dirs $OPTARG";;
+ v) verbosity=$(($verbosity + 1)) ;;
+ V) version=1 ;;
+ x) excludes="$excludes $OPTARG" ;;
+ esac
+ done
+ shift $(($OPTIND-1))
+
+ LN="ln_v"
+ if [ $always_copy -eq 1 ]; then
+ LN="cp_v"
+ fi
+
+ handle_common_flags rcup $version $verbosity
+
+ tags="${arg_tags:-$TAGS}"
+ DOTFILES_DIRS="${dotfiles_dirs:-$DOTFILES_DIRS}"
+ RUN_HOOKS=$run_hooks
+ files="$@"
+
+ 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
+ LS_ARGS="$LS_ARGS $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="$(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 "$src" "$dest" "$sigil"
+done
+
+run_hooks post up