Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c5d397c
feat: prepare interface for store
upils Jul 9, 2026
f79521e
fix: error fetching from the store
upils Jul 10, 2026
a2e22f2
fix: cleaning
upils Jul 10, 2026
2eb85d0
feat: remove arch setting until store implementation
upils Jul 15, 2026
3004a6e
test: refine
upils Jul 15, 2026
ed0e070
refactor: adopt alternative approach
upils Aug 18, 2026
268501e
style: remove unused track and risk
upils Aug 19, 2026
107103d
fix: rework fetcher interface
upils Sep 1, 2026
1249e7b
Merge branch 'main' into slicer-source-interface
upils Sep 1, 2026
4cfed24
refactor: use the manifestutil.PackageInfo interface
upils Sep 1, 2026
7b124b3
test: remove redundant tests
upils Sep 2, 2026
076ff37
style: renaming and tests simplification
upils Sep 2, 2026
eaddfd9
fix: revert unintended changes
upils Sep 2, 2026
bb39d06
docs: use package slices file term
upils Sep 3, 2026
b930f97
test: revert unrelated changes
upils Sep 3, 2026
8c24bda
docs: clean useless comment
upils Sep 16, 2026
a13c637
fix: apply review comments
upils Oct 1, 2026
3655843
fix: revert unwanted changes
upils Oct 1, 2026
a81c9a7
fix: move out fix for package naming collision
upils Oct 1, 2026
b932d17
fix: simplify arch check in Run
upils Oct 1, 2026
1a997ea
docs: fix comment
upils Oct 2, 2026
aa574b9
fix: refine abstraction
upils Oct 13, 2026
aac4ef1
style: align name with project convention
upils Oct 13, 2026
8c63924
fix: keep the diff focus on the added abstraction
upils Oct 13, 2026
3cdef0a
docs: remove useless comment
upils Oct 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions internal/archive/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,6 @@ type PackageInfo struct {
SHA256 string
}

func (p *PackageInfo) PkgName() string { return p.Name }
func (p *PackageInfo) PkgVersion() string { return p.Version }
func (p *PackageInfo) PkgRevision() int { return 0 }
func (p *PackageInfo) PkgArch() string { return p.Arch }
func (p *PackageInfo) PkgDigestKind() cache.DigestKind { return cache.SHA256 }
func (p *PackageInfo) PkgDigest() string { return p.SHA256 }

