Answer stability round 1: a manifest refuses an entry inside another category and a path an entry repeats

This commit is contained in:
2026-10-10 11:16:52 +02:00
committed by Lillem4n
parent ce2da330f7
commit fcd7ebf736
+22 -2
View File
@@ -91,8 +91,10 @@ func decodeIndex(v any) (map[string]IndexEntry, []error) {
index[p] = e index[p] = e
} }
for _, p := range sortedKeys(index) { for _, p := range sortedKeys(index) {
if err := checkParent(index, p); err != nil { for _, err := range []error{checkOutside(index, p), checkParent(index, p)} {
errs = append(errs, fmt.Errorf("index entry %q: %w", p, err)) if err != nil {
errs = append(errs, fmt.Errorf("index entry %q: %w", p, err))
}
} }
} }
return index, errs return index, errs
@@ -146,6 +148,7 @@ func decodePaths(v any) ([]string, error) {
return nil, fmt.Errorf("paths must be a list, not %s", jsonvalue.Kind(v)) return nil, fmt.Errorf("paths must be a list, not %s", jsonvalue.Kind(v))
} }
out := make([]string, 0, len(items)) out := make([]string, 0, len(items))
seen := map[string]bool{}
var errs []error var errs []error
for i, item := range items { for i, item := range items {
q, isString := item.(string) q, isString := item.(string)
@@ -159,11 +162,28 @@ func decodePaths(v any) ([]string, error) {
continue continue
} }
} }
if seen[q] {
errs = append(errs, fmt.Errorf("paths item %d repeats %q", i+1, q))
continue
}
seen[q] = true
out = append(out, q) out = append(out, q)
} }
return out, errors.Join(errs...) return out, errors.Join(errs...)
} }
// checkOutside refuses an entry whose path passes through another entry's category.
func checkOutside(index map[string]IndexEntry, p string) error {
segs := strings.Split(p, ".")
for n := 1; n < len(segs); n++ {
outer := strings.Join(segs[:n], ".")
if _, isEntry := index[outer]; isEntry {
return fmt.Errorf("%q is a category, so it holds no other", outer)
}
}
return nil
}
// checkParent refuses a parent naming no entry beside p: a table loads with its parent, // checkParent refuses a parent naming no entry beside p: a table loads with its parent,
// from one source. // from one source.
func checkParent(index map[string]IndexEntry, p string) error { func checkParent(index map[string]IndexEntry, p string) error {