Fix subtle bug in .Merge: if there are duplicate name-arch on the left, override them all. #42

This commit is contained in:
Andrey Smirnov
2014-04-24 00:57:17 +04:00
parent 37a6fb336a
commit 59647fe6d0
2 changed files with 21 additions and 4 deletions
+19 -2
View File
@@ -223,6 +223,8 @@ func (l *PackageRefList) Diff(r *PackageRefList, packageCollection *PackageColle
// replaces matching packages (by architecture/name) with reference from r. // replaces matching packages (by architecture/name) with reference from r.
// Otherwise, all packages are saved. // Otherwise, all packages are saved.
func (l *PackageRefList) Merge(r *PackageRefList, overrideMatching bool) (result *PackageRefList) { func (l *PackageRefList) Merge(r *PackageRefList, overrideMatching bool) (result *PackageRefList) {
var overriddenArch, overridenName []byte
// pointer to left and right reflists // pointer to left and right reflists
il, ir := 0, 0 il, ir := 0, 0
// length of reflists // length of reflists
@@ -254,6 +256,8 @@ func (l *PackageRefList) Merge(r *PackageRefList, overrideMatching bool) (result
result.Refs = append(result.Refs, l.Refs[il]) result.Refs = append(result.Refs, l.Refs[il])
il++ il++
ir++ ir++
overridenName = nil
overriddenArch = nil
} else { } else {
if overrideMatching { if overrideMatching {
partsL := bytes.Split(rl, []byte(" ")) partsL := bytes.Split(rl, []byte(" "))
@@ -262,11 +266,19 @@ func (l *PackageRefList) Merge(r *PackageRefList, overrideMatching bool) (result
partsR := bytes.Split(rr, []byte(" ")) partsR := bytes.Split(rr, []byte(" "))
archR, nameR := partsR[0][1:], partsR[1] archR, nameR := partsR[0][1:], partsR[1]
if bytes.Compare(archL, archR) == 0 && bytes.Compare(nameL, nameR) == 0 { if bytes.Equal(archL, overriddenArch) && bytes.Equal(nameL, overridenName) {
// this package has already been overriden on the right
il++
continue
}
if bytes.Equal(archL, archR) && bytes.Equal(nameL, nameR) {
// override with package from the right // override with package from the right
result.Refs = append(result.Refs, r.Refs[ir]) result.Refs = append(result.Refs, r.Refs[ir])
il++ il++
ir++ ir++
overriddenArch = archL
overridenName = nameL
continue continue
} }
} }
@@ -278,6 +290,8 @@ func (l *PackageRefList) Merge(r *PackageRefList, overrideMatching bool) (result
} else { } else {
result.Refs = append(result.Refs, r.Refs[ir]) result.Refs = append(result.Refs, r.Refs[ir])
ir++ ir++
overridenName = nil
overriddenArch = nil
} }
} }
} }
@@ -304,11 +318,14 @@ func FilterLatestRefs(r *PackageRefList) {
// Two packages are identical, check version and only one wins // Two packages are identical, check version and only one wins
vres := CompareVersions(string(ver), string(lastVer)) vres := CompareVersions(string(ver), string(lastVer))
// Remove the older or duplicate refs from the result // Remove the older refs from the result
if vres > 0 { if vres > 0 {
// ver[i] > ver[i-1], remove element i-1
r.Refs = append(r.Refs[:i-1], r.Refs[i:]...) r.Refs = append(r.Refs[:i-1], r.Refs[i:]...)
} else { } else {
// ver[i] < ver[i-1], remove element i
r.Refs = append(r.Refs[:i], r.Refs[i+1:]...) r.Refs = append(r.Refs[:i], r.Refs[i+1:]...)
arch, name, ver = lastArch, lastName, lastVer
} }
// Compensate for the reduced set // Compensate for the reduced set
+2 -2
View File
@@ -277,11 +277,11 @@ func (s *PackageRefListSuite) TestMerge(c *C) {
func (s *PackageRefListSuite) TestFilterLatestRefs(c *C) { func (s *PackageRefListSuite) TestFilterLatestRefs(c *C) {
packages := []*Package{ packages := []*Package{
&Package{Name: "lib", Version: "1.0", Architecture: "i386"}, &Package{Name: "lib", Version: "1.0", Architecture: "i386"},
&Package{Name: "lib", Version: "1.1", Architecture: "i386"}, &Package{Name: "lib", Version: "1.2~bp1", Architecture: "i386"},
&Package{Name: "lib", Version: "1.2", Architecture: "i386"}, &Package{Name: "lib", Version: "1.2", Architecture: "i386"},
&Package{Name: "dpkg", Version: "1.2", Architecture: "i386"}, &Package{Name: "dpkg", Version: "1.2", Architecture: "i386"},
&Package{Name: "dpkg", Version: "1.3", Architecture: "i386"}, &Package{Name: "dpkg", Version: "1.3", Architecture: "i386"},
&Package{Name: "dpkg", Version: "1.4", Architecture: "i386"}, &Package{Name: "dpkg", Version: "1.3~bp2", Architecture: "i386"},
&Package{Name: "dpkg", Version: "1.5", Architecture: "i386"}, &Package{Name: "dpkg", Version: "1.5", Architecture: "i386"},
&Package{Name: "dpkg", Version: "1.6", Architecture: "i386"}, &Package{Name: "dpkg", Version: "1.6", Architecture: "i386"},
} }