type Options struct {
Label string
Version string
Expand Down
3 changes: 1 addition & 2 deletions internal/manifestutil/manifestutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import (
"github.com/canonical/chisel/public/manifest"
)

// PackageInfo describes a package as obtained from its source, abstracting
// over archives, stores, and any other backend.
type PackageInfo interface {
PkgName() string
PkgVersion() string
Expand All @@ -26,6 +24,7 @@ type PackageInfo interface {
// revisions.
PkgRevision() int
PkgArch() string
PkgStore() string
PkgDigestKind() cache.DigestKind
PkgDigest() string
}
Expand Down
93 changes: 59 additions & 34 deletions internal/manifestutil/manifestutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
. "gopkg.in/check.v1"

"github.com/canonical/chisel/internal/apachetestutil"
"github.com/canonical/chisel/internal/archive"
"github.com/canonical/chisel/internal/cache"
"github.com/canonical/chisel/internal/manifestutil"
"github.com/canonical/chisel/internal/setup"
"github.com/canonical/chisel/public/manifest"
Expand Down Expand Up @@ -119,6 +119,24 @@ var slice2 = &setup.Slice{
Name: "slice2",
}

type testPackageInfo struct {
Name string
Version string
Revision int
Arch string
Store string
DigestKind cache.DigestKind
Digest string
}

func (p *testPackageInfo) PkgName() string { return p.Name }
func (p *testPackageInfo) PkgVersion() string { return p.Version }
func (p *testPackageInfo) PkgRevision() int { return p.Revision }
func (p *testPackageInfo) PkgArch() string { return p.Arch }
func (p *testPackageInfo) PkgStore() string { return p.Store }
func (p *testPackageInfo) PkgDigestKind() cache.DigestKind { return p.DigestKind }
func (p *testPackageInfo) PkgDigest() string { return p.Digest }

var generateManifestTests = []struct {
summary string
report *manifestutil.Report
Expand Down Expand Up @@ -149,17 +167,19 @@ var generateManifestTests = []struct {
},
},
packageInfo: []manifestutil.PackageInfo{
&archive.PackageInfo{
Name: "package1",
Version: "v1",
Arch: "a1",
SHA256: "s1",
&testPackageInfo{
Name: "package1",
Version: "v1",
Arch: "a1",
DigestKind: cache.SHA256,
Digest: "s1",
},
&archive.PackageInfo{
Name: "package2",
Version: "v2",
Arch: "a2",
SHA256: "s2",
&testPackageInfo{
Name: "package2",
Version: "v2",
Arch: "a2",
DigestKind: cache.SHA256,
Digest: "s2",
},
},
expected: &apachetestutil.ManifestContents{
Expand Down Expand Up @@ -399,11 +419,12 @@ var generateManifestTests = []struct {
},
},
packageInfo: []manifestutil.PackageInfo{
&archive.PackageInfo{
Name: "package1",
Version: "v1",
Arch: "a1",
SHA256: "s1",
&testPackageInfo{
Name: "package1",
Version: "v1",
Arch: "a1",
DigestKind: cache.SHA256,
Digest: "s1",
},
},
expected: &apachetestutil.ManifestContents{
Expand Down Expand Up @@ -500,37 +521,40 @@ var generateManifestTests = []struct {
}, {
summary: "Invalid package: missing name",
packageInfo: []manifestutil.PackageInfo{
&archive.PackageInfo{
Version: "v1",
Arch: "a1",
SHA256: "s1",
&testPackageInfo{
Version: "v1",
Arch: "a1",
DigestKind: cache.SHA256,
Digest: "s1",
},
},
error: `internal error: invalid manifest: package name not set`,
}, {
summary: "Invalid package: missing version",
packageInfo: []manifestutil.PackageInfo{
&archive.PackageInfo{
Name: "package-1",
Arch: "a1",
SHA256: "s1",
&testPackageInfo{
Name: "package-1",
Arch: "a1",
DigestKind: cache.SHA256,
Digest: "s1",
},
},
error: `internal error: invalid manifest: package "package-1" missing version`,
}, {
summary: "Invalid package: missing arch",
packageInfo: []manifestutil.PackageInfo{
&archive.PackageInfo{
Name: "package-1",
Version: "v1",
SHA256: "s1",
&testPackageInfo{
Name: "package-1",
Version: "v1",
DigestKind: cache.SHA256,
Digest: "s1",
},
},
error: `internal error: invalid manifest: package "package-1" missing arch`,
}, {
summary: "Invalid package: missing sha256",
packageInfo: []manifestutil.PackageInfo{
&archive.PackageInfo{
&testPackageInfo{
Name: "package-1",
Version: "v1",
Arch: "a1",
Expand All @@ -547,11 +571,12 @@ func (s *S) TestGenerateManifests(c *C) {
}
if test.packageInfo == nil {
test.packageInfo = []manifestutil.PackageInfo{
&archive.PackageInfo{
Name: "package1",
Version: "v1",
Arch: "a1",
SHA256: "s1",
&testPackageInfo{
Name: "package1",
Version: "v1",
Arch: "a1",
DigestKind: cache.SHA256,
Digest: "s1",
},
}
}
Expand Down
62 changes: 62 additions & 0 deletions internal/slicer/package_remote.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package slicer

import (
"io"

"github.com/canonical/chisel/internal/archive"
"github.com/canonical/chisel/internal/cache"
)

// RemotePackageInfo describes a package as reported by its provider.
type RemotePackageInfo struct {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Note to reviewer]: Following your suggestion, the archive.PackageInfo (and the future store.PackageInfo) does not satisfy the interface defined by manifestutil anymore, but RemotePackageInfo does. The Fetch method below does the fetching and converts the received PackageInfo.

Name string
Version string
Revision int
Arch string
Store string
DigestKind cache.DigestKind
Digest string
}

func (p *RemotePackageInfo) PkgName() string { return p.Name }
func (p *RemotePackageInfo) PkgVersion() string { return p.Version }
func (p *RemotePackageInfo) PkgRevision() int { return p.Revision }
func (p *RemotePackageInfo) PkgArch() string { return p.Arch }
func (p *RemotePackageInfo) PkgStore() string { return p.Store }
func (p *RemotePackageInfo) PkgDigestKind() cache.DigestKind { return p.DigestKind }
func (p *RemotePackageInfo) PkgDigest() string { return p.Digest }

// PackageRemote represents the remote from which a package is obtained.
type PackageRemote interface {
// Arch returns the architecture the remote serves packages for, which is
// the target architecture used to request the package, not the
// architecture of the fetched package itself (which may be "all", for
// example).
Arch() string
Fetch() (io.ReadSeekCloser, *RemotePackageInfo, error)
}

var _ PackageRemote = (*archiveRemote)(nil)

type archiveRemote struct {
archive archive.Archive
name string
}

func (d *archiveRemote) Arch() string {
return d.archive.Options().Arch
}

func (d *archiveRemote) Fetch() (io.ReadSeekCloser, *RemotePackageInfo, error) {
reader, info, err := d.archive.Fetch(d.name)
if err != nil {
return nil, nil, err
}
return reader, &RemotePackageInfo{
Name: info.Name,
Version: info.Version,
Arch: info.Arch,
DigestKind: cache.SHA256,
Digest: info.SHA256,
}, nil
}
29 changes: 17 additions & 12 deletions internal/slicer/slicer.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func Run(options *RunOptions) error {
targetDir = filepath.Join(dir, targetDir)
}

pkgArchive, err := selectPkgArchives(options.Archives, options.Selection)
pkgRemotes, err := selectPkgRemotes(options.Archives, options.Selection)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Note to reviewer]: This was pluralized on purpose to avoid confusion with a single PackageRemote instance.

if err != nil {
return err
}
Expand All @@ -108,7 +108,7 @@ func Run(options *RunOptions) error {
extractPackage = make(map[string][]tarball.ExtractInfo)
extract[slice.Package] = extractPackage
}
arch := pkgArchive[slice.Package].Options().Arch
arch := pkgRemotes[slice.Package].Arch()
for targetPath, pathInfo := range slice.Contents {
if targetPath == "" {
continue
Expand Down Expand Up @@ -153,7 +153,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 := pkgRemotes[pkg.Name].Fetch()
if err != nil {
return err
}
Expand Down Expand Up @@ -270,7 +270,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 := pkgRemotes[slice.Package].Arch()
for relPath, pathInfo := range slice.Contents {
if len(pathInfo.Arch) > 0 && !slices.Contains(pathInfo.Arch, arch) {
continue
Expand Down Expand Up @@ -490,10 +490,12 @@ 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) {
// selectPkgRemotes determines the remote for each package in the selection.
// For packages from an archive it selects the highest priority archive
// containing the package unless a particular archive is pinned within the
// package slices file. Packages from a store are not supported yet.
// It returns a map of PackageRemote indexed by package names.
func selectPkgRemotes(archives map[string]archive.Archive, selection *setup.Selection) (map[string]PackageRemote, error) {
sortedArchives := make([]*setup.Archive, 0, len(selection.Release.Archives))
for _, archive := range selection.Release.Archives {
if archive.Priority < 0 {
Expand All @@ -507,9 +509,9 @@ func selectPkgArchives(archives map[string]archive.Archive, selection *setup.Sel
return b.Priority - a.Priority
})

pkgArchive := make(map[string]archive.Archive)
pkgRemotes := make(map[string]PackageRemote)
for _, s := range selection.Slices {
if _, ok := pkgArchive[s.Package]; ok {
if _, ok := pkgRemotes[s.Package]; ok {
continue
}
pkg := selection.Release.Packages[s.Package]
Expand Down Expand Up @@ -538,7 +540,10 @@ 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
pkgRemotes[pkg.Name] = &archiveRemote{
archive: chosen,
name: pkg.RealName,
}
}
return pkgArchive, nil
return pkgRemotes, nil
}
Loading