From 7f8fd79c86c286523efa46cf20de8dad68c3a2a3 Mon Sep 17 00:00:00 2001 From: lou Date: Mon, 10 Aug 2026 19:34:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=87=E4=BB=BD=E5=A2=9E=E9=87=8F=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D:=20=E5=A4=87=E4=BB=BD=E5=89=8D=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E5=90=8C=E6=AD=A5=E5=89=AA=E6=9E=9D=20(manifest=20?= =?UTF-8?q?=E4=B8=AD=E6=9C=8D=E5=8A=A1=E5=99=A8=E5=B7=B2=E5=88=A0=E7=9A=84?= =?UTF-8?q?=E6=89=B9=E6=AC=A1=E7=A7=BB=E9=99=A4,=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E7=BA=B3=E5=85=A5=E5=A2=9E=E9=87=8F)=20-=20?= =?UTF-8?q?=E8=A7=A3=E5=86=B3'=E6=97=A0=E5=A2=9E=E9=87=8F=E6=9B=B4?= =?UTF-8?q?=E6=96=B0'=E4=BD=86=E6=9C=8D=E5=8A=A1=E5=99=A8=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=B7=B2=E5=88=A0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backup.py | 25 +++++++++++++++++++ debian/7z-encrypt-client/DEBIAN/control | 2 +- debian/7z-encrypt-client/DEBIAN/md5sums | 2 +- .../usr/share/7z-encrypt/backup.py | 25 +++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/backup.py b/backup.py index b300d60..be57905 100644 --- a/backup.py +++ b/backup.py @@ -196,8 +196,33 @@ def _upload_tar(tar_path: Path, chunk_mb: int) -> str: return str(receipt["file_id"]) +def _prune_manifest(name: str, manifest: dict[str, Any]) -> None: + """服务器同步: 服务器已不存在的批次从 manifest 移除, 其文件重新纳入增量 + + 服务器文件被删 (手动/清理) 后 manifest 仍认为已备份会导致"无增量更新" + 但实际恢复不到——以服务器 file_id 为准剪枝, 下次备份自动重传。 + """ + from transfer import TransferClient + try: + client = TransferClient(_server(), token=_token()) + server_ids = {f["file_id"] for f in client.list_files()} + except Exception: + return # 服务器不可达: 保留 manifest, 不阻塞备份 + batches = manifest.get("batches", {}) + stale = [bn for bn, b in batches.items() if b.get("server_id") not in server_ids] + if not stale: + return + for bn in stale: + for fp in batches[bn].get("files", []): + manifest.setdefault("files", {}).pop(fp, None) + batches.pop(bn) + print(f"[备份] 服务器同步: 移除 {len(stale)} 个失效批次 (服务器文件已删), 将重新备份") + _save_manifest(name, manifest) + + def backup(name: str, chunk_mb: int = 10) -> int: manifest = _load_manifest(name) + _prune_manifest(name, manifest) files = _scan_new(name, manifest) if not files: print(f"[备份] {name}: 无新增文件, 已是最新") diff --git a/debian/7z-encrypt-client/DEBIAN/control b/debian/7z-encrypt-client/DEBIAN/control index 8eeb5e3..9c26585 100644 --- a/debian/7z-encrypt-client/DEBIAN/control +++ b/debian/7z-encrypt-client/DEBIAN/control @@ -2,7 +2,7 @@ Package: 7z-encrypt-client Version: 1.0.0 Architecture: all Maintainer: edgevoid -Installed-Size: 125 +Installed-Size: 126 Depends: python3 (>= 3.10), python3-venv, p7zip-full Section: utils Priority: optional diff --git a/debian/7z-encrypt-client/DEBIAN/md5sums b/debian/7z-encrypt-client/DEBIAN/md5sums index 87bdf84..f0de9a9 100644 --- a/debian/7z-encrypt-client/DEBIAN/md5sums +++ b/debian/7z-encrypt-client/DEBIAN/md5sums @@ -2,7 +2,7 @@ 440c53f84f5722b5146959c8fc6d7a23 usr/bin/sz-config ec8cf0df841e479689ccb681f6168ccc usr/bin/sz-transfer 0ba5b8147990daa7fd07344952c42847 usr/bin/sz-tui -1c8e2524738649398a4385a3f2a9e3c6 usr/share/7z-encrypt/backup.py +d0faeb4f34bb1cec041c9a4616e529be usr/share/7z-encrypt/backup.py dcb31e74e0a6ee8073337fc4fb2acf99 usr/share/7z-encrypt/config.py 8a064c0b3c21d50812a3fd69a320d862 usr/share/7z-encrypt/crypto.py 21062e04f8c7f4471881a39c489dfa73 usr/share/7z-encrypt/metadata.py diff --git a/debian/7z-encrypt-client/usr/share/7z-encrypt/backup.py b/debian/7z-encrypt-client/usr/share/7z-encrypt/backup.py index b300d60..be57905 100644 --- a/debian/7z-encrypt-client/usr/share/7z-encrypt/backup.py +++ b/debian/7z-encrypt-client/usr/share/7z-encrypt/backup.py @@ -196,8 +196,33 @@ def _upload_tar(tar_path: Path, chunk_mb: int) -> str: return str(receipt["file_id"]) +def _prune_manifest(name: str, manifest: dict[str, Any]) -> None: + """服务器同步: 服务器已不存在的批次从 manifest 移除, 其文件重新纳入增量 + + 服务器文件被删 (手动/清理) 后 manifest 仍认为已备份会导致"无增量更新" + 但实际恢复不到——以服务器 file_id 为准剪枝, 下次备份自动重传。 + """ + from transfer import TransferClient + try: + client = TransferClient(_server(), token=_token()) + server_ids = {f["file_id"] for f in client.list_files()} + except Exception: + return # 服务器不可达: 保留 manifest, 不阻塞备份 + batches = manifest.get("batches", {}) + stale = [bn for bn, b in batches.items() if b.get("server_id") not in server_ids] + if not stale: + return + for bn in stale: + for fp in batches[bn].get("files", []): + manifest.setdefault("files", {}).pop(fp, None) + batches.pop(bn) + print(f"[备份] 服务器同步: 移除 {len(stale)} 个失效批次 (服务器文件已删), 将重新备份") + _save_manifest(name, manifest) + + def backup(name: str, chunk_mb: int = 10) -> int: manifest = _load_manifest(name) + _prune_manifest(name, manifest) files = _scan_new(name, manifest) if not files: print(f"[备份] {name}: 无新增文件, 已是最新")