diff --git a/internal/manifest/manifest.go b/internal/manifest/manifest.go index fd8f1d3c..724e4d2e 100644 --- a/internal/manifest/manifest.go +++ b/internal/manifest/manifest.go @@ -3,7 +3,9 @@ package manifest import ( "fmt" "io" + "path/filepath" "slices" + "strings" "github.com/canonical/chisel/internal/jsonwall" "github.com/canonical/chisel/internal/setup" @@ -158,6 +160,22 @@ func Validate(manifest *Manifest) (err error) { return nil } +// LocateManifestSlices finds the paths marked with "generate:manifest" and +// returns a map from the manifest path to all the slices that declare it. +func LocateManifestSlices(slices []*setup.Slice, manifestFileName string) map[string][]*setup.Slice { + manifestSlices := make(map[string][]*setup.Slice) + for _, slice := range slices { + for path, info := range slice.Contents { + if info.Generate == setup.GenerateManifest { + dir := strings.TrimSuffix(path, "**") + path = filepath.Join(dir, manifestFileName) + manifestSlices[path] = append(manifestSlices[path], slice) + } + } + } + return manifestSlices +} + type prefixable interface { Path | Content | Package | Slice } diff --git a/internal/manifest/manifest_test.go b/internal/manifest/manifest_test.go index 1da510da..0731f40e 100644 --- a/internal/manifest/manifest_test.go +++ b/internal/manifest/manifest_test.go @@ -9,8 +9,12 @@ import ( . "gopkg.in/check.v1" "github.com/canonical/chisel/internal/manifest" + "github.com/canonical/chisel/internal/setup" + "github.com/canonical/chisel/internal/testutil" ) +var testKey = testutil.PGPKeys["key1"] + type manifestContents struct { Paths []*manifest.Path Packages []*manifest.Package @@ -123,7 +127,7 @@ var manifestTests = []struct { readError: `cannot read manifest: unknown schema version "2.0"`, }} -func (s *S) TestRun(c *C) { +func (s *S) TestManifestReadValidate(c *C) { for _, test := range manifestTests { c.Logf("Summary: %s", test.summary) @@ -169,6 +173,102 @@ func (s *S) TestRun(c *C) { } } +var locateManifestSlicesTests = []struct { + summary string + slices []*setup.Slice + filename string + expected map[string][]string +}{{ + summary: "Single slice", + slices: []*setup.Slice{{ + Name: "slice1", + Contents: map[string]setup.PathInfo{ + "/folder/**": { + Kind: "generate", + Generate: "manifest", + }, + }, + }}, + filename: "manifest.wall", + expected: map[string][]string{ + "/folder/manifest.wall": []string{"slice1"}, + }, +}, { + summary: "No slice matched", + slices: []*setup.Slice{{ + Name: "slice1", + Contents: map[string]setup.PathInfo{}, + }}, + filename: "manifest.wall", + expected: map[string][]string{}, +}, { + summary: "Several matches with several groups", + slices: []*setup.Slice{{ + Name: "slice1", + Contents: map[string]setup.PathInfo{ + "/folder/**": { + Kind: "generate", + Generate: "manifest", + }, + }, + }, { + Name: "slice2", + Contents: map[string]setup.PathInfo{ + "/folder/**": { + Kind: "generate", + Generate: "manifest", + }, + }, + }, { + Name: "slice3", + Contents: map[string]setup.PathInfo{}, + }, { + Name: "slice4", + Contents: map[string]setup.PathInfo{ + "/other-folder/**": { + Kind: "generate", + Generate: "manifest", + }, + }, + }, { + Name: "slice5", + Contents: map[string]setup.PathInfo{ + "/other-folder/**": { + Kind: "generate", + Generate: "manifest", + }, + }, + }}, + filename: "mfest.wall", + expected: map[string][]string{ + "/folder/mfest.wall": {"slice1", "slice2"}, + "/other-folder/mfest.wall": {"slice4", "slice5"}, + }, +}} + +func (s *S) TestLocateManifestSlices(c *C) { + for _, test := range locateManifestSlicesTests { + c.Logf("Summary: %s", test.summary) + + manifestSlices := manifest.LocateManifestSlices(test.slices, test.filename) + + slicesByName := map[string]*setup.Slice{} + for _, slice := range test.slices { + _, ok := slicesByName[slice.Name] + c.Assert(ok, Equals, false, Commentf("duplicated slice name")) + slicesByName[slice.Name] = slice + } + + c.Assert(manifestSlices, HasLen, len(test.expected)) + for path, slices := range manifestSlices { + c.Assert(slices, HasLen, len(test.expected[path])) + for i, sliceName := range test.expected[path] { + c.Assert(slicesByName[sliceName], DeepEquals, slices[i]) + } + } + } +} + func dumpManifestContents(c *C, mfest *manifest.Manifest) *manifestContents { var slices []*manifest.Slice err := mfest.IterateSlices("", func(slice *manifest.Slice) error { diff --git a/internal/slicer/slicer.go b/internal/slicer/slicer.go index aada5417..0b2af526 100644 --- a/internal/slicer/slicer.go +++ b/internal/slicer/slicer.go @@ -439,10 +439,7 @@ type generateManifestsOptions struct { } func generateManifests(options *generateManifestsOptions) error { - manifestSlices, err := locateManifestSlices(options.selection) - if err != nil { - return err - } + manifestSlices := manifest.LocateManifestSlices(options.selection, manifestFileName) if len(manifestSlices) == 0 { // Nothing to do. return nil @@ -451,7 +448,7 @@ func generateManifests(options *generateManifestsOptions) error { Schema: manifest.Schema, }) - err = manifestAddPackages(dbw, options.packageInfo) + err := manifestAddPackages(dbw, options.packageInfo) if err != nil { return err } @@ -590,19 +587,3 @@ func unixPerm(mode fs.FileMode) (perm uint32) { } return perm } - -// locateManifestSlices finds the paths marked with "generate:manifest" and -// returns a map from the manifest path to all the slices that declare it. -func locateManifestSlices(slices []*setup.Slice) (map[string][]*setup.Slice, error) { - manifestSlices := make(map[string][]*setup.Slice) - for _, slice := range slices { - for path, info := range slice.Contents { - if info.Generate == setup.GenerateManifest { - dir := strings.TrimSuffix(path, "**") - path = filepath.Join(dir, manifestFileName) - manifestSlices[path] = append(manifestSlices[path], slice) - } - } - } - return manifestSlices, nil -}