diff --git a/debian/list.go b/debian/list.go index 9ee0b66d..24916bf8 100644 --- a/debian/list.go +++ b/debian/list.go @@ -6,6 +6,7 @@ import ( "github.com/smira/aptly/utils" "github.com/ugorji/go/codec" "sort" + "strings" ) // Dependency options @@ -320,40 +321,50 @@ func (l *PackageList) Search(dep Dependency) *Package { 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 - } - - r := CompareVersions(p.Version, dep.Version) - switch dep.Relation { - case VersionEqual: - if r == 0 { - return p - } - case VersionLess: - if r < 0 { - return p - } - case VersionGreater: - if r > 0 { - return p - } - case VersionLessOrEqual: - if r <= 0 { - return p - } - case VersionGreaterOrEqual: - if r >= 0 { - return p - } - } + if p.MatchesDependency(dep) { + return p } + i++ } return nil } +// 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) { + 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 + } + } + + dep, err := ParseDependency(query) + if err != nil { + if isDepQuery { + return nil, err + } + // parsing failed, but probably that wasn't a dep query + continue + } + + _ = dep + // -> Search + + } + + // -> Verify dependencies + + return result, nil +} + // PackageRefList is a list of keys of packages, this is basis for snapshot // and similar stuff // diff --git a/debian/list_test.go b/debian/list_test.go index 21cb6ec0..8444c713 100644 --- a/debian/list_test.go +++ b/debian/list_test.go @@ -251,7 +251,7 @@ func (s *PackageListSuite) TestVerifyDependencies(c *C) { c.Check(missing, DeepEquals, []Dependency{Dependency{Pkg: "libx", Relation: VersionEqual, Version: "1.5", Architecture: "source"}}) _, err = s.il.VerifyDependencies(0, []string{"i386", "amd64", "s390"}, s.il) - c.Check(err, ErrorMatches, "unable to process package app-1.0_s390:.*") + c.Check(err, ErrorMatches, "unable to process package app_1.0_s390:.*") } func (s *PackageListSuite) TestArchitectures(c *C) { @@ -416,15 +416,15 @@ func (s *PackageListSuite) TestDiff(c *C) { c.Check(diffAB, HasLen, 4) c.Check(diffAB[0].Left, IsNil) - c.Check(diffAB[0].Right.String(), Equals, "app-1.1~bp2_amd64") + c.Check(diffAB[0].Right.String(), Equals, "app_1.1~bp2_amd64") - c.Check(diffAB[1].Left.String(), Equals, "app-1.1~bp1_i386") - c.Check(diffAB[1].Right.String(), Equals, "app-1.1~bp2_i386") + c.Check(diffAB[1].Left.String(), Equals, "app_1.1~bp1_i386") + c.Check(diffAB[1].Right.String(), Equals, "app_1.1~bp2_i386") - c.Check(diffAB[2].Left.String(), Equals, "dpkg-1.7_i386") + c.Check(diffAB[2].Left.String(), Equals, "dpkg_1.7_i386") c.Check(diffAB[2].Right, IsNil) - c.Check(diffAB[3].Left.String(), Equals, "xyz-3.0_sparc") + c.Check(diffAB[3].Left.String(), Equals, "xyz_3.0_sparc") c.Check(diffAB[3].Right, IsNil) diffBA, err := reflistB.Diff(reflistA, coll) @@ -432,15 +432,15 @@ func (s *PackageListSuite) TestDiff(c *C) { c.Check(diffBA, HasLen, 4) c.Check(diffBA[0].Right, IsNil) - c.Check(diffBA[0].Left.String(), Equals, "app-1.1~bp2_amd64") + c.Check(diffBA[0].Left.String(), Equals, "app_1.1~bp2_amd64") - c.Check(diffBA[1].Right.String(), Equals, "app-1.1~bp1_i386") - c.Check(diffBA[1].Left.String(), Equals, "app-1.1~bp2_i386") + c.Check(diffBA[1].Right.String(), Equals, "app_1.1~bp1_i386") + c.Check(diffBA[1].Left.String(), Equals, "app_1.1~bp2_i386") - c.Check(diffBA[2].Right.String(), Equals, "dpkg-1.7_i386") + c.Check(diffBA[2].Right.String(), Equals, "dpkg_1.7_i386") c.Check(diffBA[2].Left, IsNil) - c.Check(diffBA[3].Right.String(), Equals, "xyz-3.0_sparc") + c.Check(diffBA[3].Right.String(), Equals, "xyz_3.0_sparc") c.Check(diffBA[3].Left, IsNil) } diff --git a/debian/package.go b/debian/package.go index 41742a0e..73b2643e 100644 --- a/debian/package.go +++ b/debian/package.go @@ -246,7 +246,7 @@ func (p *Package) Decode(input []byte) error { // String creates readable representation func (p *Package) String() string { - return fmt.Sprintf("%s-%s_%s", p.Name, p.Version, p.Architecture) + return fmt.Sprintf("%s_%s_%s", p.Name, p.Version, p.Architecture) } // MatchesArchitecture checks whether packages matches specified architecture @@ -258,6 +258,37 @@ func (p *Package) MatchesArchitecture(arch string) bool { return p.Architecture == arch } +// MatchesDependency checks whether package matches specified dependency +func (p *Package) MatchesDependency(dep Dependency) bool { + if dep.Pkg != p.Name { + return false + } + + if dep.Architecture != "" && !p.MatchesArchitecture(dep.Architecture) { + return false + } + + if dep.Relation == VersionDontCare { + return true + } + + r := CompareVersions(p.Version, dep.Version) + switch dep.Relation { + case VersionEqual: + return r == 0 + case VersionLess: + return r < 0 + case VersionGreater: + return r > 0 + case VersionLessOrEqual: + return r <= 0 + case VersionGreaterOrEqual: + return r >= 0 + } + + panic("unknown relation") +} + // GetDependencies compiles list of dependenices by flags from options func (p *Package) GetDependencies(options int) (dependencies []string) { dependencies = make([]string, 0, 30) diff --git a/debian/package_test.go b/debian/package_test.go index 1606489d..e2474d17 100644 --- a/debian/package_test.go +++ b/debian/package_test.go @@ -162,7 +162,7 @@ func (s *PackageSuite) TestStanza(c *C) { func (s *PackageSuite) TestString(c *C) { p := NewPackageFromControlFile(s.stanza) - c.Assert(p.String(), Equals, "alien-arena-common-7.40-2_i386") + c.Assert(p.String(), Equals, "alien-arena-common_7.40-2_i386") } func (s *PackageSuite) TestEquals(c *C) { @@ -211,6 +211,44 @@ func (s *PackageSuite) TestMatchesArchitecture(c *C) { c.Check(p.MatchesArchitecture("amd64"), Equals, false) } +func (s *PackageSuite) TestMatchesDependency(c *C) { + p := NewPackageFromControlFile(s.stanza) + + // exact match + c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionEqual, Version: "7.40-2"}), Equals, true) + + // different name + c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena", Architecture: "i386", Relation: VersionEqual, Version: "7.40-2"}), Equals, false) + + // different version + c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionEqual, Version: "7.40-3"}), Equals, false) + + // different arch + c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "amd64", Relation: VersionEqual, Version: "7.40-2"}), Equals, false) + + // empty arch + c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "", Relation: VersionEqual, Version: "7.40-2"}), Equals, true) + + // 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: VersionGreater, Version: "7.40-2"}), 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: VersionLess, Version: "7.40-2"}), 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: VersionGreaterOrEqual, Version: "7.40-2"}), 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: VersionLessOrEqual, Version: "7.40-2"}), Equals, true) + c.Check(p.MatchesDependency(Dependency{Pkg: "alien-arena-common", Architecture: "i386", Relation: VersionLessOrEqual, Version: "7.40-1"}), Equals, false) +} + func (s *PackageSuite) TestGetDependencies(c *C) { p := NewPackageFromControlFile(s.stanza) c.Check(p.GetDependencies(0), DeepEquals, []string{"libc6 (>= 2.7)", "alien-arena-data (>= 7.40)", "dpkg (>= 1.6)"})