Files
mesh-delivery/sdk/packagename/packagename.go
T

70 lines
2.5 KiB
Go

// Package packagename reads a package artifact's name in its own ecosystem (design 32, a package named by its name in its
// own language): a Go package by the module line of its go.mod, a TypeScript package by the name in its package.json, read
// at a commit of the repository that builds it. The indexer reads it so at each trunk merge (its packages state's series
// keys), and the checker so at a delivery group member's head for a package new in the group, so the judge is handed one
// name for each package whoever reads it (mesh-sdk composer.Request.Packages).
package packagename
import (
"context"
"encoding/json"
"fmt"
"path"
"strings"
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// ReadFile reads one file of a repository at a commit; a file the commit does not hold is nil with no error.
type ReadFile func(ctx context.Context, repository, commit, file string) ([]byte, error)
// Of is a package artifact's name in its ecosystem, read at commit from the first of its paths (or the module's directory
// dir, meshcatalogclient.RootPath or empty for the repository's root) that holds its go.mod (Go) or package.json (TypeScript). A
// file read that fails, a go.mod that names no module and a package.json that names no name are errors, said.
func Of(ctx context.Context, read ReadFile, repository, commit, dir string, a catalogue.Artifact) (string, error) {
file := "package.json"
if a.Language == "go" {
file = "go.mod"
}
base := dir
if base == meshcatalogclient.RootPath {
base = ""
}
roots := a.Paths
if len(roots) == 0 {
roots = []string{"."}
}
for _, r := range roots {
p := path.Join(base, r, file)
if strings.HasSuffix(r, file) {
p = path.Join(base, r)
}
raw, err := read(ctx, repository, commit, p)
if err != nil {
return "", fmt.Errorf("%s: %w", p, err)
}
if raw == nil {
continue
}
if a.Language == "go" {
for _, line := range strings.Split(string(raw), "\n") {
if rest, ok := strings.CutPrefix(strings.TrimSpace(line), "module "); ok {
if name := strings.Trim(strings.TrimSpace(rest), `"`); name != "" {
return name, nil
}
}
}
return "", fmt.Errorf("%s names no module", p)
}
var pj struct {
Name string `json:"name"`
}
if err := json.Unmarshal(raw, &pj); err != nil || pj.Name == "" {
return "", fmt.Errorf("%s names no name (%v)", p, err)
}
return pj.Name, nil
}
return "", fmt.Errorf("no %s under %v", file, roots)
}