From 50f3520aa9ae9ada8da08ab66527b69f47a9be34 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Thu, 25 Nov 2021 20:50:17 +0300 Subject: update script names in comments --- links-remove | 2 +- links-update | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/links-remove b/links-remove index 271fa02..ea79596 100755 --- a/links-remove +++ b/links-remove @@ -5,7 +5,7 @@ # For details, see https://github.com/egor-tensin/config-links. # Distributed under the MIT License. -# usage: ./unlink.sh [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] +# usage: ./links-remove [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] set -o errexit set -o nounset diff --git a/links-update b/links-update index 6c3b633..b195305 100755 --- a/links-update +++ b/links-update @@ -17,7 +17,7 @@ # `CYGWIN` Windows environment variable value **must** include either # `winsymlinks:native` or `winsymlinks:nativestrict`! -# usage: ./update.sh [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] +# usage: ./links-update [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] set -o errexit set -o nounset -- cgit v1.2.3 From d93e1a3e214253cffb1a99e8e3dff8d378ace8ac Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Thu, 25 Nov 2021 21:09:26 +0300 Subject: add links-chmod --- links-chmod | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/db.sh | 14 +++++++++ test/test.sh | 40 +++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100755 links-chmod diff --git a/links-chmod b/links-chmod new file mode 100755 index 0000000..517ce1f --- /dev/null +++ b/links-chmod @@ -0,0 +1,98 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021 Egor Tensin +# This file is part of the "Config file sharing" project. +# For details, see https://github.com/egor-tensin/config-links. +# Distributed under the MIT License. + +# usage: ./links-chmod [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-m|--mode MODE] [-n|--dry-run] + +set -o errexit +set -o nounset +set -o pipefail + +script_name="$( basename -- "${BASH_SOURCE[0]}" )" +readonly script_name +script_path="$( realpath --canonicalize-existing -- "${BASH_SOURCE[0]}" )" +readonly script_path +script_dir="$( dirname -- "$script_path" )" +readonly script_dir +src_dir="$( cd -- "$script_dir/src" && pwd )" +readonly src_dir + +. "$src_dir/common.sh" +. "$src_dir/os.sh" +. "$src_dir/path.sh" +. "$src_dir/vars.sh" +. "$src_dir/db.sh" + +script_usage() { + local msg + for msg; do + echo "$script_name: $msg" + done + + echo "usage: $script_name [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] + -h,--help show this message and exit + -d,--database set database file path + -s,--shared-dir set top-level shared directory path + (current working directory by default) + -n,--dry-run don't actually do anything intrusive + -m,--mode shared files mode (as in chmod)" +} + +parse_script_options() { + while [ "$#" -gt 0 ]; do + local key="$1" + shift + + case "$key" in + -h|--help) + script_usage + exit 0 + ;; + -n|--dry-run) + set_dry_run + continue + ;; + -d|--database|-s|--shared-dir|-m|--mode) + ;; + *) + script_usage "unrecognized parameter: $key" >&2 + exit 1 + ;; + esac + + if [ "$#" -eq 0 ]; then + script_usage "missing argument for parameter: $key" >&2 + exit 1 + fi + + local value="$1" + shift + + case "$key" in + -d|--database) + update_database_path "$value" + ;; + -s|--shared-dir) + update_shared_dir "$value" + ;; + -m|--mode) + mode="$value" + ;; + *) + script_usage "unrecognized parameter: $key" >&2 + exit 1 + ;; + esac + done +} + +main() { + parse_script_options "$@" + read_database + chmod_entries "$mode" +} + +main "$@" diff --git a/src/db.sh b/src/db.sh index 6145c6d..0022ab9 100644 --- a/src/db.sh +++ b/src/db.sh @@ -262,3 +262,17 @@ unlink_obsolete_entries() { fi done } + +chmod_entries() { + if [ "$#" -ne 1 ]; then + echo "usage: ${FUNCNAME[0]} MODE" >&2 + return 1 + fi + + local mode="$1" + shift + + if [ "${#shared_paths[@]}" -ne 0 ]; then + is_dry_run || chmod -- "$mode" ${shared_paths[@]+"${shared_paths[@]}"} + fi +} diff --git a/test/test.sh b/test/test.sh index 37167ec..db094ad 100755 --- a/test/test.sh +++ b/test/test.sh @@ -65,6 +65,10 @@ call_unlink() { call_bin_script "$script_dir/../links-remove" } +call_chmod() { + call_bin_script "$script_dir/../links-chmod" "$@" +} + verify_output() { if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then echo "usage: ${FUNCNAME[0]} EXPECTED_OUTPUT [DEST_DIR]" >&2 @@ -308,6 +312,40 @@ test_symlink_unlink_works() { test "$copy_content" = '3' } +test_chmod_works() { + # Test that links-chmod works. + new_test + call_update + + local expected_output="$test_dest_dir-> +$test_dest_dir/1.txt->$test_src_dir/%DEST%/1.txt +$test_dest_dir/bar-> +$test_dest_dir/bar/3.txt->$test_src_dir/%DEST%/bar/3.txt +$test_dest_dir/bar/baz-> +$test_dest_dir/bar/baz/4.txt->$test_src_dir/%DEST%/bar/baz/4.txt +$test_dest_dir/foo-> +$test_dest_dir/foo/2.txt->$test_src_dir/%DEST%/foo/2.txt" + verify_output "$expected_output" + + echo + echo 'Verifying 1.txt (the shared file) permissions...' + + local mode + + mode="$( stat -c '%a' -- "$test_src_dir/%DEST%/1.txt" )" + echo "Actual permissions: $mode" + test "$mode" = '644' + + call_chmod --mode 0600 + + echo + echo 'Verifying 1.txt (the shared file) permissions have changed...' + + mode="$( stat -c '%a' -- "$test_src_dir/%DEST%/1.txt" )" + echo "Actual permissions: $mode" + test "$mode" = '600' +} + main() { test_update_works test_unlink_works @@ -320,6 +358,8 @@ main() { test_symlink_update_works test_symlink_unlink_works + + test_chmod_works } main -- cgit v1.2.3 From b2fae87c14806fa1d7ab81de8f1a0b0cbe42b434 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Thu, 25 Nov 2021 21:54:40 +0300 Subject: links-chmod: tweak the help message --- links-chmod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/links-chmod b/links-chmod index 517ce1f..9c7a427 100755 --- a/links-chmod +++ b/links-chmod @@ -37,8 +37,8 @@ script_usage() { -d,--database set database file path -s,--shared-dir set top-level shared directory path (current working directory by default) - -n,--dry-run don't actually do anything intrusive - -m,--mode shared files mode (as in chmod)" + -m,--mode shared files mode (as in chmod) + -n,--dry-run don't actually do anything intrusive" } parse_script_options() { -- cgit v1.2.3 From 0f148a6a8ff454780722d611e642c0e15f98bc94 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Thu, 25 Nov 2021 21:55:28 +0300 Subject: db.sh: add more logging --- src/db.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/db.sh b/src/db.sh index 0022ab9..5eb1697 100644 --- a/src/db.sh +++ b/src/db.sh @@ -272,6 +272,7 @@ chmod_entries() { local mode="$1" shift + echo "Applying mode $mode to shared files..." if [ "${#shared_paths[@]}" -ne 0 ]; then is_dry_run || chmod -- "$mode" ${shared_paths[@]+"${shared_paths[@]}"} fi -- cgit v1.2.3 From 6b98b6f0b90088f276af4b3a392ca59dd8051fb9 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Thu, 25 Nov 2021 21:56:13 +0300 Subject: test/test.sh: best practices --- test/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test.sh b/test/test.sh index db094ad..efe4315 100755 --- a/test/test.sh +++ b/test/test.sh @@ -83,6 +83,7 @@ verify_output() { local dest_dir="$test_dest_dir" [ "$#" -ge 2 ] && dest_dir="$2" + local actual_output actual_output="$( find "$dest_dir" -printf '%h/%f->%l\n' | sort )" echo echo 'Actual directory structure:' -- cgit v1.2.3 From a556264de6ddab9bcd47023b1d3daa2e2b683505 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Thu, 25 Nov 2021 21:57:57 +0300 Subject: links-update: add --mode parameter --- links-update | 13 ++++++++++--- test/test.sh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/links-update b/links-update index b195305..1e1c829 100755 --- a/links-update +++ b/links-update @@ -17,7 +17,7 @@ # `CYGWIN` Windows environment variable value **must** include either # `winsymlinks:native` or `winsymlinks:nativestrict`! -# usage: ./links-update [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] +# usage: ./links-update [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-m|--mode MODE] [-n|--dry-run] set -o errexit set -o nounset @@ -32,6 +32,8 @@ readonly script_dir src_dir="$( cd -- "$script_dir/src" && pwd )" readonly src_dir +mode='' + . "$src_dir/common.sh" . "$src_dir/os.sh" . "$src_dir/path.sh" @@ -44,11 +46,12 @@ script_usage() { echo "$script_name: $msg" done - echo "usage: $script_name [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] + echo "usage: $script_name [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-m|--mode MODE] [-n|--dry-run] -h,--help show this message and exit -d,--database set database file path -s,--shared-dir set top-level shared directory path (current working directory by default) + -m,--mode shared files mode (as in chmod) -n,--dry-run don't actually do anything intrusive" } @@ -66,7 +69,7 @@ parse_script_options() { set_dry_run continue ;; - -d|--database|-s|--shared-dir) + -d|--database|-s|--shared-dir|-m|--mode) ;; *) script_usage "unrecognized parameter: $key" >&2 @@ -89,6 +92,9 @@ parse_script_options() { -s|--shared-dir) update_shared_dir "$value" ;; + -m|--mode) + mode="$value" + ;; *) script_usage "unrecognized parameter: $key" >&2 exit 1 @@ -103,6 +109,7 @@ main() { read_database unlink_obsolete_entries link_all_entries + test -n "$mode" && chmod_entries "$mode" write_database } diff --git a/test/test.sh b/test/test.sh index efe4315..de4dd85 100755 --- a/test/test.sh +++ b/test/test.sh @@ -58,7 +58,7 @@ call_bin_script() { } call_update() { - call_bin_script "$script_dir/../links-update" + call_bin_script "$script_dir/../links-update" "$@" } call_unlink() { @@ -98,6 +98,33 @@ verify_output() { fi } +verify_mode() { + if [ "$#" -ne 2 ]; then + echo "usage: ${FUNCNAME[0]} EXPECTED_MODE FILE" >&2 + return 1 + fi + + local expected_mode="$1" + local path="$2" + + echo + echo "Checking permissions for file: $path" + echo "Expected mode: $expected_mode" + + local actual_mode + actual_mode="$( stat -c '%a' -- "$path" )" + actual_mode="0$actual_mode" + + echo "Actual mode: $actual_mode" + + if [ "$actual_mode" = "$expected_mode" ]; then + echo "... They match!" + else + echo "... They don't match." + return 1 + fi +} + test_update_works() { # Basic test to make sure update.sh actually creates the proper symlinks. @@ -331,20 +358,28 @@ $test_dest_dir/foo/2.txt->$test_src_dir/%DEST%/foo/2.txt" echo echo 'Verifying 1.txt (the shared file) permissions...' - local mode - - mode="$( stat -c '%a' -- "$test_src_dir/%DEST%/1.txt" )" - echo "Actual permissions: $mode" - test "$mode" = '644' - + verify_mode 0644 "$test_src_dir/%DEST%/1.txt" call_chmod --mode 0600 + verify_mode 0600 "$test_src_dir/%DEST%/1.txt" +} - echo - echo 'Verifying 1.txt (the shared file) permissions have changed...' +test_update_chmod() { + # Test that links-update --mode works. + new_test + local expected_mode='0622' + call_update --mode "$expected_mode" + + local expected_output="$test_dest_dir-> +$test_dest_dir/1.txt->$test_src_dir/%DEST%/1.txt +$test_dest_dir/bar-> +$test_dest_dir/bar/3.txt->$test_src_dir/%DEST%/bar/3.txt +$test_dest_dir/bar/baz-> +$test_dest_dir/bar/baz/4.txt->$test_src_dir/%DEST%/bar/baz/4.txt +$test_dest_dir/foo-> +$test_dest_dir/foo/2.txt->$test_src_dir/%DEST%/foo/2.txt" + verify_output "$expected_output" - mode="$( stat -c '%a' -- "$test_src_dir/%DEST%/1.txt" )" - echo "Actual permissions: $mode" - test "$mode" = '600' + verify_mode "$expected_mode" "$test_src_dir/%DEST%/1.txt" } main() { @@ -361,6 +396,7 @@ main() { test_symlink_unlink_works test_chmod_works + test_update_chmod } main -- cgit v1.2.3 From e156fae7fc1fb0bd03b287972b1a5917b0ddab90 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Thu, 25 Nov 2021 22:01:13 +0300 Subject: README: update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2fe286..18d3838 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Usage Symlinks are created & maintained by `links-update`. ``` -usage: links-update [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-n|--dry-run] +usage: links-update [-h|--help] [-d|--database PATH] [-s|--shared-dir DIR] [-m|--mode MODE] [-n|--dry-run] ``` To remove all symlinks, use `links-remove`. -- cgit v1.2.3