2018-07-11 08:50:42 -04:00
|
|
|
"""Test hooks"""
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
2023-07-10 15:43:17 -04:00
|
|
|
"pre, pre_code, post, post_code",
|
|
|
|
[
|
2018-07-11 08:50:42 -04:00
|
|
|
(False, 0, False, 0),
|
|
|
|
(True, 0, False, 0),
|
|
|
|
(True, 5, False, 0),
|
|
|
|
(False, 0, True, 0),
|
|
|
|
(False, 0, True, 5),
|
|
|
|
(True, 0, True, 0),
|
|
|
|
(True, 5, True, 5),
|
2023-07-10 15:43:17 -04:00
|
|
|
],
|
|
|
|
ids=[
|
|
|
|
"no-hooks",
|
|
|
|
"pre-success",
|
|
|
|
"pre-fail",
|
|
|
|
"post-success",
|
|
|
|
"post-fail",
|
|
|
|
"pre-post-success",
|
|
|
|
"pre-post-fail",
|
|
|
|
],
|
|
|
|
)
|
|
|
|
@pytest.mark.parametrize("cmd", ["--version", "version"])
|
|
|
|
def test_hooks(runner, yadm_cmd, paths, cmd, pre, pre_code, post, post_code):
|
2018-07-11 08:50:42 -04:00
|
|
|
"""Test pre/post hook"""
|
|
|
|
|
|
|
|
# generate hooks
|
|
|
|
if pre:
|
2023-07-10 15:43:17 -04:00
|
|
|
create_hook(paths, "pre_version", pre_code)
|
2018-07-11 08:50:42 -04:00
|
|
|
if post:
|
2023-07-10 15:43:17 -04:00
|
|
|
create_hook(paths, "post_version", post_code)
|
2018-07-11 08:50:42 -04:00
|
|
|
|
|
|
|
# run yadm
|
2020-12-21 17:53:44 -05:00
|
|
|
run = runner(yadm_cmd(cmd))
|
2018-07-11 08:50:42 -04:00
|
|
|
# when a pre hook fails, yadm should exit with the hook's code
|
|
|
|
assert run.code == pre_code
|
2023-07-10 15:43:17 -04:00
|
|
|
assert run.err == ""
|
2018-07-11 08:50:42 -04:00
|
|
|
|
|
|
|
if pre:
|
2023-07-10 15:43:17 -04:00
|
|
|
assert "HOOK:pre_version" in run.out
|
2018-07-11 08:50:42 -04:00
|
|
|
# if pre hook is missing or successful, yadm itself should exit 0
|
|
|
|
if run.success:
|
|
|
|
if post:
|
2023-07-10 15:43:17 -04:00
|
|
|
assert "HOOK:post_version" in run.out
|
2018-07-11 08:50:42 -04:00
|
|
|
else:
|
|
|
|
# when a pre hook fails, yadm should not run the command
|
2023-07-10 15:43:17 -04:00
|
|
|
assert "version will not be run" in run.out
|
2018-07-11 08:50:42 -04:00
|
|
|
# when a pre hook fails, yadm should not run the post hook
|
2023-07-10 15:43:17 -04:00
|
|
|
assert "HOOK:post_version" not in run.out
|
2018-07-11 08:50:42 -04:00
|
|
|
|
|
|
|
|
|
|
|
# repo fixture is needed to test the population of YADM_HOOK_WORK
|
2023-07-10 15:43:17 -04:00
|
|
|
@pytest.mark.usefixtures("ds1_repo_copy")
|
2020-11-17 15:38:31 -05:00
|
|
|
def test_hook_env(runner, yadm_cmd, paths):
|
2018-07-11 08:50:42 -04:00
|
|
|
"""Test hook environment"""
|
|
|
|
|
|
|
|
# test will be done with a non existent "git" passthru command
|
|
|
|
# which should exit with a failing code
|
2023-07-10 15:43:17 -04:00
|
|
|
cmd = "passthrucmd"
|
2018-07-11 08:50:42 -04:00
|
|
|
|
|
|
|
# write the hook
|
2023-07-10 15:43:17 -04:00
|
|
|
hook = paths.hooks.join(f"post_{cmd}")
|
|
|
|
hook.write("#!/bin/bash\nenv\ndeclare\n")
|
2018-07-11 08:50:42 -04:00
|
|
|
hook.chmod(0o755)
|
|
|
|
|
2023-07-10 15:43:17 -04:00
|
|
|
run = runner(yadm_cmd(cmd, "extra_args"))
|
2018-07-11 08:50:42 -04:00
|
|
|
|
|
|
|
# expect passthru to fail
|
|
|
|
assert run.failure
|
|
|
|
assert f"'{cmd}' is not a git command" in run.err
|
|
|
|
|
|
|
|
# verify hook environment
|
2023-07-10 15:43:17 -04:00
|
|
|
assert "YADM_HOOK_EXIT=1\n" in run.out
|
|
|
|
assert f"YADM_HOOK_COMMAND={cmd}\n" in run.out
|
|
|
|
assert f"YADM_HOOK_DIR={paths.yadm}\n" in run.out
|
|
|
|
assert f"YADM_HOOK_FULL_COMMAND={cmd} extra_args\n" in run.out
|
|
|
|
assert f"YADM_HOOK_REPO={paths.repo}\n" in run.out
|
|
|
|
assert f"YADM_HOOK_WORK={paths.work}\n" in run.out
|
|
|
|
assert "YADM_ENCRYPT_INCLUDE_FILES=\n" in run.out
|
2020-01-13 08:52:02 -05:00
|
|
|
|
|
|
|
# verify the hook environment contains certain exported functions
|
|
|
|
for func in [
|
2023-07-10 15:43:17 -04:00
|
|
|
"builtin_dirname",
|
|
|
|
"relative_path",
|
|
|
|
"unix_path",
|
|
|
|
"mixed_path",
|
2020-01-13 08:52:02 -05:00
|
|
|
]:
|
2023-07-10 15:43:17 -04:00
|
|
|
assert f"BASH_FUNC_{func}" in run.out
|
2020-01-13 08:52:02 -05:00
|
|
|
|
|
|
|
# verify the hook environment contains the list of encrypted files
|
|
|
|
script = f"""
|
|
|
|
YADM_TEST=1 source {paths.pgm}
|
|
|
|
YADM_HOOKS="{paths.hooks}"
|
|
|
|
HOOK_COMMAND="{cmd}"
|
|
|
|
ENCRYPT_INCLUDE_FILES=(a b c)
|
|
|
|
invoke_hook "post"
|
|
|
|
"""
|
2023-07-10 15:43:17 -04:00
|
|
|
run = runner(command=["bash"], inp=script)
|
2020-01-13 08:52:02 -05:00
|
|
|
assert run.success
|
2023-07-10 15:43:17 -04:00
|
|
|
assert run.err == ""
|
|
|
|
assert "YADM_ENCRYPT_INCLUDE_FILES=a\nb\nc\n" in run.out
|
2018-07-11 08:50:42 -04:00
|
|
|
|
|
|
|
|
2020-11-17 15:38:31 -05:00
|
|
|
def test_escaped(runner, yadm_cmd, paths):
|
2020-01-24 09:33:30 -05:00
|
|
|
"""Test escaped values in YADM_HOOK_FULL_COMMAND"""
|
|
|
|
|
|
|
|
# test will be done with a non existent "git" passthru command
|
|
|
|
# which should exit with a failing code
|
2023-07-10 15:43:17 -04:00
|
|
|
cmd = "passthrucmd"
|
2020-01-24 09:33:30 -05:00
|
|
|
|
|
|
|
# write the hook
|
2023-07-10 15:43:17 -04:00
|
|
|
hook = paths.hooks.join(f"post_{cmd}")
|
|
|
|
hook.write("#!/bin/bash\nenv\n")
|
2020-01-24 09:33:30 -05:00
|
|
|
hook.chmod(0o755)
|
|
|
|
|
2023-07-10 15:43:17 -04:00
|
|
|
run = runner(yadm_cmd(cmd, "a b", "c\td", "e\\f"))
|
2020-01-24 09:33:30 -05:00
|
|
|
|
|
|
|
# expect passthru to fail
|
|
|
|
assert run.failure
|
|
|
|
|
|
|
|
# verify escaped values
|
2023-07-10 15:43:17 -04:00
|
|
|
assert f"YADM_HOOK_FULL_COMMAND={cmd} a\\ b c\\\td e\\\\f\n" in run.out
|
2020-01-24 09:33:30 -05:00
|
|
|
|
|
|
|
|
2023-07-10 15:43:17 -04:00
|
|
|
@pytest.mark.parametrize("condition", ["exec", "no-exec", "mingw"])
|
2020-12-22 12:52:44 -05:00
|
|
|
def test_executable(runner, paths, condition):
|
|
|
|
"""Verify hook must be exectuable"""
|
2023-07-10 15:43:17 -04:00
|
|
|
cmd = "version"
|
|
|
|
hook = paths.hooks.join(f"pre_{cmd}")
|
|
|
|
hook.write("#!/bin/sh\necho HOOK\n")
|
2020-12-22 12:52:44 -05:00
|
|
|
hook.chmod(0o644)
|
2023-07-10 15:43:17 -04:00
|
|
|
if condition == "exec":
|
2020-12-22 12:52:44 -05:00
|
|
|
hook.chmod(0o755)
|
|
|
|
|
2023-07-10 15:43:17 -04:00
|
|
|
mingw = 'OPERATING_SYSTEM="MINGWx"' if condition == "mingw" else ""
|
2020-12-22 12:52:44 -05:00
|
|
|
script = f"""
|
|
|
|
YADM_TEST=1 source {paths.pgm}
|
|
|
|
YADM_HOOKS="{paths.hooks}"
|
|
|
|
HOOK_COMMAND="{cmd}"
|
|
|
|
{mingw}
|
|
|
|
invoke_hook "pre"
|
|
|
|
"""
|
2023-07-10 15:43:17 -04:00
|
|
|
run = runner(command=["bash"], inp=script)
|
2020-12-22 12:52:44 -05:00
|
|
|
|
2023-07-10 15:43:17 -04:00
|
|
|
if condition != "mingw":
|
2020-12-22 12:52:44 -05:00
|
|
|
assert run.success
|
2023-07-10 15:43:17 -04:00
|
|
|
assert run.err == ""
|
2020-12-22 12:52:44 -05:00
|
|
|
else:
|
|
|
|
assert run.failure
|
2023-07-10 15:43:17 -04:00
|
|
|
assert "Permission denied" in run.err
|
2020-12-22 12:52:44 -05:00
|
|
|
|
2023-07-10 15:43:17 -04:00
|
|
|
if condition == "exec":
|
|
|
|
assert "HOOK" in run.out
|
|
|
|
elif condition == "no-exec":
|
|
|
|
assert "HOOK" not in run.out
|
2020-12-22 12:52:44 -05:00
|
|
|
|
|
|
|
|
2018-07-11 08:50:42 -04:00
|
|
|
def create_hook(paths, name, code):
|
|
|
|
"""Create hook"""
|
|
|
|
hook = paths.hooks.join(name)
|
2023-07-10 15:43:17 -04:00
|
|
|
hook.write("#!/bin/sh\n" f"echo HOOK:{name}\n" f"exit {code}\n")
|
2018-07-11 08:50:42 -04:00
|
|
|
hook.chmod(0o755)
|