import os import subprocess from huggingface_hub import snapshot_download # 绝对敏感:不同步 SENSITIVE_EXCLUDES = [ "auth.json", ".sandbox-secrets/**", ] # 建议不同步的大缓存/易变目录(减少文件数 & vanished) HEAVY_EXCLUDES = [ "plugins/cache/**", "projects/**", "shell-snapshots/**", "statsig/**", "todos/**", "log/**", "tmp/**", "sessions/**", ] def run_rsync(src: str, dst: str, excludes=None, delete=True): excludes = excludes or [] os.makedirs(dst, exist_ok=True) cmd = ["rsync", "-a"] if delete: cmd.append("--delete") for ex in excludes: cmd += ["--exclude", ex] cmd += [src.rstrip("/") + "/", dst.rstrip("/") + "/"] p = subprocess.run(cmd) # rsync code 24: some files vanished (often due to changing caches). Treat as warning. if p.returncode not in (0, 24): raise RuntimeError(f"rsync failed with code {p.returncode}") def main(): repo = os.getenv("DOTFILES_DATASET_REPO", "").strip() if not repo: print("DOTFILES_DATASET_REPO 未设置,跳过 dotfiles 同步") return token = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACE_HUB_TOKEN") if not token: print("HF_TOKEN 未设置(Private Dataset 必需),跳过 dotfiles 同步") return # 只下载你需要的目录,避免拉 1500+ 文件 allow = [ "ubuntu/home/.claude/**", "ubuntu/home/.codex/**", "dotfiles/home/.claude/**", "dotfiles/home/.codex/**", "ubuntu/project/**", "dotfiles/project/**", "project/**", ] local_dir = snapshot_download( repo_id=repo, repo_type="dataset", allow_patterns=allow, token=token, ) # 兼容你的结构:优先 ubuntu/home cand_home = [ os.path.join(local_dir, "ubuntu", "home"), os.path.join(local_dir, "dotfiles", "home"), os.path.join(local_dir, "home"), ] home_root = next((p for p in cand_home if os.path.isdir(p)), None) if not home_root: print("未找到 home 根目录(例如 ubuntu/home)") return claude_src = os.path.join(home_root, ".claude") codex_src = os.path.join(home_root, ".codex") # 只同步这两个目录,不碰 /home/user 其它文件 if os.path.isdir(claude_src): print(f"Sync ~/.claude: {claude_src} -> /home/user/.claude") run_rsync(claude_src, "/home/user/.claude", excludes=HEAVY_EXCLUDES, delete=True) else: print("未找到 .claude 目录,跳过") if os.path.isdir(codex_src): excludes = SENSITIVE_EXCLUDES + HEAVY_EXCLUDES print(f"Sync ~/.codex: {codex_src} -> /home/user/.codex (exclude auth/secrets)") run_rsync(codex_src, "/home/user/.codex", excludes=excludes, delete=True) else: print("未找到 .codex 目录,跳过") # 可选:项目级配置(如果你未来加了) cand_proj = [ os.path.join(local_dir, "ubuntu", "project"), os.path.join(local_dir, "dotfiles", "project"), os.path.join(local_dir, "project"), ] proj_src = next((p for p in cand_proj if os.path.isdir(p)), None) if proj_src: print(f"Sync project: {proj_src} -> /home/user/work") run_rsync(proj_src, "/home/user/work", excludes=[], delete=True) else: print("未找到 PROJECT dotfiles 源目录(可忽略)") print("Dotfiles sync done.") if __name__ == "__main__": main()