diff --git a/internal/catalogue/build.go b/internal/catalogue/build.go index 94d54be..90b4bbb 100644 --- a/internal/catalogue/build.go +++ b/internal/catalogue/build.go @@ -142,7 +142,14 @@ func (b *Build) problems(module string) []string { // is which compiler — because the mesh chooses that, and cannot choose for a module that // has not said. if a.Kind == ArtifactBundle || a.Kind == ArtifactPackage { - if a.From != "" { + // **Except for a language that compiles to a binary, where it names which one** + // (novox/hq 04-ISSUES/142). A bundle in an interpreted language is the module's own + // directory compiled whole, and naming a source would be describing its own build. A + // repository written in a compiled language holds several commands — the host and its + // bootstrap live in one, and the mesh needs the host — and "the module's own directory" + // is then not a package at all. So the compiled case may say which package, and says + // the module root by saying nothing. + if a.From != "" && !compilesToABinary(a.Language) { problems = append(problems, fmt.Sprintf( "%s: %q is a bundle and names what it is built from (%q). A bundle is built "+ "from the module's own directory; what it says is the language", diff --git a/internal/catalogue/go_bundle_test.go b/internal/catalogue/go_bundle_test.go new file mode 100644 index 0000000..eb6cd2b --- /dev/null +++ b/internal/catalogue/go_bundle_test.go @@ -0,0 +1,37 @@ +package catalogue + +import "testing" + +// A bundle is the module's own directory compiled whole, and naming a source would be describing its +// own build. That holds for an interpreted language and cannot hold for a compiled one: a repository +// written in Go carries several commands — the host and its bootstrap live in one — and "the module's +// own directory" is then not a package at all (novox/hq 04-ISSUES/142). + +func TestAGoBundleMayNameItsCommand(t *testing.T) { + b := &Build{Artifacts: []Artifact{{ + Name: "host-arch", Kind: ArtifactBundle, Language: "go", System: "arch", + From: "cmd/mesh-host", + }}} + if p := b.problems("mesh-host"); len(p) != 0 { + t.Fatalf("a go bundle naming its command was refused: %v", p) + } +} + +func TestAnInterpretedBundleStillMayNotNameASource(t *testing.T) { + b := &Build{Artifacts: []Artifact{{ + Name: "tools", Kind: ArtifactBundle, Language: "typescript", From: "src", + }}} + p := b.problems("something") + if len(p) == 0 { + t.Fatal("an interpreted bundle naming what it is built from was accepted") + } +} + +func TestACompiledBundleStillMustSayItsSystem(t *testing.T) { + b := &Build{Artifacts: []Artifact{{ + Name: "host", Kind: ArtifactBundle, Language: "go", From: "cmd/mesh-host", + }}} + if len(b.problems("mesh-host")) == 0 { + t.Fatal("a compiled bundle with no system was accepted") + } +}