Добавлена возможность обратной синхронизации в sync через флаг -r

main
ilyukhin 2 months ago
parent a92d40464a
commit 10d2e0d752

41
dsync

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
VERSION = "0.2.1" VERSION = "0.3.0"
import re import re
import sys import sys
@ -360,10 +360,13 @@ def parse_rsync_action(line: str) -> str:
else f"{direction} {item_type.upper()}: {filename} ({', '.join(details)})" else f"{direction} {item_type.upper()}: {filename} ({', '.join(details)})"
def sync() -> None: def sync(reverse: bool = False) -> None:
"""Synchronize local project directory to all nodes, honoring per-node dirs. """Synchronize local project directory to all nodes.
Uses rsync with `--delete` so remote deletions track local deletions. If reverse=True:
1) Pull files that exist on remotes but are missing locally into master
(without overwriting existing local files).
2) Then push the updated master to all nodes using --delete (to converge).
""" """
config, project_dir = load_config() config, project_dir = load_config()
ignore_file = project_dir / config.get("ignore_file", ".dsyncignore") ignore_file = project_dir / config.get("ignore_file", ".dsyncignore")
@ -377,6 +380,30 @@ def sync() -> None:
print(colored("No nodes configured", Colors.YELLOW)) print(colored("No nodes configured", Colors.YELLOW))
return return
# --- Reverse phase: pull missing files from each node into master ---
if reverse:
print(colored("[Reverse] Pulling missing files from nodes into master...", Colors.CYAN))
for n in nodes:
node = n["name"]
rdir = n["remote_dir"] or master_dir
remote = f"{node}:{rdir}/" # trailing slash to copy dir contents
print(f"[Reverse] From {remote} -> {project_dir}/ (ignore-existing)")
# --ignore-existing ensures we only fetch files that do NOT exist locally.
pull_cmd = [
"rsync", "-avz", "--ignore-existing",
f"--exclude-from={ignore_file}",
"-e", "ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10",
remote, f"{project_dir}/"
]
try:
subprocess.run(pull_cmd, check=True, capture_output=True, text=True)
print(colored(f"[OK] Pulled missing files from {node}", Colors.GREEN))
except subprocess.CalledProcessError as e:
print(colored(f"[X] Failed reverse-pull from {node} ({rdir}): {e}", Colors.RED))
print() # spacing
# --- Forward phase: push master to all nodes (same as before) ---
success_count = 0 success_count = 0
failed_nodes: List[str] = [] failed_nodes: List[str] = []
@ -655,7 +682,7 @@ Usage:
dsync clear-node-dir <node> Clear node dir (fallback to master_dir) dsync clear-node-dir <node> Clear node dir (fallback to master_dir)
dsync list-nodes List nodes with their remote dirs dsync list-nodes List nodes with their remote dirs
dsync status Show sync status for all nodes (with dirs) dsync status Show sync status for all nodes (with dirs)
dsync sync Sync to all configured nodes dsync sync [-r | --reverse] Sync; reverse pulls missing files from nodes to master first
dsync help Show this help message dsync help Show this help message
dsync version Print dsync version dsync version Print dsync version
@ -706,7 +733,9 @@ if __name__ == "__main__":
elif cmd == "status": elif cmd == "status":
status() status()
elif cmd == "sync": elif cmd == "sync":
sync() # Parse optional flags for sync, e.g., dsync sync -r / --reverse
reverse = any(arg in ("-r", "--reverse") for arg in sys.argv[2:])
sync(reverse=reverse)
elif cmd in ("-h", "--help", "help"): elif cmd in ("-h", "--help", "help"):
show_help() show_help()
elif cmd in ("-v", "--version", "version"): elif cmd in ("-v", "--version", "version"):

Loading…
Cancel
Save