diff --git a/lib/commands/link.sh b/lib/commands/link.sh index 70ce13bb..5b70b206 100644 --- a/lib/commands/link.sh +++ b/lib/commands/link.sh @@ -94,7 +94,7 @@ get_repo_files() { root=$(cd "$1" && pwd -P) ( local path - while IFS= read -d $'\n' -r path; do + while IFS= read -d $'\0' -r path; do # Remove quotes from ls-files # (used when there are newlines in the path) path=${path/#\"/} @@ -104,9 +104,7 @@ get_repo_files() { # Remove the home/ part path=${path/#home\//} # Print the file path (NUL separated because \n can be used in filenames) - # Disable SC2059, using %s messes with the filename - # shellcheck disable=SC2059 - printf "$path\0" + printf "%s\0" "$path" # Get the path of all the parent directories # up to the repo root. while true; do @@ -114,13 +112,12 @@ get_repo_files() { # If path is '.' we're done [[ $path == '.' ]] && break # Print the path - # shellcheck disable=SC2059 - printf "$path\0" + printf "%s\0" "$path" done # Enter the repo, list the repo root files in home # and do the same for any submodules done < <(cd "$root" && - git ls-files 'home/' && + git ls-files -z 'home/' && git submodule --quiet foreach --recursive \ "$homeshick/lib/submodule_files.sh \"$root\" \"\$toplevel\" \"\$path\"") # Unfortunately we have to use an external script for `git submodule foreach' diff --git a/lib/submodule_files.sh b/lib/submodule_files.sh index 06fbed4b..0aa91b43 100755 --- a/lib/submodule_files.sh +++ b/lib/submodule_files.sh @@ -17,5 +17,5 @@ if [[ $repo =~ ^home ]]; then cd "$toplevel/$path" # List the files and prefix every line # with the relative repo path - git ls-files | sed "s#^#${repo//#/\\#}/#" + git ls-files -z | sed -z "s#^#${repo//#/\\#}/#" fi diff --git a/test/fixtures/repo with spaces in name.sh b/test/fixtures/repo with spaces in name.sh index 34c4e30e..47e1318c 100644 --- a/test/fixtures/repo with spaces in name.sh +++ b/test/fixtures/repo with spaces in name.sh @@ -28,6 +28,8 @@ fixture_repo_with_spaces_in_name() { file␇☺" git add ".crazy file␇☺" + touch "%printf conver%sionchar%s %%" + git add "%printf conver%sionchar%s %%" git commit -m 'Add file with newline and all kinds of crazy characters in the name' } diff --git a/test/suites/link.bats b/test/suites/link.bats index 246884be..af49573f 100755 --- a/test/suites/link.bats +++ b/test/suites/link.bats @@ -21,6 +21,13 @@ file␇☺" file␇☺" } +@test 'link file with printf conversion chars' { + castle 'repo with spaces in name' + homeshick --batch link 'repo with spaces in name' + stat "$HOME/%printf conver%sionchar%s %%" + test -f "$HOME/%printf conver%sionchar%s %%" +} + @test 'do not fail when linking file with newline' { castle 'rc-files' test_filename="filename