🎨 Swap toposort implementation

This commit is contained in:
mudler
2022-06-07 23:27:45 +02:00
parent aeb686f426
commit 913462b81c
12 changed files with 294 additions and 218 deletions

View File

@@ -6,10 +6,9 @@ import (
"sort"
"unicode"
"github.com/mudler/luet/pkg/helpers"
"github.com/kendru/darwin/go/depgraph"
"github.com/mudler/topsort"
"github.com/pkg/errors"
toposort "github.com/scrohde/go-toposort"
)
// PackageAssert represent a package assertion.
@@ -36,42 +35,31 @@ func (assertions PackagesAssertions) EnsureOrder(definitiondb PackageDatabase) (
allAssertions := assertions
orderedAssertions := PackagesAssertions{}
tmpMap := map[string]PackageAssert{}
graph := toposort.NewGraph(len(allAssertions))
g := depgraph.New()
for _, a := range assertions {
tmpMap[a.Package.GetPackageName()] = a
graph.AddNode(a.Package.GetPackageName())
}
edges := map[string]string{}
// Build a topological graph
for _, a := range allAssertions {
for _, req := range a.Package.GetRequires() {
if def, err := definitiondb.FindPackage(req); err == nil { // Provides: Get a chance of being override here
req = def
}
edges[a.Package.GetPackageName()] = req.GetPackageName()
graph.AddNode(req.GetPackageName())
g.DependOn(a.Package.GetPackageName(), req.GetPackageName())
}
}
for k, v := range edges {
graph.AddEdge(k, v)
}
result, ok := graph.ToposortStable()
if !ok {
return nil, fmt.Errorf("cycle found")
}
for _, res := range result {
a, ok := tmpMap[res]
if ok {
orderedAssertions = append(orderedAssertions, a)
for _, res := range g.TopoSortedLayers() {
for _, r := range res {
a, ok := tmpMap[r]
if ok {
orderedAssertions = append(orderedAssertions, a)
}
}
}
helpers.ReverseAny(orderedAssertions)
// helpers.ReverseAny(orderedAssertions)
return orderedAssertions, nil
}

View File

@@ -82,5 +82,35 @@ var _ = Describe("Assertions", func() {
Expect(ordered[0].Package.Name).To(Equal("bar"))
Expect(ordered[1].Package.Name).To(Equal("foobaz"))
})
It("orders them correctly", func() {
foo := &types.Package{Name: "foo", PackageRequires: []*types.Package{{Name: "bar"}}}
assertions := types.PackagesAssertions{
{Package: foo},
{Package: &types.Package{Name: "bazbaz2", PackageRequires: []*types.Package{{Name: "baz2"}}}},
{Package: &types.Package{Name: "baz2", PackageRequires: []*types.Package{{Name: "foobaz"}, {Name: "baz"}}}},
{Package: &types.Package{Name: "baz", PackageRequires: []*types.Package{{Name: "bar"}}}},
{Package: &types.Package{Name: "bar", PackageRequires: []*types.Package{{}}}},
{Package: &types.Package{Name: "foobaz", PackageRequires: []*types.Package{{}}}},
}
ordered_old, err := assertions.Order(database.NewInMemoryDatabase(false), foo.GetFingerPrint())
Expect(err).ShouldNot(HaveOccurred())
Expect(ordered_old[0].Package.Name).To(Equal("bar"))
Expect(ordered_old[1].Package.Name).ToNot(Equal("foobaz"))
ordered, err := assertions.EnsureOrder(database.NewInMemoryDatabase(false))
Expect(err).ShouldNot(HaveOccurred())
Expect(len(ordered)).To(Equal(6))
Expect(ordered[0].Package.Name).To(Or(Equal("foobaz"), Equal("bar")))
Expect(ordered[1].Package.Name).To(Or(Equal("foobaz"), Equal("bar")))
Expect(ordered[2].Package.Name).To(Or(Equal("foo"), Equal("baz")))
Expect(ordered[3].Package.Name).To(Or(Equal("foo"), Equal("baz")))
Expect(ordered[4].Package.Name).To(Equal("baz2"))
Expect(ordered[5].Package.Name).To(Equal("bazbaz2"))
})
})
})