mesh/merge-gate head a39661aa36f3 merged into trunk 34392e74916c — pass, with a note: builds mesh-sdk (+41 dependent(s)) → ace, g14, novox, shanks; no bus …
mesh/repo-check head a39661aa36f3 merged into trunk 34392e74916c — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (typescript)…
mesh/delivery delivered
64 lines
2.4 KiB
Go
64 lines
2.4 KiB
Go
package delivery
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// SourceInputs are what a module's source fingerprint is of (novox/hq ADR 0437 §5): the module, the git tree of
|
|
// its directory, its bases (references, of which only the digest counts), the root tree of each repository its
|
|
// artifacts read (by artifact), each artifact's toolchain line, and the reason the source does not pin the build
|
|
// when it does not (a build that resolves packages when built). A context is the value the builder records for it:
|
|
// a repository's root tree, or for an image that compiles a Go program the `narrow:` hash of the build source it was
|
|
// handed (mesh-controller internal/builder/builder.go:1146-1156).
|
|
type SourceInputs struct {
|
|
Module string
|
|
Tree string
|
|
Bases []string
|
|
Contexts map[string]string
|
|
Toolchains map[string]string
|
|
Unpinned string
|
|
}
|
|
|
|
// SourceFingerprint is the module's source fingerprint, `src1:` and the hex sha256 of its inputs' lines, or none
|
|
// and the reason when the source does not pin the build: Unpinned when set, "no tree" when Tree is empty. It is the
|
|
// one function the controller's builder and the indexer both call, so they agree byte for byte. The lines are
|
|
// "module <m>" and "tree <t>", then "base <digest>" (once each), "context <artifact> <tree>" and "toolchain
|
|
// <artifact> <line>" sorted, all joined by a newline.
|
|
func SourceFingerprint(in SourceInputs) (fp, none string) {
|
|
if in.Unpinned != "" {
|
|
return "", in.Unpinned
|
|
}
|
|
if in.Tree == "" {
|
|
return "", "no tree"
|
|
}
|
|
lines := []string{"module " + in.Module, "tree " + in.Tree}
|
|
bases := map[string]bool{}
|
|
for _, b := range in.Bases {
|
|
bases[ReferenceDigest(b)] = true
|
|
}
|
|
for b := range bases {
|
|
lines = append(lines, "base "+b)
|
|
}
|
|
for a, t := range in.Contexts {
|
|
lines = append(lines, "context "+a+" "+t)
|
|
}
|
|
for a, t := range in.Toolchains {
|
|
lines = append(lines, "toolchain "+a+" "+t)
|
|
}
|
|
sort.Strings(lines[2:])
|
|
sum := sha256.Sum256([]byte(strings.Join(lines, "\n")))
|
|
return SourcePrefix + hex.EncodeToString(sum[:]), ""
|
|
}
|
|
|
|
// ReferenceDigest is a reference's digest, `sha256:...`, so the registry address a base was copied into does not
|
|
// enter the fingerprint; the reference itself when it carries none.
|
|
func ReferenceDigest(reference string) string {
|
|
if _, digest, pinned := strings.Cut(reference, "@"); pinned && digest != "" {
|
|
return digest
|
|
}
|
|
return reference
|
|
}
|