From c808afc8846c7852d84cf4a0a8c0b9739c9f8eee Mon Sep 17 00:00:00 2001 From: Akemi Izuko Date: Thu, 27 Mar 2025 14:13:37 -0600 Subject: [PATCH] Scripts: add recursion support to psyncup --- bin/psyncup.py | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/bin/psyncup.py b/bin/psyncup.py index 1face57..bbeea6c 100755 --- a/bin/psyncup.py +++ b/bin/psyncup.py @@ -4,6 +4,7 @@ import datetime as dt import json import os import subprocess +import sys from pathlib import Path CONFIG_NAME = ".psyncup.json" @@ -45,6 +46,11 @@ parser.add_argument( action="store_true", help="Runs the rsync, without writing any changes to local or remote", ) +parser.add_argument( + "--recurse-up", + action="store_true", + help=f"Checks for {CONFIG_NAME} in all parent directories as well", +) parser.add_argument( "--no-compress", action="store_true", @@ -58,7 +64,7 @@ parser.add_argument( parser.add_argument( "--exec", type=str, - help="Run command on remote machine after sync", + help="Run command on remote, after sync is complete" ) group = parser.add_mutually_exclusive_group(required=True) @@ -111,11 +117,17 @@ def get_config(): if config["remote_dir"][-1] == "/" and config["remote_dir"] != "/": config["remote_dir"] = config["remote_dir"][:-1] except FileNotFoundError: - print(f"ERROR: {CONFIG_NAME} file was not found in this directory") + print( + f"ERROR: {CONFIG_NAME} file was not found in this directory", + file=sys.stderr + ) print(epilog) exit(1) except KeyError as e: - print(f"ERROR: {CONFIG_NAME} is missing required key {e}") + print( + f"ERROR: {CONFIG_NAME} is missing required key {e}", + file=sys.stderr + ) exit(1) return config @@ -208,13 +220,13 @@ def run_check(ssh_cmd, config): try: remote_config_str = check.communicate(timeout=6)[0].decode("utf-8") except subprocess.TimeoutExpired: - print("Failed to connect to remote (timed out)") + print("Failed to connect to remote (timed out)", file=sys.stderr) exit(1) try: remote_config = json.loads(remote_config_str) except json.JSONDecodeError: - print(f"Failed to read remote {CONFIG_NAME}") + print(f"Failed to read remote {CONFIG_NAME}", file=sys.stderr) exit(1) if not remote_config.get("update_date"): @@ -242,7 +254,7 @@ def run_up(rsync_cmd, remote_dir_str, config): rsync_code = subprocess.call(rsync_cmd) if rsync_code != 0: - print(f"Rsync exited with code {rsync_code}") + print(f"Rsync exited with code {rsync_code}", file=sys.stderr) exit(1) @@ -257,13 +269,8 @@ def run_down(rsync_cmd, remote_dir_str): exit(1) -def run_exec(cmd, config): - if config.get("ssh_jump") is not None: - ssh_cmd = ["ssh", "-t", "-J", config["ssh_jump"], config["ssh_remote"], cmd] - else: - ssh_cmd = ["ssh", "-t", config["ssh_remote"], cmd] - - subprocess.run(["ssh", "-t", config["ssh_remote"], cmd]) +def run_remote_exec(cmd, config): + subprocess.call(["ssh", "-t", config["ssh_remote"], cmd]) if __name__ == "__main__": @@ -271,6 +278,19 @@ if __name__ == "__main__": run_init() exit(0) + if args.recurse_up: + while True: + if Path(CONFIG_NAME).exists(): + break + elif os.getcwd() == '/': + print( + f"Error: No {CONFIG_NAME} found in any parent directory", + file=sys.stderr + ) + exit(1) + else: + os.chdir('..') + if args.pull: run_pull(args.pull, args.debug) args.down = True @@ -285,7 +305,7 @@ if __name__ == "__main__": run_up(rsync_cmd, remote_dir_str, config) if args.exec: - run_exec(args.exec, config) + run_remote_exec(args.exec, config) elif args.down: rsync_cmd, _, remote_dir_str = build_commands(args, config) run_down(rsync_cmd, remote_dir_str)