From 147a7b66554b2b13bcbf6fec1204e0cc0a1790bf Mon Sep 17 00:00:00 2001 From: Mike Burns and Eric Collins Date: Fri, 23 Dec 2016 16:18:40 -0500 Subject: Handle spaces in dotfile name In mkrc, separate the list of files with newlines instead of spaces. Change the `$IFS` when iterating to handle this. We hand the file off to rcup, which encodes the file name by replacing spaces with the bell character (`\a`). rcup then sends the file name off to lsrc, which decodes the bell back into a space. The test makes sure an `a` character is in the filename, in case some encoding goes wrong. We use tr(1) instead of sed(1) because tr(1) handles `\a`. Shoutout to Sublime Text 3 for forcing this issue. --- Makefile.am | 2 ++ NEWS.md.in | 1 + bin/lsrc.in | 9 ++++++--- bin/mkrc.in | 9 ++++++++- bin/rcup.in | 5 ++++- share/rcm.sh.in | 14 ++++++++++++++ test/lsrc-spaces.t | 8 ++++++++ test/mkrc-spaces.t | 30 ++++++++++++++++++++++++++++++ 8 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 test/lsrc-spaces.t create mode 100644 test/mkrc-spaces.t diff --git a/Makefile.am b/Makefile.am index fd760ad..149db29 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,7 @@ TESTS = \ test/lsrc-sigils.t \ test/lsrc.t \ test/lsrc-symlink-dirs.t \ + test/lsrc-spaces.t \ test/lsrc-tags.t \ test/lsrc-usage.t \ test/lsrc-undotted.t \ @@ -24,6 +25,7 @@ TESTS = \ test/mkrc-host-file.t \ test/mkrc-hostname.t \ test/mkrc-simple-output.t \ + test/mkrc-spaces.t \ test/mkrc-symlink-dirs.t \ test/mkrc-tagged-file.t \ test/mkrc-usage.t \ diff --git a/NEWS.md.in b/NEWS.md.in index 8f6b8a1..e6d4f72 100644 --- a/NEWS.md.in +++ b/NEWS.md.in @@ -1,5 +1,6 @@ rcm (@PACKAGE_VERSION@) unstable; urgency=low + * BUGFIX: Handle dotfile names with spaces in them (Eric Collins, Mike Burns). * BUGFIX: Relative exclude globs now work (Eric Collins, Mike Burns). * BUGFIX: Use $LOGNAME instead of $USER for compatibility (Mike Burns). * BUGFIX: rcdn(1) stops at DEST_DIR (Kyle Cook, Mike Burns). diff --git a/bin/lsrc.in b/bin/lsrc.in index 8fb1fcd..b0dc30a 100755 --- a/bin/lsrc.in +++ b/bin/lsrc.in @@ -347,7 +347,8 @@ for DOTFILES_DIR in $DOTFILES_DIRS; do host_files="$DOTFILES_DIR/host-$HOSTNAME" if [ -d "$host_files" ]; then pushdir "$(basename "$host_files")" - for file in ${FILES:-*}; do + for escaped_file in ${FILES:-*}; do + file="$(decode "$escaped_file")" dotted=0 if is_excluded "$file" "$undotted_file_globs" "$never_undotted_file_globs"; then dotted=1 @@ -363,7 +364,8 @@ for DOTFILES_DIR in $DOTFILES_DIRS; do for tag in $TAGS; do if [ -d "tag-$tag" ]; then pushdir "$(basename "tag-$tag")" - for file in ${FILES:-*}; do + for escaped_file in ${FILES:-*}; do + file="$(decode "$escaped_file")" $DEBUG "TAG: $tag, exclude_file_globs: $exclude_file_globs" dotted=0 if is_excluded "$file" "$undotted_file_globs" "$never_undotted_file_globs"; then @@ -377,7 +379,8 @@ for DOTFILES_DIR in $DOTFILES_DIRS; do cd "$DOTFILES_DIR" - for file in ${FILES:-*}; do + for escaped_file in ${FILES:-*}; do + file="$(decode "$escaped_file")" dotted=0 if is_metafile "$file"; then continue diff --git a/bin/mkrc.in b/bin/mkrc.in index da22a63..5b2dea5 100755 --- a/bin/mkrc.in +++ b/bin/mkrc.in @@ -82,7 +82,10 @@ if [ $always_copy -eq 1 ]; then INSTALL="$INSTALL -C" fi -files=$@ +files="" +for i; do + files="$(printf "$files\n$i")" +done if [ $force_symlink -eq 1 ]; then for file in $files; do @@ -108,7 +111,11 @@ elif [ $undotted -eq 0 ]; then done fi +saved_IFS="$IFS" +IFS=' +' for file in $files; do + IFS="$saved_IFS" case "$file" in /*) : ;; *) [ -e "$PWD/$file" ] && file="$PWD/$file" ;; diff --git a/bin/rcup.in b/bin/rcup.in index de11751..932ac56 100755 --- a/bin/rcup.in +++ b/bin/rcup.in @@ -260,7 +260,10 @@ handle_command_line() { tags="${arg_tags:-$TAGS}" DOTFILES_DIRS="${dotfiles_dirs:-$DOTFILES_DIRS}" RUN_HOOKS=$run_hooks - files="$@" + files= + for file; do + files="$files $(encode "$file")" + done for tag in $tags; do LS_ARGS="$LS_ARGS -t $tag" diff --git a/share/rcm.sh.in b/share/rcm.sh.in index f0d3364..80e9e91 100644 --- a/share/rcm.sh.in +++ b/share/rcm.sh.in @@ -147,6 +147,20 @@ de_dot() { echo "$1" | sed -e "s|$DEST_DIR/||" | sed -e 's/^\.//' } +DELIMITER="\a" + +encode() { + local file="$1" + + echo "$file" | tr " " "$DELIMITER" +} + +decode() { + local file="$1" + + echo "$file" | tr "$DELIMITER" " " +} + : ${RCRC:=$HOME/.rcrc} if [ -r "$RCRC" ]; then diff --git a/test/lsrc-spaces.t b/test/lsrc-spaces.t new file mode 100644 index 0000000..fa406e2 --- /dev/null +++ b/test/lsrc-spaces.t @@ -0,0 +1,8 @@ + $ . "$TESTDIR/helper.sh" + +Should handle dotfiles with spaces + + $ touch ".dotfiles/sublame text 3.config" + + $ lsrc + /*/.sublame text 3.config:/*/.dotfiles/sublame text 3.config (glob) diff --git a/test/mkrc-spaces.t b/test/mkrc-spaces.t new file mode 100644 index 0000000..ebf8d5d --- /dev/null +++ b/test/mkrc-spaces.t @@ -0,0 +1,30 @@ + $ . "$TESTDIR/helper.sh" + +Should handle dotfiles with spaces + + $ touch ".sublime text 3.config" .example + $ touch .some\ other.config + + $ mkrc ".sublime text 3.config" .example .some\ other.config + + $ assert_linked "$HOME/.sublime text 3.config" "$HOME/.dotfiles/sublime text 3.config" + > assert_linked "$HOME/.example" "$HOME/.dotfiles/example" + > assert_linked "$HOME/.some other.config" "$HOME/.dotfiles/some other.config" + +Should handle hostnamed dotfiles with spaces + + $ touch ".sublime text 4.config" .example2 + + $ mkrc -o ".sublime text 4.config" .example2 + + $ assert_linked "$HOME/.sublime text 4.config" "$HOME/.dotfiles/host-$(hostname)/sublime text 4.config" + > assert_linked "$HOME/.example2" "$HOME/.dotfiles/host-$(hostname)/example2" + +Should handle tagged dotfiles with spaces + + $ touch ".sublime text 5.config" .example3 + + $ mkrc -t whatever ".sublime text 5.config" .example3 + + $ assert_linked "$HOME/.sublime text 5.config" "$HOME/.dotfiles/tag-whatever/sublime text 5.config" + > assert_linked "$HOME/.example3" "$HOME/.dotfiles/tag-whatever/example3" -- cgit v1.2.3