mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-08 22:30:41 +00:00
Merge PackageList & PackageIndexedList, support for package removal.
This commit is contained in:
Vendored
+114
-64
@@ -8,14 +8,40 @@ import (
|
|||||||
"sort"
|
"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
|
// PackageList is list of unique (by key) packages
|
||||||
//
|
//
|
||||||
// It could be seen as repo snapshot, repo contents, result of filtering,
|
// It could be seen as repo snapshot, repo contents, result of filtering,
|
||||||
// merge, etc.
|
// merge, etc.
|
||||||
|
//
|
||||||
|
// If indexed, PackageList starts supporting searching
|
||||||
type PackageList struct {
|
type PackageList struct {
|
||||||
|
// Straight list of packages as map
|
||||||
packages map[string]*Package
|
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
|
// NewPackageList creates empty package list
|
||||||
func NewPackageList() *PackageList {
|
func NewPackageList() *PackageList {
|
||||||
return &PackageList{packages: make(map[string]*Package, 1000)}
|
return &PackageList{packages: make(map[string]*Package, 1000)}
|
||||||
@@ -51,6 +77,19 @@ func (l *PackageList) Add(p *Package) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
l.packages[key] = p
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +110,54 @@ func (l *PackageList) Len() int {
|
|||||||
return len(l.packages)
|
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
|
// Architectures returns list of architectures present in packages
|
||||||
func (l *PackageList) Architectures() (result []string) {
|
func (l *PackageList) Architectures() (result []string) {
|
||||||
result = make([]string, 0, 10)
|
result = make([]string, 0, 10)
|
||||||
@@ -82,22 +169,10 @@ func (l *PackageList) Architectures() (result []string) {
|
|||||||
return
|
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.
|
// VerifyDependencies looks for missing dependencies in package list.
|
||||||
//
|
//
|
||||||
// Analysis would be peformed for each architecture, in specified sources
|
// 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)
|
missing := make([]Dependency, 0, 128)
|
||||||
|
|
||||||
for _, arch := range architectures {
|
for _, arch := range architectures {
|
||||||
@@ -109,7 +184,7 @@ func (l *PackageList) VerifyDependencies(options int, architectures []string, so
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, dep := range p.GetDependencies(options) {
|
for _, dep := range p.GetDependencies(options) {
|
||||||
variants, err := parseDependencyVariants(dep)
|
variants, err := ParseDependencyVariants(dep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to process package %s: %s", p, err)
|
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
|
return missing, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackageIndexedList is a list of packages optimized for satisfying searches
|
// Swap swaps two packages in index
|
||||||
type PackageIndexedList struct {
|
func (l *PackageList) Swap(i, j int) {
|
||||||
// List of packages, sorted by name internally
|
l.packagesIndex[i], l.packagesIndex[j] = l.packagesIndex[j], l.packagesIndex[i]
|
||||||
packages []*Package
|
|
||||||
// Map of packages for each virtual package
|
|
||||||
providesList map[string][]*Package
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify interface
|
// Compare compares two names in lexographical order
|
||||||
var (
|
func (l *PackageList) Less(i, j int) bool {
|
||||||
_ sort.Interface = &PackageIndexedList{}
|
return l.packagesIndex[i].Name < l.packagesIndex[j].Name
|
||||||
)
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareIndex prepares list for indexing
|
// PrepareIndex prepares list for indexing
|
||||||
func (l *PackageIndexedList) PrepareIndex() {
|
func (l *PackageList) PrepareIndex() {
|
||||||
sort.Sort(l)
|
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 {
|
for _, p := range l.packages {
|
||||||
|
l.packagesIndex[i] = p
|
||||||
|
i++
|
||||||
|
|
||||||
for _, provides := range p.Provides {
|
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
|
sort.Sort(l)
|
||||||
func (l *PackageIndexedList) Append(pl *PackageList) {
|
|
||||||
pp := make([]*Package, pl.Len())
|
|
||||||
i := 0
|
|
||||||
for _, p := range pl.packages {
|
|
||||||
pp[i] = p
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
l.packages = append(l.packages, pp...)
|
l.indexed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search searches package index for specified package
|
// 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 {
|
if dep.Relation == VersionDontCare {
|
||||||
for _, p := range l.providesList[dep.Pkg] {
|
for _, p := range l.providesIndex[dep.Pkg] {
|
||||||
if p.MatchesArchitecture(dep.Architecture) {
|
if p.MatchesArchitecture(dep.Architecture) {
|
||||||
return p
|
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 {
|
for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
|
||||||
p := l.packages[i]
|
p := l.packagesIndex[i]
|
||||||
if p.MatchesArchitecture(dep.Architecture) {
|
if p.MatchesArchitecture(dep.Architecture) {
|
||||||
if dep.Relation == VersionDontCare {
|
if dep.Relation == VersionDontCare {
|
||||||
return p
|
return p
|
||||||
|
|||||||
Vendored
+176
-95
@@ -8,8 +8,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type PackageListSuite struct {
|
type PackageListSuite struct {
|
||||||
|
// Simple list with "real" packages from stanzas
|
||||||
list *PackageList
|
list *PackageList
|
||||||
p1, p2, p3, p4, p5, p6 *Package
|
p1, p2, p3, p4, p5, p6 *Package
|
||||||
|
|
||||||
|
// Mocked packages in list
|
||||||
|
packages []*Package
|
||||||
|
il *PackageList
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = Suite(&PackageListSuite{})
|
var _ = Suite(&PackageListSuite{})
|
||||||
@@ -31,6 +36,27 @@ func (s *PackageListSuite) SetUpTest(c *C) {
|
|||||||
stanza = packageStanza.Copy()
|
stanza = packageStanza.Copy()
|
||||||
stanza["Version"] = "99.1"
|
stanza["Version"] = "99.1"
|
||||||
s.p6 = NewPackageFromControlFile(stanza)
|
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) {
|
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.*")
|
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) {
|
func (s *PackageListSuite) TestForeach(c *C) {
|
||||||
s.list.Add(s.p1)
|
s.list.Add(s.p1)
|
||||||
s.list.Add(s.p3)
|
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) {
|
func (s *PackageListSuite) TestNewPackageListFromRefList(c *C) {
|
||||||
db, _ := database.OpenDB(c.MkDir())
|
db, _ := database.OpenDB(c.MkDir())
|
||||||
coll := NewPackageCollection(db)
|
coll := NewPackageCollection(db)
|
||||||
@@ -146,98 +322,3 @@ func (s *PackageListSuite) TestPackageRefListForeach(c *C) {
|
|||||||
|
|
||||||
c.Check(err, Equals, e)
|
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"})
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user