From d3a2a061844e48722bfc994f227f3e88c106d1a8 Mon Sep 17 00:00:00 2001 From: Tim Byrne Date: Sun, 15 Dec 2019 18:42:21 -0600 Subject: [PATCH] Support git-crypt (#168) Support is inherently provided by `enter`, which now supports a command. I've added a `git-crypt` command, which is really just an alias under-the-hood for "enter git-crypt". --- test/conftest.py | 1 + test/test_git_crypt.py | 42 ++++++++++++++++++++++ yadm | 80 ++++++++++++++++++++++++++---------------- 3 files changed, 92 insertions(+), 31 deletions(-) create mode 100644 test/test_git_crypt.py diff --git a/test/conftest.py b/test/conftest.py index 941979e..31d872b 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -89,6 +89,7 @@ def supported_commands(): 'decrypt', 'encrypt', 'enter', + 'git-crypt', 'gitconfig', 'help', 'init', diff --git a/test/test_git_crypt.py b/test/test_git_crypt.py new file mode 100644 index 0000000..6b92de9 --- /dev/null +++ b/test/test_git_crypt.py @@ -0,0 +1,42 @@ +"""Test git-crypt""" + +import pytest + + +@pytest.mark.parametrize( + 'crypt', + [False, 'installed', 'installed-but-failed'], + ids=['not-installed', 'installed', 'installed-but-failed'] +) +def test_git_crypt(runner, yadm, paths, tmpdir, crypt): + """git-crypt tests""" + + paths.repo.ensure(dir=True) + bindir = tmpdir.mkdir('bin') + pgm = bindir.join('test-git-crypt') + + if crypt: + pgm.write(f'#!/bin/sh\necho git-crypt ran\n') + pgm.chmod(0o775) + if crypt == 'installed-but-failed': + pgm.write('false\n', mode='a') + + script = f""" + YADM_TEST=1 source {yadm} + YADM_REPO={paths.repo} + GIT_CRYPT_PROGRAM="{pgm}" + git_crypt "param1" + """ + + run = runner(command=['bash'], inp=script) + + if crypt: + if crypt == 'installed-but-failed': + assert run.failure + else: + assert run.success + assert run.out.strip() == 'git-crypt ran' + else: + assert run.failure + assert f"command '{pgm}' cannot be located" in run.out + assert run.err == '' diff --git a/yadm b/yadm index 9b328f4..b5ce07e 100755 --- a/yadm +++ b/yadm @@ -41,6 +41,7 @@ FULL_COMMAND="" GPG_PROGRAM="gpg" GIT_PROGRAM="git" AWK_PROGRAM=("gawk" "awk") +GIT_CRYPT_PROGRAM="git-crypt" J2CLI_PROGRAM="j2" ENVTPL_PROGRAM="envtpl" LSB_RELEASE_PROGRAM="lsb_release" @@ -76,45 +77,50 @@ function main() { # parse command line arguments local retval=0 - internal_commands="^(alt|bootstrap|clean|clone|config|decrypt|encrypt|enter|help|init|introspect|list|perms|upgrade|version)$" + internal_commands="^(alt|bootstrap|clean|clone|config|decrypt|encrypt|enter|git-crypt|help|init|introspect|list|perms|upgrade|version)$" if [ -z "$*" ] ; then # no argumnts will result in help() help elif [[ "$1" =~ $internal_commands ]] ; then # for internal commands, process all of the arguments - YADM_COMMAND="$1" + YADM_COMMAND="${1/-/_}" YADM_ARGS=() shift - while [[ $# -gt 0 ]] ; do - key="$1" - case $key in - -a) # used by list() - LIST_ALL="YES" - ;; - -d) # used by all commands - DEBUG="YES" - ;; - -f) # used by init() and clone() - FORCE="YES" - ;; - -l) # used by decrypt() - DO_LIST="YES" - [ "$YADM_COMMAND" = "config" ] && YADM_ARGS+=("$1") - ;; - -w) # used by init() and clone() - if [[ ! "$2" =~ ^/ ]] ; then - error_out "You must specify a fully qualified work tree" - fi - YADM_WORK="$2" - shift - ;; - *) # any unhandled arguments - YADM_ARGS+=("$1") - ;; - esac - shift - done + # commands listed below do not process any of the parameters + if [[ "$YADM_COMMAND" =~ ^(enter|git_crypt)$ ]] ; then + YADM_ARGS=("$@") + else + while [[ $# -gt 0 ]] ; do + key="$1" + case $key in + -a) # used by list() + LIST_ALL="YES" + ;; + -d) # used by all commands + DEBUG="YES" + ;; + -f) # used by init() and clone() + FORCE="YES" + ;; + -l) # used by decrypt() + DO_LIST="YES" + [ "$YADM_COMMAND" = "config" ] && YADM_ARGS+=("$1") + ;; + -w) # used by init() and clone() + if [[ ! "$2" =~ ^/ ]] ; then + error_out "You must specify a fully qualified work tree" + fi + YADM_WORK="$2" + shift + ;; + *) # any unhandled arguments + YADM_ARGS+=("$1") + ;; + esac + shift + done + fi [ ! -d "$YADM_WORK" ] && error_out "Work tree does not exist: [$YADM_WORK]" HOOK_COMMAND="$YADM_COMMAND" invoke_hook "pre" @@ -901,6 +907,11 @@ function encrypt() { } +function git_crypt() { + require_git_crypt + enter "${GIT_CRYPT_PROGRAM} $*" +} + function enter() { command="$*" require_shell @@ -983,6 +994,8 @@ Commands: yadm encrypt - Encrypt files yadm decrypt [-l] - Decrypt files yadm perms - Fix perms for private files + yadm enter [COMMAND] - Run sub-shell with GIT variables set + yadm git-crypt [OPTIONS] - Run git-crypt commands for the yadm repo Files: \$HOME/.config/yadm/config - yadm's configuration file @@ -1037,6 +1050,7 @@ decrypt encrypt enter gitconfig +git-crypt help init introspect @@ -1842,6 +1856,10 @@ function require_repo() { function require_shell() { [ -x "$SHELL" ] || error_out "\$SHELL does not refer to an executable." } +function require_git_crypt() { + command -v "$GIT_CRYPT_PROGRAM" &> /dev/null || + error_out "This functionality requires git-crypt to be installed, but the command '$GIT_CRYPT_PROGRAM' cannot be located." +} function bootstrap_available() { [ -f "$YADM_BOOTSTRAP" ] && [ -x "$YADM_BOOTSTRAP" ] && return return 1