Publish architecture variants in separate indexes

This commit is contained in:
Hansjoerg Maurer authored and André Roth committed 2026-11-05 21:00:37 +01:00
1 parent 915fd24d7b
commit 6efb8e17fd
6 files changed
+146 -3

No files matched your search

+13
View File
@@ -326,6 +326,19 @@ func (l *PackageList) Architectures(includeSource bool) (result []string) {
return
}
// IndexArchitectures returns repository index architectures present in the list.
// If includeSource is true, the source meta-architecture is included.
func (l *PackageList) IndexArchitectures(includeSource bool) (result []string) {
result = make([]string, 0, 10)
for _, pkg := range l.packages {
arch := pkg.IndexArchitecture()
if arch != ArchitectureAll && (arch != ArchitectureSource || includeSource) && !utils.StrSliceHasItem(result, arch) {
result = append(result, arch)
}
}
return
}
// Strings builds list of strings with package keys
func (l *PackageList) Strings() []string {
result := make([]string, l.Len())
+22
View File
@@ -684,3 +684,25 @@ func (s *PackageListSuite) TestFilterLatestNil(c *C) {
c.Assert(err, ErrorMatches, "package list is nil")
c.Assert(filtered, IsNil)
}
func (s *PackageListSuite) TestArchitectureVariantIndexArchitectures(c *C) {
for _, p := range []*Package{
{Name: "example", Version: "1.0", Architecture: "amd64"},
{Name: "example", Version: "1.0", Architecture: "amd64", ArchitectureVariant: "amd64v3"},
{Name: "example", Version: "2.0", Architecture: "amd64", ArchitectureVariant: "amd64v3"},
{Name: "example", Version: "1.0", Architecture: "i386"},
{Name: "data", Version: "1.0", Architecture: "all"},
{Name: "example", Version: "1.0", Architecture: "source", IsSource: true},
} {
c.Assert(s.list.Add(p), IsNil)
}
indexes := s.list.IndexArchitectures(false)
sort.Strings(indexes)
c.Check(indexes, DeepEquals, []string{"amd64", "amd64v3", "i386"})
indexes = s.list.IndexArchitectures(true)
sort.Strings(indexes)
c.Check(indexes, DeepEquals, []string{"amd64", "amd64v3", "i386", "source"})
base := s.list.Architectures(false)
sort.Strings(base)
c.Check(base, DeepEquals, []string{"amd64", "i386"})
}
+8
View File
@@ -352,6 +352,14 @@ func (p *Package) MatchesArchitecture(arch string) bool {
return p.Architecture == arch
}
// MatchesIndexArchitecture checks membership in a repository index architecture.
func (p *Package) MatchesIndexArchitecture(arch string) bool {
if p.Architecture == ArchitectureAll && arch != ArchitectureSource {
return true
}
return p.IndexArchitecture() == arch
}
func JoinErrors(errs ...error) error {
var combinedErr error
for _, err := range errs {
+23
View File
@@ -580,3 +580,26 @@ SHA256: bbb3a2cb07f741c3995b6d4bb08d772d83582b93a0236d4ea7736bc0370fc320`
const installerPackageMeta = `9d8bb14044dee520f4706ab197dfff10e9e39ecb3c1a402331712154e8284b2e ./MANIFEST.udebs
dab96042d8e25e0f6bbb8d7c5bd78543afb5eb31a4a8b122ece68ab197228028 ./udeb.list`
func (s *PackageSuite) TestArchitectureVariantMatchesIndexArchitecture(c *C) {
for _, tc := range []struct {
base, variant, target string
matches bool
}{
{"amd64", "", "amd64", true},
{"amd64", "", "amd64v3", false},
{"amd64", "amd64v3", "amd64", false},
{"amd64", "amd64v3", "amd64v3", true},
{"all", "", "amd64", true},
{"all", "", "amd64v3", true},
{"all", "", "source", false},
{"source", "", "source", true},
{"source", "", "amd64v3", false},
} {
p := &Package{Architecture: tc.base, ArchitectureVariant: tc.variant, IsSource: tc.base == "source"}
c.Check(p.MatchesIndexArchitecture(tc.target), Equals, tc.matches, Commentf("base=%s variant=%s target=%s", tc.base, tc.variant, tc.target))
}
p := &Package{Architecture: "amd64", ArchitectureVariant: "amd64v3"}
c.Check(p.MatchesArchitecture("amd64"), Equals, true)
c.Check(p.MatchesArchitecture("amd64v3"), Equals, false)
}
+3 -3
View File
@@ -883,7 +883,7 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
if !p.rePublishing {
if len(p.Architectures) == 0 {
for _, list := range lists {
p.Architectures = append(p.Architectures, list.Architectures(true)...)
p.Architectures = append(p.Architectures, list.IndexArchitectures(true)...)
}
}
@@ -941,7 +941,7 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
}
for _, arch := range p.Architectures {
if pkg.MatchesArchitecture(arch) {
if pkg.MatchesIndexArchitecture(arch) {
hadUdebs = hadUdebs || pkg.IsUdeb
var relPath string
@@ -979,7 +979,7 @@ func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageP
batch := tempDB.CreateBatch()
for _, arch := range p.Architectures {
if pkg.MatchesArchitecture(arch) {
if pkg.MatchesIndexArchitecture(arch) {
var bufWriter *bufio.Writer
if !p.SkipContents && !pkg.IsInstaller {
+77
View File
@@ -382,6 +382,83 @@ func (s *PublishedRepoSuite) TestUpdate(c *C) {
c.Assert(result.RemovedComponents(), DeepEquals, []string{})
}
func (s *PublishedRepoSuite) checkArchitectureVariantPublication(c *C, architectures []string) {
list := NewPackageList()
for _, arch := range []string{"amd64", "amd64v3"} {
filename := "example_1.0_" + arch + ".deb"
stanza := Stanza{"Package": "example", "Version": "1.0", "Architecture": "amd64", "Filename": filename}
if arch == "amd64v3" {
stanza["Architecture-Variant"] = "amd64v3"
}
p := NewPackageFromControlFile(stanza)
inputPath := filepath.Join(c.MkDir(), filename)
c.Assert(os.WriteFile(inputPath, nil, 0644), IsNil)
var err error
p.Files()[0].PoolPath, err = s.packagePool.Import(inputPath, filename, &p.Files()[0].Checksums, false, s.cs)
c.Assert(err, IsNil)
p.UpdateFiles(p.Files())
c.Assert(s.packageCollection.Update(p), IsNil)
c.Assert(list.Add(p), IsNil)
}
local := NewLocalRepo("architecture-variant", "")
local.packageRefs = NewPackageRefListFromPackageList(list)
c.Assert(s.factory.LocalRepoCollection().Add(local), IsNil)
repo, err := NewPublishedRepo("", "variant-test", "test", architectures, []string{"main"}, []interface{}{local}, s.factory, false)
c.Assert(err, IsNil)
repo.SkipContents = true
c.Assert(repo.Publish(s.packagePool, s.provider, s.factory, &NullSigner{}, nil, false, ""), IsNil)
root := filepath.Join(s.publishedStorage.PublicPath(), "variant-test")
releaseData, err := os.ReadFile(filepath.Join(root, "dists/test/Release"))
c.Assert(err, IsNil)
release, err := NewControlFileReader(bytes.NewReader(releaseData), true, false).ReadStanza()
c.Assert(err, IsNil)
c.Check(release["Architectures"], Equals, "amd64 amd64v3")
for _, arch := range []string{"amd64", "amd64v3"} {
filename := "example_1.0_" + arch + ".deb"
c.Check(filepath.Join(root, "pool/main/e/example", filename), PathExists)
indexPath := filepath.Join(root, "dists/test/main", "binary-"+arch, "Packages")
data, err := os.ReadFile(indexPath)
if !c.Check(err, IsNil, Commentf("index %s must exist", arch)) {
continue
}
reader := NewControlFileReader(bytes.NewReader(data), false, false)
var entries []Stanza
for {
entry, err := reader.ReadStanza()
c.Assert(err, IsNil)
if entry == nil {
break
}
entries = append(entries, entry)
}
c.Check(entries, HasLen, 1, Commentf("index %s must contain exactly one package", arch))
var filenames []string
for _, entry := range entries {
filenames = append(filenames, entry["Filename"])
c.Check(entry["Package"], Equals, "example")
c.Check(entry["Version"], Equals, "1.0")
c.Check(entry["Architecture"], Equals, "amd64")
if entry["Filename"] == "pool/main/e/example/example_1.0_amd64v3.deb" {
c.Check(entry["Architecture-Variant"], Equals, "amd64v3")
} else {
_, hasVariant := entry["Architecture-Variant"]
c.Check(hasVariant, Equals, false)
}
}
c.Check(filenames, DeepEquals, []string{"pool/main/e/example/" + filename}, Commentf("index %s package membership", arch))
}
}
func (s *PublishedRepoSuite) TestArchitectureVariantPublishAutoArchitectures(c *C) {
s.checkArchitectureVariantPublication(c, nil)
}
func (s *PublishedRepoSuite) TestArchitectureVariantPublishExplicitArchitectures(c *C) {
s.checkArchitectureVariantPublication(c, []string{"amd64", "amd64v3"})
}
func (s *PublishedRepoSuite) TestPublish(c *C) {
err := s.repo.Publish(s.packagePool, s.provider, s.factory, &NullSigner{}, nil, false, "")
c.Assert(err, IsNil)