"""补救:按**当前实际布局**重写各档壁纸预设里的资源路径。 背景:migrate-walls.py 的映射键在 Windows 下是反斜杠,而预设里是 `./effects/x.json` 这种正斜杠, 查表全落空 → 文件搬了、预设没改。这里不靠任何映射,直接**在壁纸目录里找**该文件现在在哪: ./effects/<名>.json → spines/<名>/<名>.json ./images/<…> → spines/<骨架>/<文件>(若该文件是某 atlas 声明的页或骨架自己的贴图) 否则 → scene/<文件> ./images/scene/<文件> → scene/<文件> 每个改写都要求目标**真实存在**,否则报错而不是写一个坏路径。 """ from __future__ import annotations import json import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] WALLS = ROOT / "wallpapers" APPLY = "--apply" in sys.argv PAGE_EXT = re.compile(r"\.(png|webp|jpg|jpeg)$", re.IGNORECASE) def atlas_pages(text: str) -> list[str]: return [l.strip() for l in text.splitlines() if l.strip() and ":" not in l.strip() and PAGE_EXT.search(l.strip())] def owner_of(wall: Path, basename: str) -> str | None: """这个文件现在归哪个目录(spines/<名> 还是 scene)。""" for atlas in (wall / "spines").rglob("*.atlas"): if basename in atlas_pages(atlas.read_text(encoding="utf-8")): return f"spines/{atlas.parent.name}" for spine_dir in (wall / "spines").iterdir() if (wall / "spines").is_dir() else []: if (spine_dir / basename).exists(): return f"spines/{spine_dir.name}" if (wall / "scene" / basename).exists(): return "scene" return None failed: list[str] = [] for wall in sorted(p.parent for p in WALLS.rglob("preset.template.json")): preset_path = wall / "preset.template.json" preset = json.loads(preset_path.read_text(encoding="utf-8")) changed: list[str] = [] def rewrite(value: object) -> object: if isinstance(value, str) and value.startswith("./") and "/" in value[2:]: basename = value.rsplit("/", 1)[-1] owner = owner_of(wall, basename) if owner and value != f"./{owner}/{basename}": changed.append(f"{value} → ./{owner}/{basename}") return f"./{owner}/{basename}" if owner is None: failed.append(f"{wall.relative_to(ROOT)}: {value} 在磁盘上找不到") if isinstance(value, dict): return {k: rewrite(v) for k, v in value.items()} if isinstance(value, list): return [rewrite(v) for v in value] return value new_preset = rewrite(preset) print(f"\n== {wall.relative_to(ROOT)}") for c in changed: print(" " + c) if APPLY and changed: preset_path.write_text(json.dumps(new_preset, ensure_ascii=False, indent="\t") + "\n", encoding="utf-8") if failed: print("\n✗ 以下路径找不到对应文件(未改写):") for f in failed: print(" " + f) sys.exit(1) print(f"\n{'已重写' if APPLY else '将重写'} {len(changed) if False else ''}{'(dry-run)' if not APPLY else ''}")