diff --git a/marketplace/builder.go b/marketplace/builder.go index 9e7e6aa..8ee97a1 100644 --- a/marketplace/builder.go +++ b/marketplace/builder.go @@ -31,15 +31,19 @@ type Builder struct { Org string } -// BuildFromDirs scans each directory for subdirectories containing either -// core.json (preferred) or .core/manifest.yaml. Each valid manifest is -// added to the resulting Index as a Module. +// BuildFromDirs scans each directory, then its immediate subdirectories, for +// core.json (preferred) or .core/manifest.yaml. Each valid manifest is added +// to the resulting Index as a Module. // Usage: BuildFromDirs(...) func (b *Builder) BuildFromDirs(dirs ...string) (*Index, error) { var modules []Module seen := make(map[string]bool) for _, dir := range dirs { + if err := b.loadInto(&modules, seen, dir); err != nil { + core.Warn(core.Sprintf("marketplace: skipping %s: %v", filepath.Base(dir), err)) + } + entries, err := os.ReadDir(dir) if err != nil { if os.IsNotExist(err) { @@ -53,26 +57,10 @@ func (b *Builder) BuildFromDirs(dirs ...string) (*Index, error) { continue } - m, err := b.loadFromDir(filepath.Join(dir, e.Name())) - if err != nil { + child := filepath.Join(dir, e.Name()) + if err := b.loadInto(&modules, seen, child); err != nil { core.Warn(core.Sprintf("marketplace: skipping %s: %v", e.Name(), err)) - continue } - if m == nil { - continue - } - if seen[m.Code] { - continue - } - seen[m.Code] = true - - mod := Module{ - Code: m.Code, - Name: m.Name, - Repo: b.repoURL(m.Code), - SignKey: m.Sign, - } - modules = append(modules, mod) } } @@ -86,6 +74,29 @@ func (b *Builder) BuildFromDirs(dirs ...string) (*Index, error) { }, nil } +func (b *Builder) loadInto(modules *[]Module, seen map[string]bool, dir string) error { + m, err := b.loadFromDir(dir) + if err != nil { + return err + } + if m == nil { + return nil + } + if seen[m.Code] { + return nil + } + seen[m.Code] = true + + mod := Module{ + Code: m.Code, + Name: m.Name, + Repo: b.repoURL(m.Code), + SignKey: m.Sign, + } + *modules = append(*modules, mod) + return nil +} + // BuildFromManifests constructs an Index from pre-loaded manifests. // This is useful when manifests have already been collected (e.g. from // a Forge API crawl). diff --git a/marketplace/builder_test.go b/marketplace/builder_test.go index 9eeaa35..966a1c8 100644 --- a/marketplace/builder_test.go +++ b/marketplace/builder_test.go @@ -65,6 +65,20 @@ func TestBuildFromDirs_Good_ManifestYAML_Good(t *testing.T) { assert.Equal(t, IndexVersion, idx.Version) } +func TestBuildFromDirs_Good_IndexesRootDirectory_Good(t *testing.T) { + root := t.TempDir() + writeManifestYAML(t, root, "root-mod", "Root Module", "1.0.0") + + b := &Builder{BaseURL: "https://forge.lthn.ai", Org: "core"} + idx, err := b.BuildFromDirs(root) + require.NoError(t, err) + + require.Len(t, idx.Modules, 1) + assert.Equal(t, "root-mod", idx.Modules[0].Code) + assert.Equal(t, "Root Module", idx.Modules[0].Name) + assert.Equal(t, "https://forge.lthn.ai/core/root-mod.git", idx.Modules[0].Repo) +} + func TestBuildFromDirs_Good_CarriesSignKey_Good(t *testing.T) { root := t.TempDir() modDir := filepath.Join(root, "signed-mod")