diff --git a/AUTHORS.rst b/AUTHORS.rst index 146245f..5330139 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -6,6 +6,7 @@ In alphabetical order: - Ben Boeckel - Christian Geier - Clément Mondon +- Corey Hinshaw - Hugo Osvaldo Barrera - Julian Mehne - Malte Kiefer diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8202b36..b09a0c0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,6 +12,7 @@ may want to subscribe to `GitHub's tag feed Version 0.19.0 ============== +- Add "shell" password fetch strategy to pass command string to a shell. - Add "description" and "order" as metadata. These fetch the CalDAV: calendar-description, CardDAV:addressbook-description and apple-ns:calendar-order properties. diff --git a/docs/keyring.rst b/docs/keyring.rst index b3fc442..747553d 100644 --- a/docs/keyring.rst +++ b/docs/keyring.rst @@ -38,6 +38,12 @@ You can fetch the username as well:: Or really any kind of parameter in a storage section. +You can also pass the command as a string to be executed in a shell:: + + [storage foo] + ... + password.fetch = ["shell", "~/.local/bin/get-my-password | head -n1"] + With pass_ for example, you might find yourself writing something like this in your configuration file:: diff --git a/tests/system/cli/test_fetchparams.py b/tests/system/cli/test_fetchparams.py index 8b1957b..f458760 100644 --- a/tests/system/cli/test_fetchparams.py +++ b/tests/system/cli/test_fetchparams.py @@ -11,7 +11,7 @@ def test_get_password_from_command(tmpdir, runner): collections = ["a", "b", "c"] [storage foo] - type = "filesystem" + type.fetch = ["shell", "echo filesystem"] path = "{base}/foo/" fileext.fetch = ["command", "echo", ".txt"] diff --git a/vdirsyncer/cli/fetchparams.py b/vdirsyncer/cli/fetchparams.py index 6cf1e44..2ef6c4f 100644 --- a/vdirsyncer/cli/fetchparams.py +++ b/vdirsyncer/cli/fetchparams.py @@ -72,7 +72,7 @@ def _fetch_value(opts, key): return rv -def _strategy_command(*command: str): +def _strategy_command(*command: str, shell: bool = False): """Execute a user-specified command and return its output.""" import subprocess @@ -82,18 +82,26 @@ def _strategy_command(*command: str): expanded_command = list(map(expand_path, command)) try: - stdout = subprocess.check_output(expanded_command, universal_newlines=True) + stdout = subprocess.check_output( + expanded_command, universal_newlines=True, shell=shell + ) return stdout.strip("\n") except OSError as e: cmd = " ".join(expanded_command) raise exceptions.UserError(f"Failed to execute command: {cmd}\n{str(e)}") +def _strategy_shell(*command: str): + """Execute a user-specified command string in a shell and return its output.""" + return _strategy_command(*command, shell=True) + + def _strategy_prompt(text): return click.prompt(text, hide_input=True) STRATEGIES = { "command": _strategy_command, + "shell": _strategy_shell, "prompt": _strategy_prompt, }