mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-07-27 13:57:46 +00:00
Snapshot difference algorithm.
This commit is contained in:
Vendored
+97
@@ -376,3 +376,100 @@ func (l *PackageRefList) ForEach(handler func([]byte) error) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PackageDiff is a difference between two packages in a list.
|
||||||
|
//
|
||||||
|
// If left & right are present, difference is in package version
|
||||||
|
// If left is nil, package is present only in right
|
||||||
|
// If right is nil, package is present only in left
|
||||||
|
type PackageDiff struct {
|
||||||
|
Left, Right *Package
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackageDiffs is a list of PackageDiff records
|
||||||
|
type PackageDiffs []PackageDiff
|
||||||
|
|
||||||
|
// Diff calculates difference between two reflists
|
||||||
|
func (l *PackageRefList) Diff(r *PackageRefList, packageCollection *PackageCollection) (result PackageDiffs, err error) {
|
||||||
|
result = make(PackageDiffs, 0, 128)
|
||||||
|
|
||||||
|
// pointer to left and right reflists
|
||||||
|
il, ir := 0, 0
|
||||||
|
// length of reflists
|
||||||
|
ll, lr := l.Len(), r.Len()
|
||||||
|
// cached loaded packages on the left & right
|
||||||
|
pl, pr := (*Package)(nil), (*Package)(nil)
|
||||||
|
|
||||||
|
// until we reached end of both lists
|
||||||
|
for il < ll || ir < lr {
|
||||||
|
// if we've exhausted left list, pull the rest from the right
|
||||||
|
if il == ll {
|
||||||
|
pr, err = packageCollection.ByKey(r.Refs[ir])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, PackageDiff{Left: nil, Right: pr})
|
||||||
|
ir++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// if we've exhausted right list, pull the rest from the left
|
||||||
|
if ir == lr {
|
||||||
|
pl, err = packageCollection.ByKey(l.Refs[il])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, PackageDiff{Left: pl, Right: nil})
|
||||||
|
il++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// refs on both sides are present, load them
|
||||||
|
rl, rr := l.Refs[il], r.Refs[ir]
|
||||||
|
// compare refs
|
||||||
|
rel := bytes.Compare(rl, rr)
|
||||||
|
|
||||||
|
if rel == 0 {
|
||||||
|
// refs are identical, so are packages, advance pointer
|
||||||
|
il++
|
||||||
|
ir++
|
||||||
|
pl, pr = nil, nil
|
||||||
|
} else {
|
||||||
|
// load pl & pr if they haven't been loaded before
|
||||||
|
if pl == nil {
|
||||||
|
pl, err = packageCollection.ByKey(rl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pr == nil {
|
||||||
|
pr, err = packageCollection.ByKey(rr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// is pl & pr the same package, but different version?
|
||||||
|
if pl.Name == pr.Name && pl.Architecture == pr.Architecture {
|
||||||
|
result = append(result, PackageDiff{Left: pl, Right: pr})
|
||||||
|
il++
|
||||||
|
ir++
|
||||||
|
pl, pr = nil, nil
|
||||||
|
} else {
|
||||||
|
// otherwise pl or pr is missing on one of the sides
|
||||||
|
if rel < 0 {
|
||||||
|
result = append(result, PackageDiff{Left: pl, Right: nil})
|
||||||
|
il++
|
||||||
|
pl = nil
|
||||||
|
} else {
|
||||||
|
result = append(result, PackageDiff{Left: nil, Right: pr})
|
||||||
|
ir++
|
||||||
|
pr = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+72
@@ -322,3 +322,75 @@ func (s *PackageListSuite) TestPackageRefListForeach(c *C) {
|
|||||||
|
|
||||||
c.Check(err, Equals, e)
|
c.Check(err, Equals, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PackageListSuite) TestDiff(c *C) {
|
||||||
|
db, _ := database.OpenDB(c.MkDir())
|
||||||
|
coll := NewPackageCollection(db)
|
||||||
|
|
||||||
|
packages := []*Package{
|
||||||
|
&Package{Name: "lib", Version: "1.0", Architecture: "i386"}, //0
|
||||||
|
&Package{Name: "dpkg", Version: "1.7", Architecture: "i386"}, //1
|
||||||
|
&Package{Name: "data", Version: "1.1~bp1", Architecture: "all"}, //2
|
||||||
|
&Package{Name: "app", Version: "1.1~bp1", Architecture: "i386"}, //3
|
||||||
|
&Package{Name: "app", Version: "1.1~bp2", Architecture: "i386"}, //4
|
||||||
|
&Package{Name: "app", Version: "1.1~bp2", Architecture: "amd64"}, //5
|
||||||
|
&Package{Name: "xyz", Version: "3.0", Architecture: "sparc"}, //6
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range packages {
|
||||||
|
coll.Update(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
listA := NewPackageList()
|
||||||
|
listA.Add(packages[0])
|
||||||
|
listA.Add(packages[1])
|
||||||
|
listA.Add(packages[2])
|
||||||
|
listA.Add(packages[3])
|
||||||
|
listA.Add(packages[6])
|
||||||
|
|
||||||
|
listB := NewPackageList()
|
||||||
|
listB.Add(packages[0])
|
||||||
|
listB.Add(packages[2])
|
||||||
|
listB.Add(packages[4])
|
||||||
|
listB.Add(packages[5])
|
||||||
|
|
||||||
|
reflistA := NewPackageRefListFromPackageList(listA)
|
||||||
|
reflistB := NewPackageRefListFromPackageList(listB)
|
||||||
|
|
||||||
|
diffAA, err := reflistA.Diff(reflistA, coll)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(diffAA, HasLen, 0)
|
||||||
|
|
||||||
|
diffAB, err := reflistA.Diff(reflistB, coll)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
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[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].Right, IsNil)
|
||||||
|
|
||||||
|
c.Check(diffAB[3].Left.String(), Equals, "xyz-3.0_sparc")
|
||||||
|
c.Check(diffAB[3].Right, IsNil)
|
||||||
|
|
||||||
|
diffBA, err := reflistB.Diff(reflistA, coll)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
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[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].Left, IsNil)
|
||||||
|
|
||||||
|
c.Check(diffBA[3].Right.String(), Equals, "xyz-3.0_sparc")
|
||||||
|
c.Check(diffBA[3].Left, IsNil)
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user