From 8d7f6c94a3458328b339b6582592b6c1fecec950 Mon Sep 17 00:00:00 2001 From: Mike Burns Date: Sun, 11 Aug 2013 17:29:01 +0200 Subject: Add the COPY_ALWAYS option The suite now honors the `COPY_ALWAYS` option in rcrc(5). This can be set to a space-separated list of file globs. Any file matching a glob is copied instead of symlinked. This is handy both for secure programs (`netrc`, `ssh/id_*`) and for programs that oddly re-write files (`weechat/*`). To always copy everything, use the `*` glob. This is reflected throughout the suite as follows: * lsrc now has a `-F` option which shows a symbol to indicate whether it is a symlink (`@`) or a copy (`X`). * rcdn only removes symlinks unless the file under question matches a `COPY_ALWAYS` glob, in which case it is removed regardless of whether it is a symlink. * rcup will copy instead of symlinking any file that matches any `COPY_ALWAYS` glob. --- bin/lsrc | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++------------- bin/rcdn | 15 +++++++--- bin/rcup | 47 +++++++++++++++++++++++-------- 3 files changed, 123 insertions(+), 35 deletions(-) (limited to 'bin') diff --git a/bin/lsrc b/bin/lsrc index 880bf05..f7f4826 100755 --- a/bin/lsrc +++ b/bin/lsrc @@ -29,37 +29,88 @@ build_path() { fi } -link_dir() { +file_join() { + local result= + + for file; do + if [ "x$file" != "x." ]; then + if [ "x$result" = "x" ]; then + result=$file + else + result="$result/$file" + fi + fi + done + + echo $result +} + +show_dir() { local dir=$1 local dest_dir=$2 local dotfiles_dir=$3 - local dotted=$4 - local exclude_file_globs="$5" - local include_file_globs="$6" + local dotfiles_subdir=$4 + local dotted=$5 + local exclude_file_globs="$6" + local include_file_globs="$7" local dest_path=`build_path $dest_dir $dir $dotted` - $DEBUG "link_dir $1 $2 $3 $4 $5 $6" + $DEBUG "show_dir $1 $2 $3 $4 $5 $6 $7" $VERBOSE "recurring on $dest_path" pushdir $dir for f in *; do $DEBUG "handling the file $f" - handle_file $f $dest_path $dotfiles_dir/$dir 1 "$exclude_file_globs" "$include_file_globs" + next_dir=`file_join $dotfiles_subdir $dir` + handle_file $f $dest_path $dotfiles_dir $next_dir 1 "$exclude_file_globs" "$include_file_globs" done popdir } -link_file() { +sigil_for() { + local file=$1 + local copy_always=0 + + for copy_file in $COPY_ALWAYS; do + $DEBUG "copy_file: $copy_file" + $DEBUG "file: $file" + + case $file in + $copy_file) + copy_always=1 + break + ;; + esac + done + + if [ $copy_always -eq 1 ]; then + echo 'X' + else + echo '@' + fi +} + +show_file() { local file=$1 local dest_dir=$2 local dotfiles_dir=$3 - local dotted=$4 + local dotfiles_subdir=$4 + local dotted=$5 local dest_file=`build_path $dest_dir $file $dotted` if echo $DEST_STACK | grep -vq ":$dest_file"; then DEST_STACK="$DEST_STACK:$dest_file" - $PRINT $dest_file:$dotfiles_dir/$file + src_file=`file_join $dotfiles_subdir $file` + abs_src_file=`file_join $dotfiles_dir $src_file` + output=$dest_file:$abs_src_file + + if [ $SHOW_SIGILS -eq 1 ]; then + sigil=`sigil_for $src_file` + output="$output:$sigil" + fi + + $PRINT $output fi } @@ -67,20 +118,21 @@ handle_file() { local file=$1 local dest_dir=$2 local dotfiles_dir=$3 - local dotted=$4 - local exclude_file_globs="$5" - local include_file_globs="$6" + local dotfiles_subdir=$4 + local dotted=$5 + local exclude_file_globs="$6" + local include_file_globs="$7" - $DEBUG "handle_file $1 $2 $3 $4 $5 $6" + $DEBUG "handle_file $1 $2 $3 $4 $5 $6 $7" if [ ! -e $file ]; then $VERBOSE "skipping non-existent file $file" elif is_excluded $file "$exclude_file_globs" "$include_file_globs"; then $VERBOSE "skipping excluded file $file" elif [ -d $file ]; then - link_dir $file $dest_dir $dotfiles_dir $dotted "$exclude_file_globs" "$include_file_globs" + show_dir $file $dest_dir $dotfiles_dir $dotfiles_subdir $dotted "$exclude_file_globs" "$include_file_globs" else - link_file $file $dest_dir $dotfiles_dir $dotted + show_file $file $dest_dir $dotfiles_dir $dotfiles_subdir $dotted fi } @@ -147,12 +199,14 @@ handle_command_line() { local arg_tags= local verbosity=0 local version=0 + local show_sigils=0 local dotfiles_dirs= local excludes= local includes= - while getopts VqvI:x:t:d: opt; do + while getopts FVqvI:x:t:d: opt; do case "$opt" in + F) show_sigils=1;; I) includes="$includes $OPTARG";; t) arg_tags="$arg_tags $OPTARG";; v) verbosity=$(($verbosity + 1));; @@ -165,6 +219,7 @@ handle_command_line() { shift $(($OPTIND-1)) handle_common_flags lsrc $version $verbosity + SHOW_SIGILS=$show_sigils TAGS=${arg_tags:-$TAGS} DOTFILES_DIRS=${dotfiles_dirs:-$DOTFILES_DIRS} EXCLUDES=${excludes:-$EXCLUDES} @@ -186,6 +241,9 @@ handle_command_line $* : ${DOTFILES_DIRS:=$DOTFILES_DIRS $DEFAULT_DOTFILES_DIR} $DEBUG "DOTFILES_DIRS: $DOTFILES_DIRS" +: ${COPY_ALWAYS:=""} +$DEBUG "COPY_ALWAYS: $COPY_ALWAYS" + for DOTFILES_DIR in $DOTFILES_DIRS; do if is_relative $DOTFILES_DIR; then DOTFILES_DIR=$PWD/$DOTFILES_DIR @@ -208,7 +266,7 @@ for DOTFILES_DIR in $DOTFILES_DIRS; do continue fi - handle_file $file $DEST_DIR $DOTFILES_DIR 0 "$exclude_file_globs" "$include_file_globs" + handle_file $file $DEST_DIR $DOTFILES_DIR . 0 "$exclude_file_globs" "$include_file_globs" done cd $DOTFILES_DIR @@ -217,7 +275,7 @@ for DOTFILES_DIR in $DOTFILES_DIRS; do if [ -d $host_files ]; then pushdir `basename $host_files` for file in ${FILES:-*}; do - handle_file $file $DEST_DIR $host_files 0 "$exclude_file_globs" "$include_file_globs" + handle_file $file $DEST_DIR $host_files . 0 "$exclude_file_globs" "$include_file_globs" done popdir fi @@ -229,7 +287,7 @@ for DOTFILES_DIR in $DOTFILES_DIRS; do pushdir `basename tag-$tag` for file in ${FILES:-*}; do $DEBUG "TAG: $tag, exclude_file_globs: $exclude_file_globs" - handle_file $file $DEST_DIR $DOTFILES_DIR/tag-$tag 0 "$exclude_file_globs" "$include_file_globs" + handle_file $file $DEST_DIR $DOTFILES_DIR/tag-$tag . 0 "$exclude_file_globs" "$include_file_globs" done popdir fi diff --git a/bin/rcdn b/bin/rcdn index df882e8..d809796 100755 --- a/bin/rcdn +++ b/bin/rcdn @@ -6,10 +6,11 @@ remove_link() { local dest=$1 local original=$2 + local sigil=$3 if [ x$dest = "x/" ]; then $VERBOSE "not a symlink, skipping: $original" - elif [ -L $dest ]; then + elif [ -L $dest -o "x$sigil" = "xX" ]; then $RM -rf $dest rmdir -p `dirname $original` 2>/dev/null else @@ -62,6 +63,8 @@ handle_command_line() { $DEBUG "LS_ARGS: $LS_ARGS" } +LS_ARGS=-F + if [ -e $HOME/.rcrc ]; then . $HOME/.rcrc fi @@ -69,8 +72,12 @@ fi handle_command_line $* for dest_and_src in `lsrc $LS_ARGS`; do - dest=`echo $dest_and_src | sed 's/:.*//'` - src=`echo $dest_and_src | sed 's/.*://'` + saved_ifs=$IFS + IFS=: + set $dest_and_src + IFS=$saved_ifs + dest=$1 + sigil=$3 - remove_link $dest $dest + remove_link $dest $dest $sigil done diff --git a/bin/rcup b/bin/rcup index af7a012..5f51192 100755 --- a/bin/rcup +++ b/bin/rcup @@ -3,25 +3,40 @@ : ${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 + else + echo $LN + fi +} + link_file() { local src=$1 local dest=$2 + local sigil=$3 if [ -h $dest ]; then $RM -f $dest fi - $LN $src $dest + 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 + $DEBUG replace_file $1 $2 $3 $RM -rf $dest - link_file $src $dest + link_file $src $dest $sigil } is_nested() { @@ -44,28 +59,29 @@ handle_dir() { handle_file() { local src=$1 local dest=$2 + local sigil=$3 - $DEBUG handle_file $1 $2 + $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 + replace_file $src $dest $sigil else $PROMPT "overwrite ${dest}? [ynaq]" read overwrite case $overwrite in a) REPLACE_ALL=1 - replace_file $src $dest + replace_file $src $dest $sigil ;; - y) replace_file $src $dest ;; + y) replace_file $src $dest $sigil ;; q) exit 1 ;; *) $VERBOSE "skipping $dest" ;; esac fi else - link_file $src $dest + link_file $src $dest $sigil fi } @@ -97,7 +113,7 @@ handle_command_line() { shift $(($OPTIND-1)) if [ $always_copy -eq 1 ]; then - LN=cp + LN=$CP fi handle_common_flags rcup $version $verbosity @@ -123,6 +139,8 @@ handle_command_line() { $DEBUG "LS_ARGS: $LS_ARGS" } +LS_ARGS=-F + if [ -e $HOME/.rcrc ]; then . $HOME/.rcrc fi @@ -130,12 +148,17 @@ fi handle_command_line $* for dest_and_src in `lsrc $LS_ARGS`; do - dest=`echo $dest_and_src | sed 's/:.*//'` - src=`echo $dest_and_src | sed 's/.*://'` + saved_ifs=$IFS + 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 + handle_file $src $dest $sigil done -- cgit v1.2.3