From fc24ce9f54694d13a618c5d974f311bf893224f8 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Fri, 1 Apr 2022 16:32:22 +0300 Subject: test: refactoring --- test/test.sh | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/test/test.sh b/test/test.sh index 0e02480..9bb8e9d 100755 --- a/test/test.sh +++ b/test/test.sh @@ -25,6 +25,7 @@ test_alt_dest_dir= new_test() { local test_name= [ "${#FUNCNAME[@]}" -gt 1 ] && test_name="${FUNCNAME[1]}" + [ "$#" -gt 0 ] && test_name="$1" echo echo ====================================================================== @@ -175,16 +176,19 @@ $test_dest_dir/bar/3.txt->" verify_output "$expected_output" } -test_dir_symlink_update_works() { - # We can symlink files to multiple directories by creating symlinks inside - # --shared-dir. - - new_test +new_test_dir_symlink() { + new_test "${FUNCNAME[1]}" # Files will get symlinks in the directory pointed to by $DEST, as well as # by $ALT_DEST. ln -s -- '%DEST%' "$test_src_dir/%ALT_DEST%" +} + +test_dir_symlink_update_works() { + # We can symlink files to multiple directories by creating symlinks inside + # --shared-dir. + new_test_dir_symlink call_update local expected_output="$test_dest_dir-> @@ -213,12 +217,7 @@ $test_alt_dest_dir/foo/2.txt->$test_src_dir/%ALT_DEST%/foo/2.txt" test_dir_symlink_unlink_works() { # Test that unlink.sh works for directory symlinks inside --shared-dir. - new_test - - # Files will get symlinks in the directory pointed to by $DEST, as well as - # by $ALT_DEST. - ln -s -- '%DEST%' "$test_src_dir/%ALT_DEST%" - + new_test_dir_symlink call_update call_unlink @@ -232,9 +231,9 @@ test_dir_symlink_unlink_works() { test_dir_symlink_remove_shared_file() { # If we remove a shared file, both of the symlinks should be removed. - new_test - ln -s -- '%DEST%' "$test_src_dir/%ALT_DEST%" + new_test_dir_symlink call_update + # Remove a random shared file: rm -- "$test_src_dir/%DEST%/bar/3.txt" call_update @@ -264,9 +263,9 @@ test_dir_symlink_remove_dir_symlink() { # If we remove a directory symlink in --shared-dir, all the symlinks # accessible through this directory symlink should be removed. - new_test - ln -s -- '%DEST%' "$test_src_dir/%ALT_DEST%" + new_test_dir_symlink call_update + # Remove the directory symlink: rm -- "$test_src_dir/%ALT_DEST%" call_update @@ -286,12 +285,17 @@ $test_dest_dir/foo/2.txt->$test_src_dir/%DEST%/foo/2.txt" verify_output "$expected_output" "$test_alt_dest_dir" } -test_symlink_update_works() { - # Shared files can also be symlinks, pointing to something else. +new_test_symlink() { + new_test "${FUNCNAME[1]}" - new_test # Create a stupid symlink. ln -s -- 'bar/3.txt' "$test_src_dir/%DEST%/3_copy.txt" +} + +test_symlink_update_works() { + # Shared files can also be symlinks, pointing to something else. + + new_test_symlink call_update local expected_output="$test_dest_dir-> @@ -319,9 +323,9 @@ $test_dest_dir/foo/2.txt->$test_src_dir/%DEST%/foo/2.txt" } test_symlink_unlink_works() { - new_test - # Create a stupid symlink. - ln -s -- 'bar/3.txt' "$test_src_dir/%DEST%/3_copy.txt" + # Verify that unlinking doesn't delete the shared symlinks. + + new_test_symlink call_update call_unlink @@ -342,6 +346,7 @@ test_symlink_unlink_works() { test_chmod_works() { # Test that links-chmod works. + new_test call_update @@ -365,6 +370,7 @@ $test_dest_dir/foo/2.txt->$test_src_dir/%DEST%/foo/2.txt" test_update_chmod() { # Test that links-update --mode works. + new_test local expected_mode='0622' call_update --mode "$expected_mode" -- cgit v1.2.3 From 646815c3b8b0fd1cb96064ffab9d776ad681474f Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Fri, 1 Apr 2022 16:36:43 +0300 Subject: test: add a test case --- test/test.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/test.sh b/test/test.sh index 9bb8e9d..f2920b5 100755 --- a/test/test.sh +++ b/test/test.sh @@ -176,6 +176,26 @@ $test_dest_dir/bar/3.txt->" verify_output "$expected_output" } +test_unlink_does_not_delete_used_dirs() { + # Check that if a user adds a file to a destination directory, it's not + # deleted when unlinking. + + new_test + call_update + + # User adds his own file to the directory: + echo 'User content' > "$test_dest_dir/bar/my-file" + + call_unlink + + # bar/ and bar/my-file must be kept: + local expected_output="$test_dest_dir-> +$test_dest_dir/bar-> +$test_dest_dir/bar/my-file->" + + verify_output "$expected_output" +} + new_test_dir_symlink() { new_test "${FUNCNAME[1]}" @@ -392,6 +412,7 @@ main() { test_update_works test_unlink_works test_unlink_does_not_overwrite_files + test_unlink_does_not_delete_used_dirs test_dir_symlink_update_works test_dir_symlink_unlink_works -- cgit v1.2.3 From 65bfbc1fb54850275d4e9842ef2bd333d2081af4 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sat, 2 Apr 2022 14:28:37 +0300 Subject: bash best practices & linting --- links-chmod | 5 ++--- links-remove | 5 ++--- links-update | 5 ++--- src/db.sh | 19 +++++++++++++------ src/path.sh | 4 ++-- test/test.sh | 3 ++- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/links-chmod b/links-chmod index 9810cf6..f722b95 100755 --- a/links-chmod +++ b/links-chmod @@ -7,9 +7,8 @@ # usage: ./links-chmod [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] MODE -set -o errexit -set -o nounset -set -o pipefail +set -o errexit -o nounset -o pipefail +shopt -s inherit_errexit lastpipe script_name="$( basename -- "${BASH_SOURCE[0]}" )" readonly script_name diff --git a/links-remove b/links-remove index ea79596..c378485 100755 --- a/links-remove +++ b/links-remove @@ -7,9 +7,8 @@ # usage: ./links-remove [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] -set -o errexit -set -o nounset -set -o pipefail +set -o errexit -o nounset -o pipefail +shopt -s inherit_errexit lastpipe script_name="$( basename -- "${BASH_SOURCE[0]}" )" readonly script_name diff --git a/links-update b/links-update index 6a802bc..5b15f1b 100755 --- a/links-update +++ b/links-update @@ -19,9 +19,8 @@ # usage: ./links-update [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-m|--mode MODE] [-n|--dry-run] -set -o errexit -set -o nounset -set -o pipefail +set -o errexit -o nounset -o pipefail +shopt -s inherit_errexit lastpipe script_name="$( basename -- "${BASH_SOURCE[0]}" )" readonly script_name diff --git a/src/db.sh b/src/db.sh index b057202..201ad25 100644 --- a/src/db.sh +++ b/src/db.sh @@ -57,7 +57,7 @@ add_entry() { local shared_var_dir="$shared_root_dir%$var_name%" local symlink_var_dir symlink_var_dir="$( resolve_variable "$var_name" )" - local subpath="${entry#%$var_name%/}" + local subpath="${entry#%"$var_name"%/}" local shared_path="$shared_var_dir" [ "$shared_var_dir" != / ] && shared_path="$shared_path/" @@ -134,7 +134,7 @@ delete_obsolete_dirs() { [ "$base_dir" = "$dir" ] && return 0 - local subpath="${dir##$base_dir/}" + local subpath="${dir##"$base_dir"/}" if [ "$subpath" = "$dir" ]; then dump "base directory: $base_dir" >&2 @@ -193,10 +193,18 @@ shared_file_present() { link_all_entries() { local shared_var_dir + + find "$shared_root_dir" \ + -mindepth 1 -maxdepth 1 \ + -\( -type d -o -type l -\) \ + -regextype posix-basic \ + -regex ".*/$var_name_regex\$" \ + -printf '%P\0' | while IFS= read -d '' -r shared_var_dir; do dump "shared directory: $shared_root_dir$shared_var_dir" - local shared_path + + find "$shared_root_dir$shared_var_dir/" -\( -type f -o -type l -\) -print0 | while IFS= read -d '' -r shared_path; do dump " shared file path: $shared_path" local entry="${shared_path:${#shared_root_dir}}" @@ -214,9 +222,8 @@ link_all_entries() { dump ' ... adding a symlink' is_dry_run || link_entry "$entry" fi - - done < <( find "$shared_root_dir$shared_var_dir/" -\( -type f -o -type l -\) -print0 ) - done < <( find "$shared_root_dir" -regextype posix-basic -mindepth 1 -maxdepth 1 -\( -type d -o -type l -\) -regex ".*/$var_name_regex\$" -printf '%P\0' ) + done + done } unlink_all_entries() { diff --git a/src/path.sh b/src/path.sh index bf52a6f..8ac71a9 100644 --- a/src/path.sh +++ b/src/path.sh @@ -76,7 +76,7 @@ traverse_path() { local -a abs_paths=() local path - while IFS= read -d '' -r path; do + readlink -z --canonicalize-missing -- ${paths[@]+"${paths[@]}"} | while IFS= read -d '' -r path; do if [ -n "$must_exist" ] && [ ! -e "$path" ]; then dump "must exist: $path" >&2 return 1 @@ -88,7 +88,7 @@ traverse_path() { fi abs_paths+=("$path") - done < <( readlink -z --canonicalize-missing -- ${paths[@]+"${paths[@]}"} ) + done printf -- "$fmt" ${abs_paths[@]+"${abs_paths[@]}"} } diff --git a/test/test.sh b/test/test.sh index f2920b5..9a9ff33 100755 --- a/test/test.sh +++ b/test/test.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -o errexit -o nounset -o pipefail +shopt -s inherit_errexit lastpipe script_dir="$( dirname -- "${BASH_SOURCE[0]}" )" script_dir="$( cd -- "$script_dir" && pwd )" @@ -55,7 +56,7 @@ call_bin_script() { printf -- '\n' echo - DEST="$test_dest_dir" ALT_DEST="$test_alt_dest_dir" eval "$@" --shared-dir "$test_src_dir" --database "$test_root_dir/links.bin" + DEST="$test_dest_dir" ALT_DEST="$test_alt_dest_dir" "$@" --shared-dir "$test_src_dir" --database "$test_root_dir/links.bin" } call_update() { -- cgit v1.2.3 From 9981e5593448d5968126cdd242548f5d6986966c Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sat, 2 Apr 2022 14:29:22 +0300 Subject: README: update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 18d3838..2ff362c 100644 --- a/README.md +++ b/README.md @@ -93,10 +93,10 @@ In this example, symlinks to files in "../src" must appear in "/test/dest". For my personal real-life usage examples, see -* my [Linux/Cygwin environment], +* [my dotfiles], * configuration files for various [Windows apps]. -[Linux/Cygwin environment]: https://github.com/egor-tensin/linux-home +[my dotfiles]: https://github.com/egor-tensin/linux-home [Windows apps]: https://github.com/egor-tensin/windows-home Limitations -- cgit v1.2.3 From dc5752ab9ca0b5f0daea85d9cbfa569611e4f2b6 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sat, 2 Apr 2022 14:35:49 +0300 Subject: test: update comments --- test/test.sh | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/test/test.sh b/test/test.sh index 9a9ff33..f2abfde 100755 --- a/test/test.sh +++ b/test/test.sh @@ -63,7 +63,7 @@ call_update() { call_bin_script "$script_dir/../links-update" "$@" } -call_unlink() { +call_remove() { call_bin_script "$script_dir/../links-remove" } @@ -128,7 +128,8 @@ verify_mode() { } test_update_works() { - # Basic test to make sure update.sh actually creates the proper symlinks. + # Basic test to make sure that links-update actually creates the proper + # symlinks. new_test call_update @@ -145,19 +146,20 @@ $test_dest_dir/foo/2.txt->$test_src_dir/%DEST%/foo/2.txt" verify_output "$expected_output" } -test_unlink_works() { - # Basic test to make sure unlink.sh actually removes the created symlinks. +test_remove_works() { + # Basic test to make sure links-remove actually removes the created + # symlinks. new_test call_update - call_unlink + call_remove local expected_output="$test_dest_dir->" verify_output "$expected_output" } -test_unlink_does_not_overwrite_files() { - # Check that if a user overwrites a symlink with his own file, unlink.sh +test_remove_does_not_overwrite_files() { + # Check that if a user overwrites a symlink with his own file, links-remove # keeps it. new_test @@ -167,7 +169,7 @@ test_unlink_does_not_overwrite_files() { rm -- "$test_dest_dir/bar/3.txt" echo 'User content' > "$test_dest_dir/bar/3.txt" - call_unlink + call_remove # 3.txt must be kept: local expected_output="$test_dest_dir-> @@ -177,9 +179,9 @@ $test_dest_dir/bar/3.txt->" verify_output "$expected_output" } -test_unlink_does_not_delete_used_dirs() { +test_remove_does_not_delete_used_dirs() { # Check that if a user adds a file to a destination directory, it's not - # deleted when unlinking. + # deleted by links-remove. new_test call_update @@ -187,7 +189,7 @@ test_unlink_does_not_delete_used_dirs() { # User adds his own file to the directory: echo 'User content' > "$test_dest_dir/bar/my-file" - call_unlink + call_remove # bar/ and bar/my-file must be kept: local expected_output="$test_dest_dir-> @@ -235,12 +237,12 @@ $test_alt_dest_dir/foo/2.txt->$test_src_dir/%ALT_DEST%/foo/2.txt" verify_output "$expected_output" "$test_alt_dest_dir" } -test_dir_symlink_unlink_works() { - # Test that unlink.sh works for directory symlinks inside --shared-dir. +test_dir_symlink_remove_works() { + # Test that links-remove works for directory symlinks inside --shared-dir. new_test_dir_symlink call_update - call_unlink + call_remove local expected_output="$test_dest_dir->" verify_output "$expected_output" @@ -343,12 +345,12 @@ $test_dest_dir/foo/2.txt->$test_src_dir/%DEST%/foo/2.txt" test "$copy_content" = '3' } -test_symlink_unlink_works() { - # Verify that unlinking doesn't delete the shared symlinks. +test_symlink_remove_works() { + # Verify that links-remove doesn't delete shared symlinks. new_test_symlink call_update - call_unlink + call_remove local expected_output="$test_dest_dir->" verify_output "$expected_output" @@ -411,17 +413,17 @@ $test_dest_dir/foo/2.txt->$test_src_dir/%DEST%/foo/2.txt" main() { test_update_works - test_unlink_works - test_unlink_does_not_overwrite_files - test_unlink_does_not_delete_used_dirs + test_remove_works + test_remove_does_not_overwrite_files + test_remove_does_not_delete_used_dirs test_dir_symlink_update_works - test_dir_symlink_unlink_works + test_dir_symlink_remove_works test_dir_symlink_remove_shared_file test_dir_symlink_remove_dir_symlink test_symlink_update_works - test_symlink_unlink_works + test_symlink_remove_works test_chmod_works test_update_chmod -- cgit v1.2.3