diff --git a/test/conftest.py b/test/conftest.py index b18cae4..7ea38f6 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -157,6 +157,7 @@ def supported_configs(): "yadm.openssl-old", "yadm.openssl-program", "yadm.ssh-perms", + "yadm.template-read-only", ] diff --git a/test/test_alt.py b/test/test_alt.py index c429ad4..d6edd75 100644 --- a/test/test_alt.py +++ b/test/test_alt.py @@ -292,6 +292,28 @@ def test_ensure_alt_path(runner, paths, style): assert run.out == "" assert paths.work.join(filename).read().strip() == "test-data" +@pytest.mark.usefixtures("ds1_repo_copy") +@pytest.mark.parametrize("readonly", [None, "true", "false"]) +def test_template_readonly(runner, yadm_cmd, paths, tst_sys, readonly): + """Remove write permission for template result file. + + If the `yadm.template-read-only` configuration is not set to false, + the resulting file from processing a template should has no write permission. + """ + # set the value of template read-only + if readonly: + runner(yadm_cmd("config", "yadm.template-read-only", readonly)) + + utils.create_alt_files(paths, f"##template.default") + run = runner(yadm_cmd("alt")) + + for stale_path in [utils.ALT_FILE1, utils.ALT_FILE2]: + write_perm_mask = os.stat(paths.work.join(stale_path)).st_mode & 0o222 + if readonly == "false": + assert write_perm_mask > 0 + else: + assert write_perm_mask == 0 + def setup_standard_yadm_dir(paths): """Configure a yadm home within the work tree""" diff --git a/yadm b/yadm index 09da278..3eb0655 100755 --- a/yadm +++ b/yadm @@ -540,6 +540,7 @@ function move_file() { mv -f "$temp_file" "$output" copy_perms "$input" "$output" + [ "$(config --bool yadm.template-read-only)" != "false" ] && chmod a-w "$output" } # ****** yadm Commands ****** @@ -1266,6 +1267,7 @@ yadm.openssl-ciphername yadm.openssl-old yadm.openssl-program yadm.ssh-perms +yadm.template-read-only EOF printf '%s' "$msg" } diff --git a/yadm.1 b/yadm.1 index c689eb6..7069511 100644 --- a/yadm.1 +++ b/yadm.1 @@ -108,6 +108,9 @@ unnecessary to run this command, as yadm automatically processes alternates by default. This automatic behavior can be disabled by setting the configuration .I yadm.auto-alt to "false". +The resulting file's write permission can be controlled with the +.I yadm.template-read-only +configuration. .TP .B bootstrap Execute @@ -425,6 +428,10 @@ By default, the first "openssl" found in $PATH is used. Disable the permission changes to .IR $HOME/.ssh/* . This feature is enabled by default. +.TP +.B yadm.template-read-only +Remove write permissions from the resulting template file. +This feature is enabled by default. .RE The following five "local" configurations are not stored in the diff --git a/yadm.md b/yadm.md index 328e384..707382a 100644 --- a/yadm.md +++ b/yadm.md @@ -67,7 +67,9 @@ TEMPLATES sections. It is usually unnecessary to run this com‐ mand, as yadm automatically processes alternates by default. This automatic behavior can be disabled by setting the configu‐ - ration yadm.auto-alt to "false". + ration yadm.auto-alt to "false". The resulting file's write + permission can be controlled with the yadm.template-read-only + configuration. bootstrap Execute $HOME/.config/yadm/bootstrap if it exists.