Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a948b10
feat: add sha256
lczyk Jul 6, 2026
e1b7e40
docs: comment
lczyk Jul 6, 2026
daf5864
tests: test SHA512 cache entries
upils Jul 7, 2026
46d5658
fix: refine comments
upils Jul 7, 2026
1511187
tests: use stonking for SHA512 tests
upils Jul 7, 2026
bbdf2fe
fix: rely on ok to check digest
upils Jul 7, 2026
7501ca0
Merge remote-tracking branch 'canonical/main' into fix/issue-305-acce…
lczyk Jul 7, 2026
c973b90
test: cover by-hash over sha512
lczyk Jul 7, 2026
9fa6d53
test: propagate digest kind to packages in test helper
lczyk Jul 7, 2026
46fefb3
test: cover release publishing both digests
lczyk Jul 7, 2026
1e1a0d1
refactor: rename digestField to digestSection
lczyk Jul 7, 2026
58c0e97
test: inline makeSha256
lczyk Jul 7, 2026
82dd7e7
test: make digest kinds an archive-wide property
lczyk Jul 7, 2026
f8eb118
test: drop implicit SHA256 default for digest kinds
lczyk Jul 7, 2026
bc4b7f6
fix: check Walk return in inheritDigestKinds
lczyk Jul 7, 2026
c179489
fix: build by-hash URLs from strongest digest
lczyk Jul 8, 2026
744fae9
refactor: name digest fields, not sections
lczyk Jul 8, 2026
8c5cbc1
fix: panic on unknown digest kind in test archive
lczyk Jul 8, 2026
7a308a3
refactor: drop redundant inheritDigestKinds call
lczyk Jul 8, 2026
2ec8ab9
refactor: propagate Walk errors in test archive
lczyk Jul 8, 2026
c5ce9e3
docs: describe digestKinds field, not its writer
lczyk Jul 8, 2026
1397709
refactor: packages read digest kinds through the release
lczyk Jul 8, 2026
7cf965b
refactor: adopt packages through Walk
lczyk Jul 8, 2026
abfc91f
refactor: rename adoptPackages to wirePackages
lczyk Jul 8, 2026
0ebadf2
docs: keep findDigest comment above the table format
lczyk Jul 8, 2026
606e7a1
test: cover by-hash dirs beyond the strongest digest
lczyk Jul 8, 2026
86024cd
docs: by-hash dirs beyond the strongest are legal
lczyk Jul 8, 2026
b70e1b4
Update internal/archive/testarchive/testarchive.go
lczyk Jul 9, 2026
311052e
refactor: single strongest-first digest preference
lczyk Jul 9, 2026
0c9e9e3
test: pass DigestKinds instead of release pointer
upils Jul 15, 2026
b9da3c9
refactor: strongest kind at the release level
upils Jul 15, 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
63 changes: 53 additions & 10 deletions internal/archive/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,9 @@ func (a *ubuntuArchive) Fetch(pkg string) (io.ReadSeekCloser, *PackageInfo, erro
return nil, nil, err
}
path := section.Get("Filename")
digest, digestKind := packageDigest(section)
logf("Fetching %s...", path)
reader, err := index.fetch(path, section.Get("SHA256"), fetchBulk)
reader, err := index.fetch(path, digest, digestKind, fetchBulk)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -280,7 +281,9 @@ func openUbuntu(options *Options) (Archive, error) {

func (index *ubuntuIndex) fetchRelease() error {
logf("Fetching %s %s %s suite details...", index.displayName(), index.version, index.suite)
reader, err := index.fetch(index.distPath("InRelease"), "", fetchDefault)
// InRelease has no digest to check against (it is verified by its PGP
// signature below), so the digest kind here is arbitrary.
reader, err := index.fetch(index.distPath("InRelease"), "", cache.SHA256, fetchDefault)
if err != nil {
return err
}
Expand Down Expand Up @@ -328,10 +331,47 @@ func (index *ubuntuIndex) fetchRelease() error {
return nil
}

// digestField is an archive checksum field Chisel can verify. Its name
// doubles as the by-hash directory name in the archive layout.
type digestField struct {
name string
kind cache.DigestKind
}

// digestFields lists the checksum fields Chisel can verify, in order of
// preference: strongest first. The order also matches the by-hash archive
// layout, where only the by-hash directory of the strongest advertised hash
// is guaranteed to exist.
var digestFields = []digestField{
Comment thread
lczyk marked this conversation as resolved.
{"SHA512", cache.SHA512},
{"SHA256", cache.SHA256},
}

// findDigest returns the digest recorded for path in the release, along with
// the field it was found in, trying the given fields in order.
func findDigest(release control.Section, path string, order []digestField) (digest string, field digestField) {
for _, f := range order {
if d, _, ok := control.ParsePathInfo(release.Get(f.name), path); ok {
return d, f
}
}
return "", digestField{}
}

func packageDigest(section control.Section) (digest string, kind cache.DigestKind) {
for _, f := range digestFields {
if d := section.Get(f.name); d != "" {
return d, f.kind
}
}
// No digest advertised; fall back to SHA256 so the package can still be
// cached and retrieved by its computed digest.
return "", cache.SHA256
}

func (index *ubuntuIndex) fetchIndex() error {
releaseDigests := index.release.Get("SHA256")
packagesPath := fmt.Sprintf("%s/binary-%s/Packages", index.component, index.arch)
packagesDigest, _, _ := control.ParsePathInfo(releaseDigests, packagesPath)
packagesDigest, field := findDigest(index.release, packagesPath, digestFields)
if packagesDigest == "" {
return fmt.Errorf("%s is missing from %s %s component digests", packagesPath, index.suite, index.component)
}
Expand All @@ -345,10 +385,14 @@ func (index *ubuntuIndex) fetchIndex() error {
packagesGzPath := packagesPath + ".gz"
var reader io.ReadSeekCloser
if index.release.Get("Acquire-By-Hash") == "yes" {
packagesGzDigest, _, _ := control.ParsePathInfo(releaseDigests, packagesGzPath)
// By-hash directories are only guaranteed to exist for the strongest
// hash the archive advertises, which is what findDigest prefers. If
// the archive advertises a hash stronger than any Chisel knows, the
// URL may 404 and the named-path fallback below applies.
packagesGzDigest, byHashField := findDigest(index.release, packagesGzPath, digestFields)
if packagesGzDigest != "" {
packagesByHashPath := fmt.Sprintf("%s/binary-%s/by-hash/SHA256/%s", index.component, index.arch, packagesGzDigest)
r, err := index.fetch(index.distPath(packagesByHashPath), packagesDigest, fetchBulk|fetchGzip)
packagesByHashPath := fmt.Sprintf("%s/binary-%s/by-hash/%s/%s", index.component, index.arch, byHashField.name, packagesGzDigest)
r, err := index.fetch(index.distPath(packagesByHashPath), packagesDigest, field.kind, fetchBulk|fetchGzip)
if err != nil && err != errNotFound {
return err
}
Expand All @@ -358,7 +402,7 @@ func (index *ubuntuIndex) fetchIndex() error {
}
}
if reader == nil {
r, err := index.fetch(index.distPath(packagesGzPath), packagesDigest, fetchBulk|fetchGzip)
r, err := index.fetch(index.distPath(packagesGzPath), packagesDigest, field.kind, fetchBulk|fetchGzip)
if err != nil {
return err
}
Expand Down Expand Up @@ -399,8 +443,7 @@ func (index *ubuntuIndex) distPath(suffix string) string {
return "dists/" + index.suite + "/" + suffix
}

func (index *ubuntuIndex) fetch(path, digest string, flags fetchFlags) (io.ReadSeekCloser, error) {
const digestKind = cache.SHA256
func (index *ubuntuIndex) fetch(path, digest string, digestKind cache.DigestKind, flags fetchFlags) (io.ReadSeekCloser, error) {
reader, err := index.archive.cache.Open(digestKind, digest)
if err == nil {
return reader, nil
Expand Down
Loading
Loading