diff --git a/internal/slicer/slicer.go b/internal/slicer/slicer.go index 6f4783b8..fcc16d67 100644 --- a/internal/slicer/slicer.go +++ b/internal/slicer/slicer.go @@ -41,6 +41,15 @@ type contentChecker struct { knownPaths map[string]pathData } +// pkgSource holds the resolved source for a package: its architecture and a +// fetch function returning the package reader and metadata. The fetch +// function is bound at resolution time, so callers are agnostic to whether +// the package comes from an archive or a store. +type pkgSource struct { + arch string + fetch func() (io.ReadSeekCloser, *archive.PackageInfo, error) +} + func (cc *contentChecker) checkMutable(path string) error { if !cc.knownPaths[path].mutable { return fmt.Errorf("cannot write file which is not mutable: %s", path) @@ -90,7 +99,7 @@ func Run(options *RunOptions) error { targetDir = filepath.Join(dir, targetDir) } - pkgArchive, err := selectPkgArchives(options.Archives, options.Selection) + pkgSources, err := resolvePkgSources(options.Archives, options.Selection) if err != nil { return err } @@ -108,7 +117,7 @@ func Run(options *RunOptions) error { extractPackage = make(map[string][]tarball.ExtractInfo) extract[slice.Package] = extractPackage } - arch := pkgArchive[slice.Package].Options().Arch + arch := pkgSources[slice.Package].arch for targetPath, pathInfo := range slice.Contents { if targetPath == "" { continue @@ -153,7 +162,7 @@ func Run(options *RunOptions) error { continue } pkg := options.Selection.Release.Packages[slice.Package] - reader, info, err := pkgArchive[slice.Package].Fetch(pkg.RealName) + reader, info, err := pkgSources[pkg.Name].fetch() if err != nil { return err } @@ -270,7 +279,7 @@ func Run(options *RunOptions) error { // them to the appropriate slices. relPaths := map[string][]*setup.Slice{} for _, slice := range options.Selection.Slices { - arch := pkgArchive[slice.Package].Options().Arch + arch := pkgSources[slice.Package].arch for relPath, pathInfo := range slice.Contents { if len(pathInfo.Arch) > 0 && !slices.Contains(pathInfo.Arch, arch) { continue @@ -490,10 +499,13 @@ func createFile(targetDir, relPath string, pathInfo setup.PathInfo) (*fsutil.Ent }) } -// selectPkgArchives selects the highest priority archive containing the package -// unless a particular archive is pinned within the slice definition file. It -// returns a map of archives indexed by package names. -func selectPkgArchives(archives map[string]archive.Archive, selection *setup.Selection) (map[string]archive.Archive, error) { +// resolvePkgSources determines the source for each package in the selection. +// For archive packages it selects the highest priority archive containing the +// package unless a particular archive is pinned within the slice definition +// file. For store packages it records a fetch function that returns an error +// until store support is implemented. It returns a map of pkgSource indexed by +// package names. +func resolvePkgSources(archives map[string]archive.Archive, selection *setup.Selection) (map[string]pkgSource, error) { sortedArchives := make([]*setup.Archive, 0, len(selection.Release.Archives)) for _, archive := range selection.Release.Archives { if archive.Priority < 0 { @@ -507,15 +519,20 @@ func selectPkgArchives(archives map[string]archive.Archive, selection *setup.Sel return b.Priority - a.Priority }) - pkgArchive := make(map[string]archive.Archive) + pkgSources := make(map[string]pkgSource) for _, s := range selection.Slices { - if _, ok := pkgArchive[s.Package]; ok { + if _, ok := pkgSources[s.Package]; ok { continue } pkg := selection.Release.Packages[s.Package] - if pkg.Store != "" { - return nil, fmt.Errorf("cannot fetch package %q from store %q: not implemented", pkg.Name, pkg.Store) + pkgSources[pkg.Name] = pkgSource{ + // TODO: set the arch when implementing fetching from the store. + fetch: func() (io.ReadSeekCloser, *archive.PackageInfo, error) { + return nil, nil, fmt.Errorf("cannot fetch package %q from store %q: not implemented", pkg.Name, pkg.Store) + }, + } + continue } var candidates []*setup.Archive @@ -538,7 +555,12 @@ func selectPkgArchives(archives map[string]archive.Archive, selection *setup.Sel if chosen == nil { return nil, fmt.Errorf("cannot find package %q in archive(s)", pkg.RealName) } - pkgArchive[pkg.Name] = chosen + pkgSources[pkg.Name] = pkgSource{ + arch: chosen.Options().Arch, + fetch: func() (io.ReadSeekCloser, *archive.PackageInfo, error) { + return chosen.Fetch(pkg.RealName) + }, + } } - return pkgArchive, nil + return pkgSources, nil } diff --git a/internal/slicer/slicer_test.go b/internal/slicer/slicer_test.go index d6ef9ca0..954602de 100644 --- a/internal/slicer/slicer_test.go +++ b/internal/slicer/slicer_test.go @@ -1979,21 +1979,29 @@ var slicerTests = []slicerTest{{ "/dir/file": "file 0644 cc55e2ec {test-package_third}", }, }, { - summary: "Store package is not yet implemented", - slices: []setup.SliceKey{{"bin-curl", "bin"}}, + summary: "Store package fetching not yet implemented", + slices: []setup.SliceKey{{"test-package", "myslice"}, {"bin-store-pkg", "myslice"}}, + arch: "amd64", release: map[string]string{ "chisel.yaml": testutil.DefaultChiselYamlWithStores, - "slices/curl.yaml": ` - package: curl + "slices/mydir/test-package.yaml": ` + package: test-package + slices: + myslice: + contents: + /dir/file: + `, + "slices/mydir/store-pkg.yaml": ` + package: store-pkg store: bin - default-track: latest + default-track: 3.1 slices: - bin: + myslice: contents: - /usr/bin/curl: + /dir/store-file: `, }, - error: `cannot fetch package "bin-curl" from store "bin": not implemented`, + error: `cannot fetch package "bin-store-pkg" from store "bin": not implemented`, }} func (s *S) TestRun(c *C) {