List filtering with dependency resolution.

This commit is contained in:
Andrey Smirnov
2014-02-27 15:54:17 +04:00
parent f430e78a2b
commit d6dec91c93
2 changed files with 97 additions and 9 deletions

67
debian/list.go vendored
View File

@@ -331,21 +331,36 @@ func (l *PackageList) Search(dep Dependency) *Package {
}
// Filter filters package index by specified queries (ORed together), possibly pulling dependencies
func (l *PackageList) Filter(queries []string, withDependencies bool, dependencyOptions int, architecturesList []string) (*PackageList, error) {
func (l *PackageList) Filter(queries []string, withDependencies bool, source *PackageList, dependencyOptions int, architecturesList []string) (*PackageList, error) {
if !l.indexed {
panic("list not indexed, can't filter")
}
result := NewPackageList()
for _, query := range queries {
isDepQuery := strings.IndexAny(query, " (){}=<>") != -1
if !isDepQuery {
// try to interpret query as package key
p := l.packages[query]
if p != nil {
result.Add(p)
continue
// try to interpret query as package string representation
// convert Package.String() to Package.Key()
i := strings.Index(query, "_")
if i != -1 {
pkg, query := query[:i], query[i+1:]
j := strings.LastIndex(query, "_")
if j != -1 {
version, arch := query[:j], query[j+1:]
p := l.packages["P"+arch+" "+pkg+" "+version]
if p != nil {
result.Add(p)
continue
}
}
}
}
// try as dependency
dep, err := ParseDependency(query)
if err != nil {
if isDepQuery {
@@ -355,12 +370,46 @@ func (l *PackageList) Filter(queries []string, withDependencies bool, dependency
continue
}
_ = dep
// -> Search
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 {
p := l.packagesIndex[i]
if p.MatchesDependency(dep) {
result.Add(p)
}
i++
}
}
// -> Verify dependencies
if withDependencies {
added := result.Len()
dependencySource := NewPackageList()
dependencySource.Append(source)
dependencySource.Append(result)
dependencySource.PrepareIndex()
// while some new dependencies were discovered
for added > 0 {
added = 0
// find missing dependencies
missing, err := result.VerifyDependencies(dependencyOptions, architecturesList, dependencySource)
if err != nil {
return nil, err
}
// try to satisfy dependencies
for _, dep := range missing {
p := l.Search(dep)
if p != nil {
result.Add(p)
dependencySource.Add(p)
added++
}
}
}
}
return result, nil
}

39
debian/list_test.go vendored
View File

@@ -5,6 +5,7 @@ import (
"github.com/smira/aptly/database"
. "launchpad.net/gocheck"
"sort"
"strings"
)
type PackageListSuite struct {
@@ -220,6 +221,44 @@ func (s *PackageListSuite) TestSearch(c *C) {
c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.2"}), IsNil)
}
func (s *PackageListSuite) TestFilter(c *C) {
c.Check(func() { s.list.Filter([]string{"abcd_0.3_i386"}, false, nil, 0, nil) }, Panics, "list not indexed, can't filter")
_, err := s.il.Filter([]string{"app >3)"}, false, nil, 0, nil)
c.Check(err, ErrorMatches, "unable to parse dependency.*")
plString := func(l *PackageList) string {
list := make([]string, 0, l.Len())
for _, p := range l.packages {
list = append(list, p.String())
}
sort.Strings(list)
return strings.Join(list, " ")
}
result, err := s.il.Filter([]string{"app_1.1~bp1_i386"}, false, nil, 0, nil)
c.Check(err, IsNil)
c.Check(plString(result), Equals, "app_1.1~bp1_i386")
result, err = s.il.Filter([]string{"app_1.1~bp1_i386", "dpkg_1.7_source", "dpkg_1.8_amd64"}, false, nil, 0, nil)
c.Check(err, IsNil)
c.Check(plString(result), Equals, "app_1.1~bp1_i386 dpkg_1.7_source")
result, err = s.il.Filter([]string{"app", "dpkg (>>1.6.1-3)", "app (>=1.0)", "xyz", "aa (>>3.0)"}, false, nil, 0, nil)
c.Check(err, IsNil)
c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 dpkg_1.7_i386 dpkg_1.7_source")
result, err = s.il.Filter([]string{"app {i386}"}, true, NewPackageList(), 0, []string{"i386"})
c.Check(err, IsNil)
c.Check(plString(result), Equals, "app_1.1~bp1_i386 data_1.1~bp1_all dpkg_1.7_i386 lib_1.0_i386 mailer_3.5.8_i386")
result, err = s.il.Filter([]string{"app (>=0.9)", "lib", "data"}, true, NewPackageList(), 0, []string{"i386", "amd64"})
c.Check(err, IsNil)
c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 data_1.1~bp1_all dpkg_1.6.1-3_amd64 dpkg_1.7_i386 lib_1.0_i386 mailer_3.5.8_i386")
}
func (s *PackageListSuite) TestVerifyDependencies(c *C) {
missing, err := s.il.VerifyDependencies(0, []string{"i386"}, s.il)
c.Check(err, IsNil)