The path-preservation proof resolves access ids to their default paths too
An access named by id (issue 153) resolves to the path the definition still carries when the assignment says nothing, and the proof compares that — the same rule as a placed directory.
This commit is contained in:
@@ -60,6 +60,11 @@ func TestPlacedDirectoriesKeepTheirPaths(t *testing.T) {
|
|||||||
// (issue 119's conversion), and what must not move is the path a machine sees.
|
// (issue 119's conversion), and what must not move is the path a machine sees.
|
||||||
was = resolvedTree(was, dirsFor(earlier, Rendering{}), module, t)
|
was = resolvedTree(was, dirsFor(earlier, Rendering{}), module, t)
|
||||||
resolved := resolvedTree(is, dirsFor(m, Rendering{}), module, t)
|
resolved := resolvedTree(is, dirsFor(m, Rendering{}), module, t)
|
||||||
|
// An access named by id resolves to the path the definition still carries as its default
|
||||||
|
// (issue 153) — the same rule as a placed directory: an assignment that says nothing moves
|
||||||
|
// nothing.
|
||||||
|
was = accessesResolved(was, earlier)
|
||||||
|
resolved = accessesResolved(resolved, m)
|
||||||
if !reflect.DeepEqual(was, resolved) {
|
if !reflect.DeepEqual(was, resolved) {
|
||||||
wasJSON, _ := json.MarshalIndent(was, "", " ")
|
wasJSON, _ := json.MarshalIndent(was, "", " ")
|
||||||
isJSON, _ := json.MarshalIndent(resolved, "", " ")
|
isJSON, _ := json.MarshalIndent(resolved, "", " ")
|
||||||
@@ -128,3 +133,48 @@ func firstDifference(a, b string) string {
|
|||||||
}
|
}
|
||||||
return "(the difference is beyond the shorter document)"
|
return "(the difference is beyond the shorter document)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// accessesResolved fills every ${access:<id>} with the default path the definition carries for that
|
||||||
|
// access, and drops the id, so a manifest that names its accesses is compared by the paths a machine
|
||||||
|
// with no placement receives.
|
||||||
|
func accessesResolved(node any, m Manifest) any {
|
||||||
|
defaults := map[string]string{}
|
||||||
|
for _, a := range m.Accesses {
|
||||||
|
if a.ID != "" && a.Path != "" {
|
||||||
|
defaults[a.ID] = a.Path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var walk func(any) any
|
||||||
|
walk = func(n any) any {
|
||||||
|
switch v := n.(type) {
|
||||||
|
case map[string]any:
|
||||||
|
out := map[string]any{}
|
||||||
|
for k, child := range v {
|
||||||
|
if k == "id" {
|
||||||
|
if _, isAccess := v["mode"]; isAccess && v["type"] == nil {
|
||||||
|
if _, hasPath := v["path"]; hasPath {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out[k] = walk(child)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
case []any:
|
||||||
|
out := make([]any, len(v))
|
||||||
|
for i, child := range v {
|
||||||
|
out[i] = walk(child)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
case string:
|
||||||
|
return accessRef.ReplaceAllStringFunc(v, func(ref string) string {
|
||||||
|
if p, ok := defaults[accessRef.FindStringSubmatch(ref)[1]]; ok {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
return ref
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
return walk(node)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user