116 lines
4.5 KiB
Go
116 lines
4.5 KiB
Go
package index
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// The reasons a module has no fingerprint of the new form while the indexer writes none for any module (novox/hq
|
|
// ADR 0465 clause 2; issue 1444). Toolchains missing is delivery.ToolchainNoReport.
|
|
const (
|
|
// None2NoManifest is for a module whose directory the merged message carries no manifest of (an older bridge).
|
|
None2NoManifest = "the message carries no manifest"
|
|
// None2Builder is for a module with no artifact of a toolchain: only the builder's fingerprint is missing.
|
|
None2Builder = "builder's fingerprint not yet known"
|
|
// None2Context is for a module an artifact of which reads another repository's tree (today's form gives it none
|
|
// either, NoneContext).
|
|
None2Context = "context not pinned"
|
|
)
|
|
|
|
// lockFile is the lock file of a language's artifact that resolves packages when it is built, by name in the module's
|
|
// directory (the bridge reads these, internal/bridge LockFiles; issue 1450).
|
|
var lockFile = map[string]string{"go": "go.sum", "typescript": "package-lock.json"}
|
|
|
|
// moduleInputs is what a module's manifest and lock hashes give the indexer at a merge (issue 1450).
|
|
type moduleInputs struct {
|
|
// Kept is the new-form inputs the merge gave the module; nil when the manifest could not be read or gave none.
|
|
Kept *delivery.KeptInputs2
|
|
// Languages is the language of each artifact that has a toolchain (a bundle or a package of go or typescript), by
|
|
// artifact name. The toolchain versions are joined to them when the build modules report them (issue 1444, the
|
|
// watching half); the SDK's KeptInputs2 keeps no languages, so they are read from the manifest again then.
|
|
Languages map[string]string
|
|
// None2 is why the module has no fingerprint of the new form.
|
|
None2 string
|
|
}
|
|
|
|
// baseFP answers a base module's new-form fingerprint, or why it has none.
|
|
type baseFP func(module string) (fp, none string)
|
|
|
|
// inputsOf turns the manifest of a module (raw, as the forge answered it), the tree of its directory and the lock
|
|
// hashes of that directory (lock file name to hash) into its new-form inputs. The manifest is read by the catalogue's
|
|
// parser; a manifest it refuses, or one that is of another module, leaves Kept nil and says why.
|
|
//
|
|
// The rules are the controller's builder (mesh-controller internal/builder/builder.go): a bundle or a package of a
|
|
// language with a toolchain (go, typescript) is the artifact that has one; a package, and a bundle of those languages,
|
|
// resolves packages when it is built (wantsPackages, :1017), so it has an entry in Locks, with the hash of its
|
|
// language's lock file or an empty hash when none was carried (the fingerprint is then none, "no lock"); an archive,
|
|
// an image and an upstream resolve nothing and have no toolchain. A base is a build.on entry that names a module.
|
|
func inputsOf(module, raw, tree string, locks map[string]string, base baseFP) moduleInputs {
|
|
m, err := catalogue.ParseManifest([]byte(raw))
|
|
if err != nil {
|
|
return moduleInputs{None2: "the manifest cannot be read: " + err.Error()}
|
|
}
|
|
if m.Module != module {
|
|
return moduleInputs{None2: fmt.Sprintf("the manifest is of module %q, not %q", m.Module, module)}
|
|
}
|
|
if tree == "" {
|
|
return moduleInputs{None2: "the merge names no tree for the module's directory"}
|
|
}
|
|
kept := delivery.KeptInputs2{Tree: tree}
|
|
langs := map[string]string{}
|
|
contexts := false
|
|
var missing []string
|
|
if m.Build != nil {
|
|
for _, a := range m.Build.Artifacts {
|
|
if a.Context != nil {
|
|
contexts = true
|
|
}
|
|
if a.Kind != catalogue.ArtifactBundle && a.Kind != catalogue.ArtifactPackage {
|
|
continue
|
|
}
|
|
name, ok := lockFile[a.Language]
|
|
if !ok {
|
|
continue
|
|
}
|
|
langs[a.Name] = a.Language
|
|
if kept.Locks == nil {
|
|
kept.Locks = map[string]string{}
|
|
}
|
|
kept.Locks[a.Name] = locks[name]
|
|
}
|
|
seen := map[string]bool{}
|
|
for _, on := range m.Build.On {
|
|
if on.Module == "" || seen[on.Module] {
|
|
continue
|
|
}
|
|
seen[on.Module] = true
|
|
if fp, none := base(on.Module); fp != "" {
|
|
kept.Bases = append(kept.Bases, fp)
|
|
} else {
|
|
missing = append(missing, fmt.Sprintf("the base %s has no fingerprint (%s)", on.Module, none))
|
|
}
|
|
}
|
|
}
|
|
sort.Strings(kept.Bases)
|
|
sort.Strings(missing)
|
|
out := moduleInputs{Kept: &kept}
|
|
if len(langs) > 0 {
|
|
out.Languages = langs
|
|
}
|
|
switch {
|
|
case contexts:
|
|
out.None2 = None2Context
|
|
case len(missing) > 0:
|
|
out.None2 = strings.Join(missing, "; ")
|
|
case len(langs) > 0:
|
|
out.None2 = delivery.ToolchainNoReport
|
|
default:
|
|
out.None2 = None2Builder
|
|
}
|
|
return out
|
|
}
|