package buildstep import ( "context" "strings" "testing" "git.novox.be/novox/mesh-sdk/go/delivery" "git.novox.be/novox/mesh-sdk/go/forgekey" ) // A module whose every artifact names its paths takes its tree from them (novox/hq ADR 0499 clause 2): ModuleTrees asks // git for each named path's object at the commit, keeps them in Paths and answers their delivery.NamedTree as Tree; a // module naming none keeps its directory's tree, as before. func TestModuleTreesNarrowsAModuleWhoseArtifactsNameTheirPaths(t *testing.T) { root := t.TempDir() sdk := `{"module":"mesh-sdk","version":"1","build":{"artifacts":[{"name":"lib","kind":"package","language":"typescript","paths":["src","package.json"]}]}}` writeTreeFile(t, root, "module.json", sdk) writeTreeFile(t, root, "modules/b/module.json", `{"module":"b","version":"1"}`) merge := strings.Repeat("c", 40) var lsTree []string run := func(ctx context.Context, env []string, name string, args ...string) forgekey.Ran { switch args[2] { case "ls-files": return forgekey.Ran{Stdout: "module.json\nmodules/b/module.json\n"} case "rev-parse": return forgekey.Ran{Stdout: "tree-of-" + args[3] + "\n"} case "ls-tree": lsTree = append(lsTree, strings.Join(args[4:], " ")) return forgekey.Ran{Stdout: "100644 blob " + strings.Repeat("b", 40) + "\tpackage.json\x00" + "040000 tree " + strings.Repeat("a", 40) + "\tsrc\x00"} } return forgekey.Ran{Status: 1, Stderr: "unexpected " + args[2]} } got, err := ModuleTrees(context.Background(), run, nil, root, merge) if err != nil { t.Fatal(err) } paths := map[string]string{"src": strings.Repeat("a", 40), "package.json": strings.Repeat("b", 40)} want, _ := delivery.NamedTree(hexOf(sdk), paths) if g := got["."]; g.Tree != want || len(g.Paths) != 2 || g.Paths["src"] != paths["src"] || g.Paths["package.json"] != paths["package.json"] { t.Fatalf("the root module = %+v, want tree %s and paths %v", g, want, paths) } if len(lsTree) != 1 || lsTree[0] != merge+" -- package.json src" { t.Fatalf("git ls-tree ran as %v", lsTree) } if g := got["modules/b"]; g.Tree != "tree-of-"+merge+":modules/b" || g.Paths != nil { t.Fatalf("a module naming no path was narrowed: %+v", g) } } // A named path absent at the commit fails the answer, naming the module and the path: a tree computed without it would // pin a build source that does not exist. func TestModuleTreesFailsNamingANamedPathAbsentAtTheCommit(t *testing.T) { root := t.TempDir() writeTreeFile(t, root, "modules/a/module.json", `{"module":"a","version":"1","build":{"artifacts":[{"name":"lib","kind":"package","language":"typescript","paths":["src","gone"]}]}}`) run := func(ctx context.Context, env []string, name string, args ...string) forgekey.Ran { switch args[2] { case "ls-files": return forgekey.Ran{Stdout: "modules/a/module.json\n"} case "rev-parse": return forgekey.Ran{Stdout: "t\n"} case "ls-tree": if strings.Join(args[4:], " ") != strings.Repeat("c", 40)+" -- modules/a/gone modules/a/src" { return forgekey.Ran{Status: 1, Stderr: "wrong arguments " + strings.Join(args[3:], " ")} } return forgekey.Ran{Stdout: "040000 tree " + strings.Repeat("a", 40) + "\tmodules/a/src\x00"} } return forgekey.Ran{Status: 1} } _, err := ModuleTrees(context.Background(), run, nil, root, strings.Repeat("c", 40)) if err == nil || !strings.Contains(err.Error(), `"gone"`) || !strings.Contains(err.Error(), "modules/a") { t.Fatalf("an absent named path gave %v", err) } }