"""Sync a local directory to/from a bucket prefix (plan-and-apply). # Pull a slug folder to disk for local inspection bucket_sync.py hf://buckets/hetchyy/quranic-inspector-bucket/reciters/husary ./_scratch/husary # Push edits back bucket_sync.py ./_scratch/husary hf://buckets/hetchyy/quranic-inspector-bucket-dev/reciters/husary Use --dry-run first to see what would change; ``--yes-prod`` required when the destination is the prod bucket. """ from __future__ import annotations import argparse import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent)) import _bootstrap as bs # noqa: E402 def _is_prod_target(dst: str) -> bool: return f"hf://buckets/{bs.BUCKETS['prod']}/" in dst def main() -> int: p = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter ) p.add_argument("src", help="source: local path or hf://buckets/... URI") p.add_argument("dst", help="destination: local path or hf://buckets/... URI") p.add_argument("--dry-run", action="store_true", help="print planned ops, don't execute") p.add_argument("--delete", action="store_true", help="remove dst files that aren't in src") p.add_argument("--yes-prod", action="store_true", help="required to write to the prod bucket") a = p.parse_args() bs.ensure_utf8_stdout() bs.load_hf_token() if _is_prod_target(a.dst) and not a.yes_prod and not a.dry_run: print("refusing to sync TO prod bucket without --yes-prod", file=sys.stderr) return 2 from huggingface_hub import sync_bucket res = sync_bucket(src=a.src, dst=a.dst, delete=a.delete, dry_run=a.dry_run) # res surfaces the planned/applied ops; print compact summary. for line in str(res).splitlines(): print(line) return 0 if __name__ == "__main__": raise SystemExit(main())