diff --git a/syncall/app_utils.py b/syncall/app_utils.py index bd38207..cfaf645 100644 --- a/syncall/app_utils.py +++ b/syncall/app_utils.py @@ -304,19 +304,22 @@ def fetch_from_pass_manager(password_path: str, allow_fail=False) -> str | None: passwd = None try: - passwd = read_gpg_token(pass_full_path) - except subprocess.CalledProcessError as err: + # pass format allows additional metadata (username, url, etc.) + # the password itself is a single string on the first line + passwd = read_gpg_token(pass_full_path).split("\n")[0] + except (subprocess.CalledProcessError, AttributeError) as err: if not allow_fail: - logger.error( - "\n".join( - [ - f"Couldn't read {password_path} from pass\n\nFull path:" - f" {pass_full_path}", - non_empty("stdout", err.stdout.decode("utf-8"), join_with=": "), - non_empty("stderr", err.stderr.decode("utf-8"), join_with=": "), - ], - ), - ) + log_lines = [ + f"Couldn't read {password_path} from pass\n\nFull path: {pass_full_path}", + ] + + if hasattr(err, "stdout") and hasattr(err, "stderr"): + log_lines += [ + non_empty("stdout", err.stdout.decode("utf-8"), join_with=": "), + non_empty("stderr", err.stderr.decode("utf-8"), join_with=": "), + ] + + logger.error("\n".join(log_lines)) sys.exit(1) return passwd diff --git a/tests/test_app_utils.py b/tests/test_app_utils.py index ccca4d6..a10b46f 100644 --- a/tests/test_app_utils.py +++ b/tests/test_app_utils.py @@ -5,6 +5,7 @@ from syncall.app_utils import ( cache_or_reuse_cached_combination, fetch_app_configuration, + fetch_from_pass_manager, inform_about_combination_name_usage, report_toplevel_exception, ) @@ -98,3 +99,20 @@ def test_cache_or_reuse_cached_combination(fs, caplog, mock_prefs_manager): assert "Loading cached configuration" in caplog.text assert "1__2__3" in caplog.text caplog.clear() + + +def test_fetch_from_pass_manager(): + with patch("syncall.app_utils.valid_path", return_value="password_store"): + with patch( + "syncall.app_utils.read_gpg_token", + return_value="foobar\nusername: foo@bar", + ): + assert fetch_from_pass_manager("password_store") == "foobar" + + with patch("syncall.app_utils.read_gpg_token", return_value=""): + assert fetch_from_pass_manager("password_store") == "" + + with patch("syncall.app_utils.read_gpg_token", return_value=None): + with pytest.raises(SystemExit): + assert fetch_from_pass_manager("password_store") + assert fetch_from_pass_manager("password_store", allow_fail=True) is None