Ask git ls-tree for nested named paths in rounds: given go and go/seats/x together it lists go's children, so mesh-contracts' preview failed (issue 1966)
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -82,18 +82,20 @@ func narrow(ctx context.Context, run forgekey.Runner, env []string, dir, commit,
|
||||
for i, p := range paths {
|
||||
full[i] = path.Join(mdir, p)
|
||||
}
|
||||
r := run(ctx, env, "git", append([]string{"-C", dir, "ls-tree", "-z", commit, "--"}, full...)...)
|
||||
if r.Status != 0 || r.Err != "" {
|
||||
return fmt.Errorf("git ls-tree %s of the module %s: %s", commit, mdir, forgekey.Said(r.Err+"\n"+r.Stderr))
|
||||
}
|
||||
objects := map[string]string{}
|
||||
for _, l := range strings.Split(r.Stdout, "\x00") {
|
||||
meta, name, ok := strings.Cut(l, "\t")
|
||||
fields := strings.Fields(meta)
|
||||
if !ok || len(fields) != 3 {
|
||||
continue
|
||||
for _, round := range unnested(full) {
|
||||
r := run(ctx, env, "git", append([]string{"-C", dir, "ls-tree", "-z", commit, "--"}, round...)...)
|
||||
if r.Status != 0 || r.Err != "" {
|
||||
return fmt.Errorf("git ls-tree %s of the module %s: %s", commit, mdir, forgekey.Said(r.Err+"\n"+r.Stderr))
|
||||
}
|
||||
for _, l := range strings.Split(r.Stdout, "\x00") {
|
||||
meta, name, ok := strings.Cut(l, "\t")
|
||||
fields := strings.Fields(meta)
|
||||
if !ok || len(fields) != 3 {
|
||||
continue
|
||||
}
|
||||
objects[name] = fields[2]
|
||||
}
|
||||
objects[name] = fields[2]
|
||||
}
|
||||
mt.Paths = map[string]string{}
|
||||
for i, p := range paths {
|
||||
@@ -106,4 +108,35 @@ func narrow(ctx context.Context, run forgekey.Runner, env []string, dir, commit,
|
||||
return nil
|
||||
}
|
||||
|
||||
// unnested splits paths into rounds of one git ls-tree each, none of whose paths lies inside another of its round: given
|
||||
// "go" and "go/seats/x" together, git ls-tree descends into go and lists its children instead of go itself, so the
|
||||
// object of go is missing from its answer (issue 1966: mesh-contracts' manifest names both). Usually one round; the
|
||||
// order of paths is kept within a round.
|
||||
func unnested(paths []string) [][]string {
|
||||
var rounds [][]string
|
||||
for _, p := range paths {
|
||||
placed := false
|
||||
for i, round := range rounds {
|
||||
if !nestsWithAny(p, round) {
|
||||
rounds[i] = append(round, p)
|
||||
placed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !placed {
|
||||
rounds = append(rounds, []string{p})
|
||||
}
|
||||
}
|
||||
return rounds
|
||||
}
|
||||
|
||||
func nestsWithAny(p string, round []string) bool {
|
||||
for _, q := range round {
|
||||
if p == q || strings.HasPrefix(p, q+"/") || strings.HasPrefix(q, p+"/") || p == "." || q == "." {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func sha256Hex(b []byte) string { h := sha256.Sum256(b); return hex.EncodeToString(h[:]) }
|
||||
|
||||
@@ -62,4 +62,16 @@ func TestAGoOnlyCommitLeavesTheNamedObjectsEqualOnRealGit(t *testing.T) {
|
||||
if src["."].Paths["src"] != realGit(t, repo, "rev-parse", "HEAD:src") {
|
||||
t.Fatalf("the object of src is %s, git says %s", src["."].Paths["src"], realGit(t, repo, "rev-parse", "HEAD:src"))
|
||||
}
|
||||
|
||||
// A manifest naming a path and a path inside it (mesh-contracts' "go" and "go/seats/meshvault"; issue 1966): each
|
||||
// gets its own object, not git ls-tree's listing of the outer one's children.
|
||||
writeFile(t, repo, "nested/module.json", `{"module":"nested","version":"1","build":{"artifacts":[`+
|
||||
`{"name":"go","kind":"package","language":"go","paths":["go"]},`+
|
||||
`{"name":"go-seat","kind":"package","language":"go","paths":["go/seats/a"]}]}}`)
|
||||
writeFile(t, repo, "nested/go/go.mod", "module x\n")
|
||||
writeFile(t, repo, "nested/go/seats/a/a.go", "package a\n")
|
||||
nested := trees(commit("nested"))["nested"]
|
||||
if nested.Paths["go"] != realGit(t, repo, "rev-parse", "HEAD:nested/go") || nested.Paths["go/seats/a"] != realGit(t, repo, "rev-parse", "HEAD:nested/go/seats/a") {
|
||||
t.Fatalf("a path and a path inside it: %v", nested.Paths)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user