package check import ( "context" "errors" "fmt" "strings" "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" "git.novox.be/novox/mesh-sdk/go/catalogue" ) // declaredPackage is one package a group member declares: the module, its directory in the repository (RootPath for its // root, empty when not known), and the artifact's name, paths and language. type declaredPackage struct { pull Pull module, dir string name string paths []string language string } // manifestAtHead is a touched module's manifest read from the forge at its member's head (the lead's ruling 4 on A2c's // finding 4): with no preview of the merge, a package new in the group is declared only there, never at the trunk. The // module's directory is the indexer's when it knows the module, else modules/ or the repository's root, the one // whose manifest names the module. Found is false when no such file names it. func (st *state) manifestAtHead(ctx context.Context, p Pull, module string) (m catalogue.Manifest, dir string, found bool, err error) { var dirs []string if st.j.Dirs != nil { if d, ok := st.j.Dirs.ModuleDir(module); ok { dirs = []string{d} } } if dirs == nil { dirs = []string{"modules/" + module, meshcatalogclient.RootPath} } for _, d := range dirs { file := "module.json" if t := strings.Trim(d, "/"); t != "" && t != meshcatalogclient.RootPath { file = t + "/module.json" } text, err := st.j.Forge.File(ctx, p.Repository, file, p.Head) if errors.Is(err, ErrNotFound) { continue } if err != nil { return catalogue.Manifest{}, "", false, fmt.Errorf("the manifest of %s at the head of %s cannot be read%s: %w", module, pullKey(p), unheardWords(err), err) } m, err := catalogue.Decode([]byte(text)) if err != nil { return catalogue.Manifest{}, "", false, fmt.Errorf("the manifest %s of %s at the head of %s is no manifest: %w", file, module, pullKey(p), err) } if m.Module == module { return m, d, true, nil } } return catalogue.Manifest{}, "", false, nil } // declaredPackages are the packages the case's members declare, read from each touched module's manifest at the merge // preview (the candidate's); with no preview, at the member's head on the forge, so a package new in the group is asked // for on the first check too (trunk's manifest when no forge is read): a member that declares none is not asked for. func (st *state) declaredPackages(ctx context.Context) ([]declaredPackage, error) { if st.j.Read == nil && st.j.Forge == nil { return nil, nil } var trunk map[string]string if st.j.Manifests != nil { trunk = st.j.Manifests.ManifestDigests() } var out []declaredPackage for _, p := range st.c.Pulls { for _, module := range p.Modules { var m catalogue.Manifest var dir string digest := p.Fps[module].Manifest switch { case digest != "" && st.j.Read != nil: var err error if m, err = st.j.Read.Manifest(ctx, digest); err != nil { return nil, fmt.Errorf("the manifest of %s (%s) cannot be read, so the packages it declares are not known: %w", module, pullKey(p), err) } case st.j.Forge != nil: var found bool var err error if m, dir, found, err = st.manifestAtHead(ctx, p, module); err != nil { return nil, fmt.Errorf("%v, so the packages it declares are not known", err) } if !found { continue } case trunk[module] != "" && st.j.Read != nil: var err error if m, err = st.j.Read.Manifest(ctx, trunk[module]); err != nil { return nil, fmt.Errorf("the manifest of %s (%s) cannot be read, so the packages it declares are not known: %w", module, pullKey(p), err) } default: continue } if dir == "" && st.j.Dirs != nil { dir, _ = st.j.Dirs.ModuleDir(module) } if m.Build == nil { continue } for _, a := range m.Build.Artifacts { if a.Kind != catalogue.ArtifactPackage { continue } out = append(out, declaredPackage{pull: p, module: module, dir: dir, name: a.Name, paths: a.Paths, language: a.Language}) } } } return out, nil }