fix(kc_format): eliminate duplicate silo/manifest.json in .kc files #311
@@ -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")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user