Apply audit fixes for pack-sequence (14 findings, 28 new tests)

Cross-validation audit by Codex + Opus identified 14 issues:

CRITICAL:
- Fix _find_subdir_ci() prefix match accepting wrong folders (e.g.
  Publish_old). Now uses exact case-insensitive match.

HIGH:
- Add pack-sequence CLI subcommand with unambiguous arg parsing.
  Deprecate --sequence on pack (nargs='+' consumed the target).
- Fix Windows UNC/drive path normalization in bpathlib.make_absolute()
- Fix ZIP failure losing traceback + progress bar stuck on error
- Fix os.path.commonpath crash on cross-drive paths (new
  derive_common_project helper)
- Fix progress bar saturating at 40% during trace (log scale)

MEDIUM:
- Add per-shot error isolation in sequence scan (collect all errors)
- Add memory warning for >50 files in sequence pack
- Improve pack-info.txt with dedup stats
- Wrap single Path in list for old operators (type consistency)

LOW/INFO:
- Document VERSION_RE pattern
- Add TASK_CHOICE_ITEMS empty guard

28 new tests in tests/test_sequence_pack.py, 0 regressions.

Co-Authored-By: Mario Hawat <mario@autourdeminuit.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 16:56:36 +01:00
co-authored by mario.hawat Claude Opus 4.6
parent 05d97cdeda
commit b8cfe5c1ac
7 changed files with 576 additions and 64 deletions
+18 -1
View File
@@ -245,6 +245,13 @@ class Packer:
in the execute() function.
"""
if len(self.blendfiles) > 50:
log.info(
"Packing %d blend files. Peak memory may be high (~%.1f GB estimated).",
len(self.blendfiles),
len(self.blendfiles) * 0.005,
)
self._progress_cb.pack_start()
self._new_location_paths = set()
self._output_paths = []
@@ -656,12 +663,22 @@ class Packer:
with infopath.open("wt", encoding="utf8") as infofile:
print("This is a Blender Asset Tracer pack.", file=infofile)
if len(self._output_paths) > 1:
print("This pack contains the following blend files:", file=infofile)
print(
"This pack contains %d blend files:" % len(self._output_paths),
file=infofile,
)
for op in self._output_paths:
print(
" %s" % op.relative_to(self._target_path).as_posix(),
file=infofile,
)
print(
"Total unique assets: %d" % len(self._actions), file=infofile
)
if self.missing_files:
print(
"Missing files: %d" % len(self.missing_files), file=infofile
)
else:
print("Start by opening the following blend file:", file=infofile)
print(
+1 -1
View File
@@ -83,7 +83,7 @@ class ZipTransferrer(transfer.FileTransferer):
except Exception:
# We have to catch exceptions in a broad way, as this is running in
# a separate thread, and exceptions won't otherwise be seen.
log.exception("Error transferring %s to %s", src, dst)
log.exception("Error writing %s to ZIP archive at %s", src, dst)
# Put the files to copy back into the queue, and abort. This allows
# the main thread to inspect the queue and see which files were not
# copied. The one we just failed (due to this exception) should also