Skip to content

Commit f6a7cd8

Browse files
committed
fix: guard corrupted registry entries and make manifest authoritative
- Add isinstance(meta, dict) guard in bash registry parsing so corrupted entries are skipped instead of breaking priority ordering - Only use convention-based file lookup when the manifest does not list the requested template, making preset.yml authoritative and preventing stray on-disk files from creating unintended layers
1 parent d43011c commit f6a7cd8

2 files changed

Lines changed: 11 additions & 6 deletions

File tree

scripts/bash/common.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,8 @@ try:
320320
with open(os.environ['SPECKIT_REGISTRY']) as f:
321321
data = json.load(f)
322322
presets = data.get('presets', {})
323-
for pid, meta in sorted(presets.items(), key=lambda x: x[1].get('priority', 10)):
324-
if meta.get('enabled', True) is not False:
323+
for pid, meta in sorted(presets.items(), key=lambda x: x[1].get('priority', 10) if isinstance(x[1], dict) else 10):
324+
if isinstance(meta, dict) and meta.get('enabled', True) is not False:
325325
print(pid)
326326
except Exception:
327327
sys.exit(1)
@@ -408,8 +408,8 @@ try:
408408
with open(os.environ['SPECKIT_REGISTRY']) as f:
409409
data = json.load(f)
410410
presets = data.get('presets', {})
411-
for pid, meta in sorted(presets.items(), key=lambda x: x[1].get('priority', 10)):
412-
if meta.get('enabled', True) is not False:
411+
for pid, meta in sorted(presets.items(), key=lambda x: x[1].get('priority', 10) if isinstance(x[1], dict) else 10):
412+
if isinstance(meta, dict) and meta.get('enabled', True) is not False:
413413
print(pid)
414414
except Exception:
415415
sys.exit(1)

src/specify_cli/presets.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,6 +2701,7 @@ def _find_in_subdirs(base_dir: Path) -> Optional[Path]:
27012701
strategy = "replace"
27022702
manifest_file_path = None
27032703
manifest_has_strategy = False
2704+
manifest_found_entry = False
27042705
manifest = self._get_manifest(pack_dir)
27052706
if manifest:
27062707
for tmpl in manifest.templates:
@@ -2709,16 +2710,20 @@ def _find_in_subdirs(base_dir: Path) -> Optional[Path]:
27092710
strategy = tmpl.get("strategy", "replace")
27102711
manifest_has_strategy = "strategy" in tmpl
27112712
manifest_file_path = tmpl.get("file")
2713+
manifest_found_entry = True
27122714
break
2713-
# Use manifest file path if specified, otherwise convention-based lookup
2715+
# Use manifest file path if specified, otherwise convention-based
2716+
# lookup — but only when the manifest doesn't exist or doesn't
2717+
# list this template, so preset.yml stays authoritative.
27142718
candidate = None
27152719
if manifest_file_path:
27162720
manifest_candidate = pack_dir / manifest_file_path
27172721
if manifest_candidate.exists():
27182722
candidate = manifest_candidate
27192723
# Explicit file path that doesn't exist: skip convention
27202724
# fallback to avoid masking typos or picking up unintended files.
2721-
elif candidate is None:
2725+
elif not manifest_found_entry:
2726+
# Manifest doesn't list this template — check convention paths
27222727
candidate = _find_in_subdirs(pack_dir)
27232728
if candidate:
27242729
# Legacy fallback: if manifest doesn't explicitly declare a

0 commit comments

Comments
 (0)