mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-31 04:30:44 +00:00
Implementation of all-matches functionality + tests
When performing an *aptly snapshot pull*, users might list dependency versions that can potentially match multiple packages in the source snapshot. However, the current implementation of the 'snapshot pull' command only allows one package to be pulled from a snapshot at a time for a given dependency. The newly implemented all-matches flag allows users to pull all the matching packages from a source snapshot, provided that they satisfy the version requirements indicated by the dependencies. The all-matches flag defaults to false and only produces the described behaviour when it is explicitly set to true.
This commit is contained in:
+36
-25
@@ -18,6 +18,7 @@ func aptlySnapshotPull(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
noDeps := context.flags.Lookup("no-deps").Value.Get().(bool)
|
noDeps := context.flags.Lookup("no-deps").Value.Get().(bool)
|
||||||
noRemove := context.flags.Lookup("no-remove").Value.Get().(bool)
|
noRemove := context.flags.Lookup("no-remove").Value.Get().(bool)
|
||||||
|
allMatches := context.flags.Lookup("all-matches").Value.Get().(bool)
|
||||||
|
|
||||||
// Load <name> snapshot
|
// Load <name> snapshot
|
||||||
snapshot, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
|
snapshot, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
|
||||||
@@ -97,24 +98,30 @@ func aptlySnapshotPull(cmd *commander.Command, args []string) error {
|
|||||||
dep := dependencies[i]
|
dep := dependencies[i]
|
||||||
|
|
||||||
// Search for package that can satisfy dependencies
|
// Search for package that can satisfy dependencies
|
||||||
pkg := sourcePackageList.Search(dep)
|
searchResults := sourcePackageList.Search(dep, allMatches)
|
||||||
if pkg == nil {
|
if searchResults == nil {
|
||||||
context.Progress().ColoredPrintf("@y[!]@| @!Dependency %s can't be satisfied with source %s@|", &dep, source)
|
context.Progress().ColoredPrintf("@y[!]@| @!Dependency %s can't be satisfied with source %s@|", &dep, source)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !noRemove {
|
if !noRemove {
|
||||||
// Remove all packages with the same name and architecture
|
// Remove all packages with the same name and architecture
|
||||||
for p := packageList.Search(deb.Dependency{Architecture: pkg.Architecture, Pkg: pkg.Name}); p != nil; {
|
for _, pkg := range searchResults {
|
||||||
packageList.Remove(p)
|
for pS := packageList.Search(deb.Dependency{Architecture: pkg.Architecture, Pkg: pkg.Name}, allMatches); pS != nil; {
|
||||||
context.Progress().ColoredPrintf("@r[-]@| %s removed", p)
|
for _, p := range pS {
|
||||||
p = packageList.Search(deb.Dependency{Architecture: pkg.Architecture, Pkg: pkg.Name})
|
packageList.Remove(p)
|
||||||
|
context.Progress().ColoredPrintf("@r[-]@| %s removed", p)
|
||||||
|
}
|
||||||
|
pS = packageList.Search(deb.Dependency{Architecture: pkg.Architecture, Pkg: pkg.Name}, allMatches)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new discovered package
|
// Add new discovered package
|
||||||
packageList.Add(pkg)
|
for _, pkg := range searchResults {
|
||||||
context.Progress().ColoredPrintf("@g[+]@| %s added", pkg)
|
packageList.Add(pkg)
|
||||||
|
context.Progress().ColoredPrintf("@g[+]@| %s added", pkg)
|
||||||
|
}
|
||||||
|
|
||||||
if noDeps {
|
if noDeps {
|
||||||
continue
|
continue
|
||||||
@@ -122,26 +129,28 @@ func aptlySnapshotPull(cmd *commander.Command, args []string) error {
|
|||||||
|
|
||||||
// Find missing dependencies for single added package
|
// Find missing dependencies for single added package
|
||||||
pL := deb.NewPackageList()
|
pL := deb.NewPackageList()
|
||||||
pL.Add(pkg)
|
for _, pkg := range searchResults {
|
||||||
|
pL.Add(pkg)
|
||||||
|
|
||||||
var missing []deb.Dependency
|
var missing []deb.Dependency
|
||||||
missing, err = pL.VerifyDependencies(context.DependencyOptions(), []string{arch}, packageList, nil)
|
missing, err = pL.VerifyDependencies(context.DependencyOptions(), []string{arch}, packageList, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
context.Progress().ColoredPrintf("@y[!]@| @!Error while verifying dependencies for pkg %s: %s@|", pkg, err)
|
context.Progress().ColoredPrintf("@y[!]@| @!Error while verifying dependencies for pkg %s: %s@|", pkg, err)
|
||||||
}
|
|
||||||
|
|
||||||
// Append missing dependencies to the list of dependencies to satisfy
|
|
||||||
for _, misDep := range missing {
|
|
||||||
found := false
|
|
||||||
for _, d := range dependencies {
|
|
||||||
if d == misDep {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
// Append missing dependencies to the list of dependencies to satisfy
|
||||||
dependencies = append(dependencies, misDep)
|
for _, misDep := range missing {
|
||||||
|
found := false
|
||||||
|
for _, d := range dependencies {
|
||||||
|
if d == misDep {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
dependencies = append(dependencies, misDep)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,6 +195,8 @@ Example:
|
|||||||
cmd.Flag.Bool("dry-run", false, "don't create destination snapshot, just show what would be pulled")
|
cmd.Flag.Bool("dry-run", false, "don't create destination snapshot, just show what would be pulled")
|
||||||
cmd.Flag.Bool("no-deps", false, "don't process dependencies, just pull listed packages")
|
cmd.Flag.Bool("no-deps", false, "don't process dependencies, just pull listed packages")
|
||||||
cmd.Flag.Bool("no-remove", false, "don't remove other package versions when pulling package")
|
cmd.Flag.Bool("no-remove", false, "don't remove other package versions when pulling package")
|
||||||
|
cmd.Flag.Bool("all-matches", false, "pull all the packages that satisfy the dependency version requirements")
|
||||||
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-11
@@ -263,7 +263,7 @@ func (l *PackageList) VerifyDependencies(options int, architectures []string, so
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if sources.Search(dep) == nil {
|
if sources.Search(dep, false) == nil {
|
||||||
variantsMissing = append(variantsMissing, dep)
|
variantsMissing = append(variantsMissing, dep)
|
||||||
missingCount++
|
missingCount++
|
||||||
} else {
|
} else {
|
||||||
@@ -326,29 +326,47 @@ func (l *PackageList) PrepareIndex() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search searches package index for specified package
|
// Search searches package index for specified package
|
||||||
func (l *PackageList) Search(dep Dependency) *Package {
|
func (l *PackageList) Search(dep Dependency, allMatches bool) []*Package {
|
||||||
if !l.indexed {
|
if !l.indexed {
|
||||||
panic("list not indexed, can't search")
|
panic("list not indexed, can't search")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
searchResults := []*Package{}
|
||||||
|
|
||||||
if dep.Relation == VersionDontCare {
|
if dep.Relation == VersionDontCare {
|
||||||
for _, p := range l.providesIndex[dep.Pkg] {
|
for _, p := range l.providesIndex[dep.Pkg] {
|
||||||
if p.MatchesArchitecture(dep.Architecture) {
|
if p.MatchesArchitecture(dep.Architecture) {
|
||||||
return p
|
searchResults = append(searchResults, p)
|
||||||
|
|
||||||
|
if !allMatches {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(searchResults) != 0 {
|
||||||
|
return searchResults
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[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.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
|
for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
|
||||||
p := l.packagesIndex[i]
|
p := l.packagesIndex[i]
|
||||||
if p.MatchesDependency(dep) {
|
if p.MatchesDependency(dep, allMatches) {
|
||||||
return p
|
searchResults = append(searchResults, p)
|
||||||
|
|
||||||
|
if !allMatches {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(searchResults) != 0 {
|
||||||
|
return searchResults
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,7 +414,7 @@ func (l *PackageList) Filter(queries []string, withDependencies bool, source *Pa
|
|||||||
|
|
||||||
for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
|
for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
|
||||||
p := l.packagesIndex[i]
|
p := l.packagesIndex[i]
|
||||||
if p.MatchesDependency(dep) {
|
if p.MatchesDependency(dep, false) {
|
||||||
result.Add(p)
|
result.Add(p)
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
@@ -423,11 +441,13 @@ func (l *PackageList) Filter(queries []string, withDependencies bool, source *Pa
|
|||||||
|
|
||||||
// try to satisfy dependencies
|
// try to satisfy dependencies
|
||||||
for _, dep := range missing {
|
for _, dep := range missing {
|
||||||
p := l.Search(dep)
|
searchResults := l.Search(dep, false)
|
||||||
if p != nil {
|
if searchResults != nil {
|
||||||
result.Add(p)
|
for _, p := range searchResults {
|
||||||
dependencySource.Add(p)
|
result.Add(p)
|
||||||
added++
|
dependencySource.Add(p)
|
||||||
|
added++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+95
-16
@@ -7,6 +7,43 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type containsChecker struct {
|
||||||
|
*CheckerInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *containsChecker) Check(params []interface{}, names []string) (result bool, error string) {
|
||||||
|
var (
|
||||||
|
pkgSlice1 []*Package
|
||||||
|
pkgSlice2 []*Package
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
pkgMap := make (map[*Package]bool)
|
||||||
|
|
||||||
|
|
||||||
|
pkgSlice1, ok = params[0].([]*Package)
|
||||||
|
if !ok {
|
||||||
|
return false, "The first parameter is not a Package slice"
|
||||||
|
}
|
||||||
|
pkgSlice2, ok = params[1].([]*Package)
|
||||||
|
if !ok {
|
||||||
|
return false, "The second parameter is not a Package slice"
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range pkgSlice2 {
|
||||||
|
pkgMap[pkg] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range pkgSlice1 {
|
||||||
|
if _, ok := pkgMap[pkg]; !ok {
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var Contains Checker = &containsChecker{&CheckerInfo{Name: "Contains", Params: []string{"Container", "Expected to contain"}}}
|
||||||
|
|
||||||
type PackageListSuite struct {
|
type PackageListSuite struct {
|
||||||
// Simple list with "real" packages from stanzas
|
// Simple list with "real" packages from stanzas
|
||||||
list *PackageList
|
list *PackageList
|
||||||
@@ -14,8 +51,10 @@ type PackageListSuite struct {
|
|||||||
|
|
||||||
// Mocked packages in list
|
// Mocked packages in list
|
||||||
packages []*Package
|
packages []*Package
|
||||||
|
packages2 []*Package
|
||||||
sourcePackages []*Package
|
sourcePackages []*Package
|
||||||
il *PackageList
|
il *PackageList
|
||||||
|
il2 *PackageList
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = Suite(&PackageListSuite{})
|
var _ = Suite(&PackageListSuite{})
|
||||||
@@ -60,6 +99,20 @@ func (s *PackageListSuite) SetUpTest(c *C) {
|
|||||||
}
|
}
|
||||||
s.il.PrepareIndex()
|
s.il.PrepareIndex()
|
||||||
|
|
||||||
|
s.il2 = NewPackageList()
|
||||||
|
s.packages2 = []*Package{
|
||||||
|
&Package{Name: "mailer", Version: "3.5.8", Architecture: "amd64", Source: "postfix (1.3)", Provides: []string{"mail-agent"}, deps: &PackageDependencies{}},
|
||||||
|
&Package{Name: "sendmail", Version: "1.0", Architecture: "amd64", Source: "postfix (1.3)", Provides: []string{"mail-agent"}, deps: &PackageDependencies{}},
|
||||||
|
&Package{Name: "app", Version: "1.1-bp1", Architecture: "amd64", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}},
|
||||||
|
&Package{Name: "app", Version: "1.1-bp2", Architecture: "amd64", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}},
|
||||||
|
&Package{Name: "app", Version: "1.2", Architecture: "amd64", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9) | libx (>= 1.5)", "data (>= 1.0) | mail-agent"}}},
|
||||||
|
&Package{Name: "app", Version: "3.0", Architecture: "amd64", deps: &PackageDependencies{PreDepends: []string{"dpkg >= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}},
|
||||||
|
}
|
||||||
|
for _, p := range s.packages2 {
|
||||||
|
s.il2.Add(p)
|
||||||
|
}
|
||||||
|
s.il2.PrepareIndex()
|
||||||
|
|
||||||
s.sourcePackages = []*Package{
|
s.sourcePackages = []*Package{
|
||||||
&Package{Name: "postfix", Version: "1.3", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
|
&Package{Name: "postfix", Version: "1.3", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
|
||||||
&Package{Name: "app", Version: "1.1~bp1", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
|
&Package{Name: "app", Version: "1.1~bp1", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
|
||||||
@@ -196,28 +249,54 @@ func (s *PackageListSuite) TestAppend(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *PackageListSuite) TestSearch(c *C) {
|
func (s *PackageListSuite) TestSearch(c *C) {
|
||||||
c.Check(func() { s.list.Search(Dependency{Architecture: "i386", Pkg: "app"}) }, Panics, "list not indexed, can't search")
|
//allMatches = False
|
||||||
|
c.Check(func() { s.list.Search(Dependency{Architecture: "i386", Pkg: "app"}, false) }, 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: "app"}, false), DeepEquals, []*Package{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: "mail-agent"}, false), DeepEquals, []*Package{s.packages[4]})
|
||||||
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "puppy"}), IsNil)
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "puppy"}, false), 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~bp1"}, false), DeepEquals, []*Package{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: VersionEqual, Version: "1.1~bp2"}, false), 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"}, false), DeepEquals, []*Package{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: VersionLess, Version: "1.1~~"}, false), 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"}, false), DeepEquals, []*Package{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~bp1"}, false), DeepEquals, []*Package{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: VersionLessOrEqual, Version: "1.1~~"}, false), 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.0"}, false), DeepEquals, []*Package{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: VersionGreater, Version: "1.2"}, false), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.0"}, false), DeepEquals, []*Package{s.packages[3]})
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.1~bp1"}, false), DeepEquals, []*Package{s.packages[3]})
|
||||||
|
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.2"}, false), IsNil)
|
||||||
|
|
||||||
|
// allMatches = True
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app"}, true), Contains, []*Package{s.packages2[2], s.packages2[3], s.packages2[4], s.packages2[5]})
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "mail-agent"}, true), Contains, []*Package{s.packages2[0], s.packages2[1]})
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "puppy"}, true), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionEqual, Version: "1.1"}, true), Contains, []*Package{s.packages2[2], s.packages2[3]})
|
||||||
|
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionEqual, Version: "1.1"}, true), Contains, []*Package{s.packages2[2], s.packages2[3]})
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionEqual, Version: "3"}, true), Contains, []*Package{s.packages2[5]})
|
||||||
|
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLess, Version: "1.2"}, true), Contains, []*Package{s.packages2[2], s.packages2[3]})
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLess, Version: "1.1~"}, true), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.2"}, true), Contains, []*Package{s.packages2[2], s.packages2[3], s.packages2[4]})
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1-bp1"}, true), Contains, []*Package{s.packages2[2]})
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.0"}, true), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreater, Version: "1.1"}, true), Contains, []*Package{s.packages2[2], s.packages2[3], s.packages2[4], s.packages2[5]})
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreater, Version: "5.0"}, true), IsNil)
|
||||||
|
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.2"}, true), Contains, []*Package{s.packages2[4], s.packages2[5]})
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.1~bp1"}, true), Contains, []*Package{s.packages2[2], s.packages2[3], s.packages2[4], s.packages2[5]})
|
||||||
|
c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "5.0"}, true), 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) TestFilter(c *C) {
|
func (s *PackageListSuite) TestFilter(c *C) {
|
||||||
|
|||||||
+8
-2
@@ -198,7 +198,7 @@ func (p *Package) MatchesArchitecture(arch string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MatchesDependency checks whether package matches specified dependency
|
// MatchesDependency checks whether package matches specified dependency
|
||||||
func (p *Package) MatchesDependency(dep Dependency) bool {
|
func (p *Package) MatchesDependency(dep Dependency, allMatches bool) bool {
|
||||||
if dep.Pkg != p.Name {
|
if dep.Pkg != p.Name {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -212,9 +212,15 @@ func (p *Package) MatchesDependency(dep Dependency) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r := CompareVersions(p.Version, dep.Version)
|
r := CompareVersions(p.Version, dep.Version)
|
||||||
|
|
||||||
switch dep.Relation {
|
switch dep.Relation {
|
||||||
case VersionEqual:
|
case VersionEqual:
|
||||||
return r == 0
|
if allMatches {
|
||||||
|
rn := CompareVersions(p.Version, dep.NextVersion())
|
||||||
|
return r+rn == 0 || r == 0
|
||||||
|
} else {
|
||||||
|
return r == 0
|
||||||
|
}
|
||||||
case VersionLess:
|
case VersionLess:
|
||||||
return r < 0
|
return r < 0
|
||||||
case VersionGreater:
|
case VersionGreater:
|
||||||
|
|||||||
+20
-14
@@ -172,38 +172,44 @@ func (s *PackageSuite) TestMatchesDependency(c *C) {
|
|||||||
p := NewPackageFromControlFile(s.stanza)
|
p := NewPackageFromControlFile(s.stanza)
|
||||||
|
|
||||||
// exact match
|
// exact match
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionEqual, Version: "7.40-2"}), Equals, true)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionEqual, Version: "7.40-2"}, false), Equals, true)
|
||||||
|
|
||||||
|
// exact match, same version, no revision specified
|
||||||
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionEqual, Version: "7.40"}, false), Equals, false)
|
||||||
|
|
||||||
|
// non-exact match, same version, no revision specified
|
||||||
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionEqual, Version: "7.40"}, true), Equals, true)
|
||||||
|
|
||||||
// different name
|
// different name
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena", Architecture: "i386", Relation: VersionEqual, Version: "7.40-2"}), Equals, false)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena", Architecture: "i386", Relation: VersionEqual, Version: "7.40-2"}, false), Equals, false)
|
||||||
|
|
||||||
// different version
|
// different version
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionEqual, Version: "7.40-3"}), Equals, false)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionEqual, Version: "7.40-3"}, false), Equals, false)
|
||||||
|
|
||||||
// different arch
|
// different arch
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "amd64", Relation: VersionEqual, Version: "7.40-2"}), Equals, false)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "amd64", Relation: VersionEqual, Version: "7.40-2"}, false), Equals, false)
|
||||||
|
|
||||||
// empty arch
|
// empty arch
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "", Relation: VersionEqual, Version: "7.40-2"}), Equals, true)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "", Relation: VersionEqual, Version: "7.40-2"}, false), Equals, true)
|
||||||
|
|
||||||
// version don't care
|
// version don't care
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionDontCare, Version: ""}), Equals, true)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionDontCare, Version: ""}, false), Equals, true)
|
||||||
|
|
||||||
// >
|
// >
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionGreater, Version: "7.40-2"}), Equals, false)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionGreater, Version: "7.40-2"}, false), Equals, false)
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionGreater, Version: "7.40-1"}), Equals, true)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionGreater, Version: "7.40-1"}, false), Equals, true)
|
||||||
|
|
||||||
// <
|
// <
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionLess, Version: "7.40-2"}), Equals, false)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionLess, Version: "7.40-2"}, false), Equals, false)
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionLess, Version: "7.40-3"}), Equals, true)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionLess, Version: "7.40-3"}, false), Equals, true)
|
||||||
|
|
||||||
// >=
|
// >=
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionGreaterOrEqual, Version: "7.40-2"}), Equals, true)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionGreaterOrEqual, Version: "7.40-2"}, false), Equals, true)
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionGreaterOrEqual, Version: "7.40-3"}), Equals, false)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionGreaterOrEqual, Version: "7.40-3"}, false), Equals, false)
|
||||||
|
|
||||||
// <=
|
// <=
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionLessOrEqual, Version: "7.40-2"}), Equals, true)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionLessOrEqual, Version: "7.40-2"}, false), Equals, true)
|
||||||
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionLessOrEqual, Version: "7.40-1"}), Equals, false)
|
c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionLessOrEqual, Version: "7.40-1"}, false), Equals, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PackageSuite) TestGetDependencies(c *C) {
|
func (s *PackageSuite) TestGetDependencies(c *C) {
|
||||||
|
|||||||
@@ -188,6 +188,29 @@ type Dependency struct {
|
|||||||
Architecture string
|
Architecture string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NextVersion returns the next version of a dependency (eg. if d.Version = 1.9, it returns 1.10)
|
||||||
|
func (d *Dependency) NextVersion() string {
|
||||||
|
l := len(d.Version)
|
||||||
|
|
||||||
|
if l == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
i := l
|
||||||
|
for i > 0 {
|
||||||
|
_, err := strconv.ParseUint(d.Version[i-1:l],10,0)
|
||||||
|
if err != nil { break }
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := strconv.ParseUint(d.Version[i:l],10,0)
|
||||||
|
if err != nil {
|
||||||
|
return d.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.Version[0:i] + strconv.Itoa(int(v)+1)
|
||||||
|
}
|
||||||
|
|
||||||
// Hash calculates some predefined unique ID of Dependency
|
// Hash calculates some predefined unique ID of Dependency
|
||||||
func (d *Dependency) Hash() string {
|
func (d *Dependency) Hash() string {
|
||||||
return fmt.Sprintf("%s:%s:%d:%s", d.Architecture, d.Pkg, d.Relation, d.Version)
|
return fmt.Sprintf("%s:%s:%d:%s", d.Architecture, d.Pkg, d.Relation, d.Version)
|
||||||
|
|||||||
@@ -217,3 +217,45 @@ func (s *VersionSuite) TestDependencyString(c *C) {
|
|||||||
d.Architecture = "i386"
|
d.Architecture = "i386"
|
||||||
c.Check(d.String(), Equals, "dpkg [i386]")
|
c.Check(d.String(), Equals, "dpkg [i386]")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *VersionSuite) TestDependencyNextVersion(c *C){
|
||||||
|
d, _ := ParseDependency("dpkg(=1.7)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "1.8")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg(=1.9)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "1.10")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg(=9)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "10")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg(=9.909)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "9.910")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg(=9.0.9)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "9.0.10")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg(=9.0.100)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "9.0.101")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg(=9.0.0-209)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "9.0.0-210")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg(=9.0.0-209rel)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "9.0.0-209rel")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg(=9.0.0-rel219)")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "9.0.0-rel220")
|
||||||
|
|
||||||
|
d, _ = ParseDependency("dpkg")
|
||||||
|
d.Architecture = "i386"
|
||||||
|
c.Check(d.NextVersion(), Equals, "")
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user