from __future__ import annotations import argparse from pathlib import Path from .exact import exact_dedupe from .l2 import acoustic_dedupe from .scanner import scan from .watcher import watch def _db_path(root: Path, explicit: Path | None) -> Path: if explicit: return explicit if str(root).startswith("/music/"): return Path("/data/dedupe.db") return root / ".dedupe" / "dedupe.db" def main() -> None: parser = argparse.ArgumentParser(prog="am-deduper") sub = parser.add_subparsers(dest="cmd", required=True) for name in ("scan", "dedupe", "reconcile"): sp = sub.add_parser(name) sp.add_argument("root", type=Path) sp.add_argument("--db", type=Path, default=None) if name != "scan": sp.add_argument("--dry-run", action="store_true") wp = sub.add_parser("watch") wp.add_argument("root", type=Path) wp.add_argument("--db", type=Path, default=None) wp.add_argument("--l2", action="store_true", help="enable acoustic matching") args = parser.parse_args() db = _db_path(args.root, args.db) if args.cmd == "watch": watch(args.root, db, l2=args.l2) return indexed = scan(args.root, db) print(f"indexed={indexed} db={db}") if args.cmd == "scan": return exact = exact_dedupe(db, args.root, dry_run=args.dry_run) print(f"exact_hardlinked={len(exact)} dry_run={args.dry_run}") l2 = acoustic_dedupe(db, args.root, dry_run=args.dry_run) print(f"l2={l2} dry_run={args.dry_run}")