Stabilize ordering graph

In this way when we order, we always return the same solution order in
case there are weak deps.

The following is optional - it doesn't change the "correctness" of the
solver results: We add an extra edge between deps that
share common dependendencies. This makes the link more stronger and
balances the graph so it doesn't show different results for the same query, as they
could be shuffled as don't have a direct connection.
This commit is contained in:
Ettore Di Giacinto
2020-11-02 14:30:41 +01:00
parent c3ef549673
commit 940f553e1c
2 changed files with 43 additions and 2 deletions

View File

@@ -163,7 +163,7 @@ func (assertions PackagesAssertions) Order(definitiondb pkg.PackageDatabase, fin
// Build a topological graph
for _, a := range unorderedAssertions {
currentPkg := a.Package
added := map[string]interface{}{}
added := map[string][]*pkg.DefaultPackage{}
REQUIRES:
for _, requiredDef := range currentPkg.GetRequires() {
if def, err := definitiondb.FindPackage(requiredDef); err == nil { // Provides: Get a chance of being override here
@@ -181,7 +181,16 @@ func (assertions PackagesAssertions) Order(definitiondb pkg.PackageDatabase, fin
}
// Expand also here, as we need to order them (or instead the solver should give back the dep correctly?)
graph.AddEdge(currentPkg.GetFingerPrint(), requiredDef.GetFingerPrint())
added[requiredDef.GetFingerPrint()] = nil
// The following is optional - it doesn't change the "correctness" of the solver results
// Here we add an extra edge between deps that share common dependendencies.
// This makes the link more stronger and balances the graph so it doesn't show
// different results for the same query, as they could be shuffled as don't have a direct connection.
for _, d := range added[currentPkg.GetFingerPrint()] {
graph.AddEdge(d.GetFingerPrint(), requiredDef.GetFingerPrint())
}
added[currentPkg.GetFingerPrint()] = append(added[currentPkg.GetFingerPrint()], requiredDef)
}
}
result, err := graph.TopSort(fingerprint)

View File

@@ -388,5 +388,37 @@ var _ = Describe("Decoder", func() {
Expect(solution4.Drop(Y).AssertionHash()).To(Equal(solution4.HashFrom(Y)))
})
for index := 0; index < 300; index++ { // Just to make sure we don't have false positives
It("Always same solution", func() {
X := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
Y := pkg.NewPackage("Y", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{})
Z := pkg.NewPackage("Z", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{})
W := pkg.NewPackage("W", "", []*pkg.DefaultPackage{Z, Y}, []*pkg.DefaultPackage{})
for _, p := range []pkg.Package{X, Y, Z} {
_, err := dbDefinitions.CreatePackage(p)
Expect(err).ToNot(HaveOccurred())
}
for _, p := range []pkg.Package{} {
_, err := dbInstalled.CreatePackage(p)
Expect(err).ToNot(HaveOccurred())
}
solution, err := s.Install([]pkg.Package{W})
Expect(err).ToNot(HaveOccurred())
orderW, err := solution.Order(dbDefinitions, W.GetFingerPrint())
Expect(err).ToNot(HaveOccurred())
Expect(orderW[0].Package.GetName()).To(Equal("X"))
Expect(orderW[1].Package.GetName()).To(Equal("Y"))
Expect(orderW[2].Package.GetName()).To(Equal("Z"))
Expect(orderW[3].Package.GetName()).To(Equal("W"))
})
}
})
})