diff --git a/debian/list.go b/debian/list.go index 42a8245b..0b771f0c 100644 --- a/debian/list.go +++ b/debian/list.go @@ -8,14 +8,40 @@ import ( "sort" ) +// Dependency options +const ( + // DepFollowSource pulls source packages when required + DepFollowSource = 1 << iota + // DepFollowSuggests pulls from suggests + DepFollowSuggests + // DepFollowRecommends pulls from recommends + DepFollowRecommends + // DepFollowAllVariants follows all variants if depends on "a | b" + DepFollowAllVariants +) + // PackageList is list of unique (by key) packages // // It could be seen as repo snapshot, repo contents, result of filtering, // merge, etc. +// +// If indexed, PackageList starts supporting searching type PackageList struct { + // Straight list of packages as map packages map[string]*Package + // Has index been prepared? + indexed bool + // Indexed list of packages, sorted by name internally + packagesIndex []*Package + // Map of packages for each virtual package (provides) + providesIndex map[string][]*Package } +// Verify interface +var ( + _ sort.Interface = &PackageList{} +) + // NewPackageList creates empty package list func NewPackageList() *PackageList { return &PackageList{packages: make(map[string]*Package, 1000)} @@ -51,6 +77,19 @@ func (l *PackageList) Add(p *Package) error { return nil } l.packages[key] = p + + if l.indexed { + for _, provides := range p.Provides { + l.providesIndex[provides] = append(l.providesIndex[provides], p) + } + + i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= p.Name }) + + // insert p into l.packagesIndex in position i + l.packagesIndex = append(l.packagesIndex, nil) + copy(l.packagesIndex[i+1:], l.packagesIndex[i:]) + l.packagesIndex[i] = p + } return nil } @@ -71,6 +110,54 @@ func (l *PackageList) Len() int { return len(l.packages) } +// Append adds content from one package list to another +func (l *PackageList) Append(pl *PackageList) error { + if l.indexed { + panic("Append not supported when indexed") + } + for k, p := range pl.packages { + existing, ok := l.packages[k] + if ok { + if !existing.Equals(p) { + return fmt.Errorf("conflict in package %s: %#v != %#v", p, existing, p) + } + } else { + l.packages[k] = p + } + } + + return nil +} + +// Remove removes package from the list, and updates index when required +func (l *PackageList) Remove(p *Package) { + delete(l.packages, string(p.Key())) + if l.indexed { + for _, provides := range p.Provides { + for i, pkg := range l.providesIndex[provides] { + if pkg.Equals(p) { + // remove l.ProvidesIndex[provides][i] w/o preserving order + l.providesIndex[provides][len(l.providesIndex[provides])-1], l.providesIndex[provides][i], l.providesIndex[provides] = + nil, l.providesIndex[provides][len(l.providesIndex[provides])-1], l.providesIndex[provides][:len(l.providesIndex[provides])-1] + break + } + } + } + + i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= p.Name }) + for i < len(l.packagesIndex) && l.packagesIndex[i].Name == p.Name { + if l.packagesIndex[i].Equals(p) { + // remove l.packagesIndex[i] preserving order + copy(l.packagesIndex[i:], l.packagesIndex[i+1:]) + l.packagesIndex[len(l.packagesIndex)-1] = nil + l.packagesIndex = l.packagesIndex[:len(l.packagesIndex)-1] + break + } + i++ + } + } +} + // Architectures returns list of architectures present in packages func (l *PackageList) Architectures() (result []string) { result = make([]string, 0, 10) @@ -82,22 +169,10 @@ func (l *PackageList) Architectures() (result []string) { return } -// Dependency options -const ( - // DepFollowSource pulls source packages when required - DepFollowSource = 1 << iota - // DepFollowSuggests pulls from suggests - DepFollowSuggests - // DepFollowRecommends pulls from recommends - DepFollowRecommends - // DepFollowAllVariants follows all variants if depends on "a | b" - DepFollowAllVariants -) - // VerifyDependencies looks for missing dependencies in package list. // // Analysis would be peformed for each architecture, in specified sources -func (l *PackageList) VerifyDependencies(options int, architectures []string, sources *PackageIndexedList) ([]Dependency, error) { +func (l *PackageList) VerifyDependencies(options int, architectures []string, sources *PackageList) ([]Dependency, error) { missing := make([]Dependency, 0, 128) for _, arch := range architectures { @@ -109,7 +184,7 @@ func (l *PackageList) VerifyDependencies(options int, architectures []string, so } for _, dep := range p.GetDependencies(options) { - variants, err := parseDependencyVariants(dep) + variants, err := ParseDependencyVariants(dep) if err != nil { return nil, fmt.Errorf("unable to process package %s: %s", p, err) } @@ -147,79 +222,54 @@ func (l *PackageList) VerifyDependencies(options int, architectures []string, so return missing, nil } -// PackageIndexedList is a list of packages optimized for satisfying searches -type PackageIndexedList struct { - // List of packages, sorted by name internally - packages []*Package - // Map of packages for each virtual package - providesList map[string][]*Package +// Swap swaps two packages in index +func (l *PackageList) Swap(i, j int) { + l.packagesIndex[i], l.packagesIndex[j] = l.packagesIndex[j], l.packagesIndex[i] } -// Verify interface -var ( - _ sort.Interface = &PackageIndexedList{} -) - -// NewPackageIndexedList creates empty PackageIndexedList -func NewPackageIndexedList() *PackageIndexedList { - return &PackageIndexedList{ - packages: make([]*Package, 0, 1024), - } -} - -// Len returns number of refs -func (l *PackageIndexedList) Len() int { - return len(l.packages) -} - -// Swap swaps two refs -func (l *PackageIndexedList) Swap(i, j int) { - l.packages[i], l.packages[j] = l.packages[j], l.packages[i] -} - -// Compare compares two refs in lexographical order -func (l *PackageIndexedList) Less(i, j int) bool { - return l.packages[i].Name < l.packages[j].Name +// Compare compares two names in lexographical order +func (l *PackageList) Less(i, j int) bool { + return l.packagesIndex[i].Name < l.packagesIndex[j].Name } // PrepareIndex prepares list for indexing -func (l *PackageIndexedList) PrepareIndex() { - sort.Sort(l) +func (l *PackageList) PrepareIndex() { + l.packagesIndex = make([]*Package, l.Len()) + l.providesIndex = make(map[string][]*Package, 128) - l.providesList = make(map[string][]*Package, 128) + i := 0 for _, p := range l.packages { + l.packagesIndex[i] = p + i++ + for _, provides := range p.Provides { - l.providesList[provides] = append(l.providesList[provides], p) + l.providesIndex[provides] = append(l.providesIndex[provides], p) } } -} -// Append adds more packages to the index -func (l *PackageIndexedList) Append(pl *PackageList) { - pp := make([]*Package, pl.Len()) - i := 0 - for _, p := range pl.packages { - pp[i] = p - i++ - } + sort.Sort(l) - l.packages = append(l.packages, pp...) + l.indexed = true } // Search searches package index for specified package -func (l *PackageIndexedList) Search(dep Dependency) *Package { +func (l *PackageList) Search(dep Dependency) *Package { + if !l.indexed { + panic("list not indexed, can't search") + } + if dep.Relation == VersionDontCare { - for _, p := range l.providesList[dep.Pkg] { + for _, p := range l.providesIndex[dep.Pkg] { if p.MatchesArchitecture(dep.Architecture) { return p } } } - i := sort.Search(len(l.packages), func(j int) bool { return l.packages[j].Name >= dep.Pkg }) + i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= dep.Pkg }) - for i < len(l.packages) && l.packages[i].Name == dep.Pkg { - p := l.packages[i] + for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg { + p := l.packagesIndex[i] if p.MatchesArchitecture(dep.Architecture) { if dep.Relation == VersionDontCare { return p diff --git a/debian/list_test.go b/debian/list_test.go index 09cf76c4..9ec3e75c 100644 --- a/debian/list_test.go +++ b/debian/list_test.go @@ -8,8 +8,13 @@ import ( ) type PackageListSuite struct { + // Simple list with "real" packages from stanzas list *PackageList p1, p2, p3, p4, p5, p6 *Package + + // Mocked packages in list + packages []*Package + il *PackageList } var _ = Suite(&PackageListSuite{}) @@ -31,6 +36,27 @@ func (s *PackageListSuite) SetUpTest(c *C) { stanza = packageStanza.Copy() stanza["Version"] = "99.1" s.p6 = NewPackageFromControlFile(stanza) + + s.il = NewPackageList() + s.packages = []*Package{ + &Package{Name: "lib", Version: "1.0", Architecture: "i386", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"mail-agent"}}, + &Package{Name: "dpkg", Version: "1.7", Architecture: "i386", Provides: []string{"package-installer"}}, + &Package{Name: "data", Version: "1.1~bp1", Architecture: "all", PreDepends: []string{"dpkg (>= 1.6)"}}, + &Package{Name: "app", Version: "1.1~bp1", Architecture: "i386", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}, + &Package{Name: "mailer", Version: "3.5.8", Architecture: "i386", Provides: []string{"mail-agent"}}, + &Package{Name: "app", Version: "1.1~bp1", Architecture: "amd64", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}, + &Package{Name: "app", Version: "1.1~bp1", Architecture: "arm", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9) | libx (>= 1.5)", "data (>= 1.0) | mail-agent"}}, + &Package{Name: "app", Version: "1.0", Architecture: "s390", PreDepends: []string{"dpkg >= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}, + &Package{Name: "aa", Version: "2.0-1", Architecture: "i386", PreDepends: []string{"dpkg (>= 1.6)"}}, + &Package{Name: "dpkg", Version: "1.6.1-3", Architecture: "amd64", Provides: []string{"package-installer"}}, + &Package{Name: "libx", Version: "1.5", Architecture: "arm", PreDepends: []string{"dpkg (>= 1.6)"}}, + &Package{Name: "dpkg", Version: "1.6.1-3", Architecture: "arm", Provides: []string{"package-installer"}}, + } + for _, p := range s.packages { + s.il.Add(p) + } + s.il.PrepareIndex() + } func (s *PackageListSuite) TestAddLen(c *C) { @@ -44,6 +70,73 @@ func (s *PackageListSuite) TestAddLen(c *C) { c.Check(s.list.Add(s.p4), ErrorMatches, "conflict in package.*") } +func (s *PackageListSuite) TestRemove(c *C) { + c.Check(s.list.Add(s.p1), IsNil) + c.Check(s.list.Add(s.p3), IsNil) + c.Check(s.list.Len(), Equals, 2) + + s.list.Remove(s.p1) + c.Check(s.list.Len(), Equals, 1) +} + +func (s *PackageListSuite) TestAddWhenIndexed(c *C) { + c.Check(s.list.Len(), Equals, 0) + s.list.PrepareIndex() + + c.Check(s.list.Add(&Package{Name: "a1st", Version: "1.0", Architecture: "i386", Provides: []string{"fa", "fb"}}), IsNil) + c.Check(s.list.packagesIndex[0].Name, Equals, "a1st") + c.Check(s.list.providesIndex["fa"][0].Name, Equals, "a1st") + c.Check(s.list.providesIndex["fb"][0].Name, Equals, "a1st") + + c.Check(s.list.Add(&Package{Name: "c3rd", Version: "1.0", Architecture: "i386", Provides: []string{"fa"}}), IsNil) + c.Check(s.list.packagesIndex[0].Name, Equals, "a1st") + c.Check(s.list.packagesIndex[1].Name, Equals, "c3rd") + c.Check(s.list.providesIndex["fa"][0].Name, Equals, "a1st") + c.Check(s.list.providesIndex["fa"][1].Name, Equals, "c3rd") + c.Check(s.list.providesIndex["fb"][0].Name, Equals, "a1st") + + c.Check(s.list.Add(&Package{Name: "b2nd", Version: "1.0", Architecture: "i386"}), IsNil) + c.Check(s.list.packagesIndex[0].Name, Equals, "a1st") + c.Check(s.list.packagesIndex[1].Name, Equals, "b2nd") + c.Check(s.list.packagesIndex[2].Name, Equals, "c3rd") + c.Check(s.list.providesIndex["fa"][0].Name, Equals, "a1st") + c.Check(s.list.providesIndex["fa"][1].Name, Equals, "c3rd") + c.Check(s.list.providesIndex["fb"][0].Name, Equals, "a1st") +} + +func (s *PackageListSuite) TestRemoveWhenIndexed(c *C) { + s.il.Remove(s.packages[0]) + names := make([]string, s.il.Len()) + for i, p := range s.il.packagesIndex { + names[i] = p.Name + } + c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "dpkg", "libx", "mailer"}) + + s.il.Remove(s.packages[4]) + names = make([]string, s.il.Len()) + for i, p := range s.il.packagesIndex { + names[i] = p.Name + } + c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "dpkg", "libx"}) + c.Check(s.il.providesIndex["mail-agent"], DeepEquals, []*Package{}) + + s.il.Remove(s.packages[9]) + names = make([]string, s.il.Len()) + for i, p := range s.il.packagesIndex { + names[i] = p.Name + } + c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "libx"}) + c.Check(s.il.providesIndex["package-installer"], HasLen, 2) + + s.il.Remove(s.packages[1]) + names = make([]string, s.il.Len()) + for i, p := range s.il.packagesIndex { + names[i] = p.Name + } + c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "libx"}) + c.Check(s.il.providesIndex["package-installer"], DeepEquals, []*Package{s.packages[11]}) +} + func (s *PackageListSuite) TestForeach(c *C) { s.list.Add(s.p1) s.list.Add(s.p3) @@ -67,6 +160,89 @@ func (s *PackageListSuite) TestForeach(c *C) { } +func (s *PackageListSuite) TestIndex(c *C) { + c.Check(len(s.il.providesIndex), Equals, 2) + c.Check(len(s.il.providesIndex["mail-agent"]), Equals, 1) + c.Check(len(s.il.providesIndex["package-installer"]), Equals, 3) + c.Check(s.il.packagesIndex[0], Equals, s.packages[8]) +} + +func (s *PackageListSuite) TestAppend(c *C) { + s.list.Add(s.p1) + s.list.Add(s.p3) + + err := s.list.Append(s.il) + c.Check(err, IsNil) + c.Check(s.list.Len(), Equals, 14) + + list := NewPackageList() + list.Add(s.p4) + + err = s.list.Append(list) + c.Check(err, ErrorMatches, "conflict.*") + + s.list.PrepareIndex() + c.Check(func() { s.list.Append(s.il) }, Panics, "Append not supported when indexed") +} + +func (s *PackageListSuite) TestSearch(c *C) { + c.Check(func() { s.list.Search(Dependency{Architecture: "i386", Pkg: "app"}) }, Panics, "list not indexed, can't search") + + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app"}), Equals, s.packages[3]) + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "mail-agent"}), Equals, s.packages[4]) + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "puppy"}), IsNil) + + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionEqual, Version: "1.1~bp1"}), Equals, s.packages[3]) + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionEqual, Version: "1.1~bp2"}), IsNil) + + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLess, Version: "1.1"}), Equals, s.packages[3]) + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLess, Version: "1.1~~"}), IsNil) + + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1"}), Equals, s.packages[3]) + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1~bp1"}), Equals, s.packages[3]) + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1~~"}), IsNil) + + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreater, Version: "1.0"}), Equals, s.packages[3]) + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreater, Version: "1.2"}), IsNil) + + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.0"}), Equals, s.packages[3]) + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.1~bp1"}), Equals, s.packages[3]) + c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.2"}), IsNil) +} + +func (s *PackageListSuite) TestVerifyDependencies(c *C) { + missing, err := s.il.VerifyDependencies(0, []string{"i386"}, s.il) + + c.Check(err, IsNil) + c.Check(missing, DeepEquals, []Dependency{}) + + missing, err = s.il.VerifyDependencies(0, []string{"i386", "amd64"}, s.il) + + c.Check(err, IsNil) + c.Check(missing, DeepEquals, []Dependency{Dependency{Pkg: "lib", Relation: VersionGreater, Version: "0.9", Architecture: "amd64"}}) + + missing, err = s.il.VerifyDependencies(0, []string{"arm"}, s.il) + + c.Check(err, IsNil) + c.Check(missing, DeepEquals, []Dependency{}) + + missing, err = s.il.VerifyDependencies(DepFollowAllVariants, []string{"arm"}, s.il) + + c.Check(err, IsNil) + c.Check(missing, DeepEquals, []Dependency{Dependency{Pkg: "lib", Relation: VersionGreater, Version: "0.9", Architecture: "arm"}, + Dependency{Pkg: "mail-agent", Relation: VersionDontCare, Version: "", Architecture: "arm"}}) + + _, err = s.il.VerifyDependencies(0, []string{"i386", "amd64", "s390"}, s.il) + + c.Check(err, ErrorMatches, "unable to process package app-1.0_s390:.*") +} + +func (s *PackageListSuite) TestArchitectures(c *C) { + archs := s.il.Architectures() + sort.Strings(archs) + c.Check(archs, DeepEquals, []string{"amd64", "arm", "i386", "s390"}) +} + func (s *PackageListSuite) TestNewPackageListFromRefList(c *C) { db, _ := database.OpenDB(c.MkDir()) coll := NewPackageCollection(db) @@ -146,98 +322,3 @@ func (s *PackageListSuite) TestPackageRefListForeach(c *C) { c.Check(err, Equals, e) } - -type PackageIndexedListSuite struct { - packages []*Package - pl *PackageList - list *PackageIndexedList -} - -var _ = Suite(&PackageIndexedListSuite{}) - -func (s *PackageIndexedListSuite) SetUpTest(c *C) { - s.pl = NewPackageList() - s.packages = []*Package{ - &Package{Name: "lib", Version: "1.0", Architecture: "i386", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"mail-agent"}}, - &Package{Name: "dpkg", Version: "1.7", Architecture: "i386"}, - &Package{Name: "data", Version: "1.1~bp1", Architecture: "all", PreDepends: []string{"dpkg (>= 1.6)"}}, - &Package{Name: "app", Version: "1.1~bp1", Architecture: "i386", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}, - &Package{Name: "mailer", Version: "3.5.8", Architecture: "i386", Provides: []string{"mail-agent"}}, - &Package{Name: "app", Version: "1.1~bp1", Architecture: "amd64", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}, - &Package{Name: "app", Version: "1.1~bp1", Architecture: "arm", PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9) | libx (>= 1.5)", "data (>= 1.0) | mail-agent"}}, - &Package{Name: "app", Version: "1.0", Architecture: "s390", PreDepends: []string{"dpkg >= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}, - &Package{Name: "aa", Version: "2.0-1", Architecture: "i386", PreDepends: []string{"dpkg (>= 1.6)"}}, - &Package{Name: "dpkg", Version: "1.6.1-3", Architecture: "amd64"}, - &Package{Name: "libx", Version: "1.5", Architecture: "arm", PreDepends: []string{"dpkg (>= 1.6)"}}, - &Package{Name: "dpkg", Version: "1.6.1-3", Architecture: "arm"}, - } - for _, p := range s.packages { - s.pl.Add(p) - } - - s.list = NewPackageIndexedList() - s.list.Append(s.pl) - s.list.PrepareIndex() -} - -func (s *PackageIndexedListSuite) TestIndex(c *C) { - c.Check(len(s.list.providesList), Equals, 1) - c.Check(len(s.list.providesList["mail-agent"]), Equals, 1) - c.Check(s.list.packages[0], Equals, s.packages[8]) -} - -func (s *PackageIndexedListSuite) TestSearch(c *C) { - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app"}), Equals, s.packages[3]) - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "mail-agent"}), Equals, s.packages[4]) - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "puppy"}), IsNil) - - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionEqual, Version: "1.1~bp1"}), Equals, s.packages[3]) - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionEqual, Version: "1.1~bp2"}), IsNil) - - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLess, Version: "1.1"}), Equals, s.packages[3]) - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLess, Version: "1.1~~"}), IsNil) - - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1"}), Equals, s.packages[3]) - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1~bp1"}), Equals, s.packages[3]) - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1~~"}), IsNil) - - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreater, Version: "1.0"}), Equals, s.packages[3]) - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreater, Version: "1.2"}), IsNil) - - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.0"}), Equals, s.packages[3]) - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.1~bp1"}), Equals, s.packages[3]) - c.Check(s.list.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.2"}), IsNil) -} - -func (s *PackageIndexedListSuite) TestVerifyDependencies(c *C) { - missing, err := s.pl.VerifyDependencies(0, []string{"i386"}, s.list) - - c.Check(err, IsNil) - c.Check(missing, DeepEquals, []Dependency{}) - - missing, err = s.pl.VerifyDependencies(0, []string{"i386", "amd64"}, s.list) - - c.Check(err, IsNil) - c.Check(missing, DeepEquals, []Dependency{Dependency{Pkg: "lib", Relation: VersionGreater, Version: "0.9", Architecture: "amd64"}}) - - missing, err = s.pl.VerifyDependencies(0, []string{"arm"}, s.list) - - c.Check(err, IsNil) - c.Check(missing, DeepEquals, []Dependency{}) - - missing, err = s.pl.VerifyDependencies(DepFollowAllVariants, []string{"arm"}, s.list) - - c.Check(err, IsNil) - c.Check(missing, DeepEquals, []Dependency{Dependency{Pkg: "lib", Relation: VersionGreater, Version: "0.9", Architecture: "arm"}, - Dependency{Pkg: "mail-agent", Relation: VersionDontCare, Version: "", Architecture: "arm"}}) - - _, err = s.pl.VerifyDependencies(0, []string{"i386", "amd64", "s390"}, s.list) - - c.Check(err, ErrorMatches, "unable to process package app-1.0_s390:.*") -} - -func (s *PackageIndexedListSuite) TestArchitectures(c *C) { - archs := s.pl.Architectures() - sort.Strings(archs) - c.Check(archs, DeepEquals, []string{"amd64", "arm", "i386", "s390"}) -}