fix(kc_format): eliminate duplicate silo/manifest.json in .kc files #311

Merged
forbes merged 1 commits from fix/kc-duplicate-manifest into main 2026-02-21 15:51:00 +00:00
Showing only changes of commit 88efa2a6ae - Show all commits

View File

@@ -162,34 +162,28 @@ class _KcFormatObserver:
f"kc_format: pre_reinject hook failed: {exc}\n"
)
try:
# Ensure silo/manifest.json exists in entries and update modified_at.
# All manifest mutations happen here so only one copy is written.
if "silo/manifest.json" in entries:
try:
manifest = json.loads(entries["silo/manifest.json"])
except (json.JSONDecodeError, ValueError):
manifest = _default_manifest()
else:
manifest = _default_manifest()
manifest["modified_at"] = datetime.now(timezone.utc).strftime(
"%Y-%m-%dT%H:%M:%SZ"
)
entries["silo/manifest.json"] = (
json.dumps(manifest, indent=2) + "\n"
).encode("utf-8")
with zipfile.ZipFile(filename, "a") as zf:
existing = set(zf.namelist())
# Re-inject cached silo/ entries
if entries:
for name, data in entries.items():
if name not in existing:
zf.writestr(name, data)
existing.add(name)
# Ensure silo/manifest.json exists
if "silo/manifest.json" not in existing:
manifest = _default_manifest()
zf.writestr(
"silo/manifest.json",
json.dumps(manifest, indent=2) + "\n",
)
else:
# Update modified_at timestamp
raw = zf.read("silo/manifest.json")
manifest = json.loads(raw)
now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
if manifest.get("modified_at") != now:
manifest["modified_at"] = now
# ZipFile append mode can't overwrite; write new entry
# (last duplicate wins in most ZIP readers)
zf.writestr(
"silo/manifest.json",
json.dumps(manifest, indent=2) + "\n",
)
for name, data in entries.items():
if name not in existing:
zf.writestr(name, data)
existing.add(name)
except Exception as e:
FreeCAD.Console.PrintWarning(
f"kc_format: failed to update .kc silo/ entries: {e}\n"
@@ -209,17 +203,36 @@ def update_manifest_fields(filename, updates):
return
if not os.path.isfile(filename):
return
import shutil
import tempfile
try:
with zipfile.ZipFile(filename, "a") as zf:
if "silo/manifest.json" not in zf.namelist():
return
raw = zf.read("silo/manifest.json")
manifest = json.loads(raw)
manifest.update(updates)
zf.writestr(
"silo/manifest.json",
json.dumps(manifest, indent=2) + "\n",
)
fd, tmp = tempfile.mkstemp(suffix=".kc", dir=os.path.dirname(filename))
os.close(fd)
try:
with (
zipfile.ZipFile(filename, "r") as zin,
zipfile.ZipFile(tmp, "w", compression=zipfile.ZIP_DEFLATED) as zout,
):
found = False
for item in zin.infolist():
if item.filename == "silo/manifest.json":
if found:
continue # skip duplicate entries
found = True
raw = zin.read(item.filename)
manifest = json.loads(raw)
manifest.update(updates)
zout.writestr(
item.filename,
json.dumps(manifest, indent=2) + "\n",
)
else:
zout.writestr(item, zin.read(item.filename))
shutil.move(tmp, filename)
except BaseException:
os.unlink(tmp)
raise
except Exception as e:
FreeCAD.Console.PrintWarning(f"kc_format: failed to update manifest: {e}\n")