diff --git a/update_mods.py b/update_mods.py index 70fcf67..732e68a 100644 --- a/update_mods.py +++ b/update_mods.py @@ -102,6 +102,7 @@ def main() -> None: COL_GROUP = 24 total_checked = total_updated = total_bytes = 0 + total_removed = 0 not_on_server = [] for group, folder_name, mod_dir in targets: @@ -123,46 +124,65 @@ def main() -> None: all_files = list_mod_files(folder_url, session) if not args.force else stale checked = len(all_files) if not args.force else len(stale) - if not stale: + # Find local files that no longer exist on the server (orphans) + server_rel = {rel for rel, _, _ in all_files} + orphans = [ + f for f in mod_dir.rglob("*") if f.is_file() + and str(f.relative_to(mod_dir)).replace("\\", "/") not in server_rel + ] + + if not stale and not orphans: print(f" [=] {folder_name:<{COL_MOD}} {group:<{COL_GROUP}} {checked} files up-to-date") total_checked += checked continue # Download stale files mod_bytes = 0 - with tqdm( - total=len(stale), unit="file", - desc=f" {folder_name[-COL_MOD:]:<{COL_MOD}}", - position=0, leave=True, dynamic_ncols=True, - ) as file_bar: - for rel, url, size in stale: - dest_file = mod_dir / rel - with tqdm( - total=size if size else None, - unit="B", unit_scale=True, unit_divisor=1024, - desc=f" {rel[-40:]:40s}", - position=1, leave=False, dynamic_ncols=True, - ) as chunk_bar: - n = download_file(url, dest_file, session, - on_chunk=lambda b: chunk_bar.update(b)) - mod_bytes += n - file_bar.update(1) + if stale: + with tqdm( + total=len(stale), unit="file", + desc=f" {folder_name[-COL_MOD:]:<{COL_MOD}}", + position=0, leave=True, dynamic_ncols=True, + ) as file_bar: + for rel, url, size in stale: + dest_file = mod_dir / rel + with tqdm( + total=size if size else None, + unit="B", unit_scale=True, unit_divisor=1024, + desc=f" {rel[-40:]:40s}", + position=1, leave=False, dynamic_ncols=True, + ) as chunk_bar: + n = download_file(url, dest_file, session, + on_chunk=lambda b: chunk_bar.update(b)) + mod_bytes += n + file_bar.update(1) + + # Remove orphan files + for orphan in orphans: + tqdm.write(f" [-] orphan removed: {orphan.relative_to(mod_dir)}") + orphan.unlink() total_checked += checked total_updated += len(stale) total_bytes += mod_bytes - print(f" [+] {folder_name:<{COL_MOD}} {group:<{COL_GROUP}} " - f"{checked} files {len(stale)} updated ({_fmt_bytes(mod_bytes)})") + total_removed += len(orphans) + parts = [f"{checked} files"] + if stale: + parts.append(f"{len(stale)} updated ({_fmt_bytes(mod_bytes)})") + if orphans: + parts.append(f"{len(orphans)} orphan(s) removed") + print(f" [+] {folder_name:<{COL_MOD}} {group:<{COL_GROUP}} {' '.join(parts)}") print(f"\n{'='*56}") print(f" Total: {total_checked} files checked, " f"{total_updated} updated, " + f"{total_removed} orphan(s) removed, " f"{_fmt_bytes(total_bytes)} downloaded") if not_on_server: print(f" Not found on server ({len(not_on_server)}): {', '.join(not_on_server)}") print(f"{'='*56}\n") - if total_updated == 0 and not not_on_server: + if total_updated == 0 and total_removed == 0 and not not_on_server: print(" All mods are up-to-date.\n")