🎨 Cleanups

This commit is contained in:
Ettore Di Giacinto
2022-06-06 11:45:05 +02:00
parent 49d8c2b972
commit ce95b3ada4
10 changed files with 136 additions and 29 deletions

View File

@@ -6,9 +6,10 @@ import (
"sort"
"unicode"
"github.com/mudler/luet/pkg/helpers"
"github.com/mudler/topsort"
"github.com/philopon/go-toposort"
"github.com/pkg/errors"
toposort "github.com/scrohde/go-toposort"
)
// PackageAssert represent a package assertion.
@@ -30,50 +31,47 @@ func (a *PackageAssert) String() string {
return fmt.Sprintf("%s/%s %s %s", a.Package.GetCategory(), a.Package.GetName(), a.Package.GetVersion(), msg)
}
func (assertions PackagesAssertions) EnsureOrder() (PackagesAssertions, error) {
func (assertions PackagesAssertions) EnsureOrder(definitiondb PackageDatabase) (PackagesAssertions, error) {
allAssertions := assertions
orderedAssertions := PackagesAssertions{}
unorderedAssertions := PackagesAssertions{}
fingerprints := []string{}
tmpMap := map[string]PackageAssert{}
for _, a := range assertions {
tmpMap[a.Package.GetFingerPrint()] = a
fingerprints = append(fingerprints, a.Package.GetFingerPrint())
unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered
graph := toposort.NewGraph(len(allAssertions))
if a.Value {
unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered
} else {
orderedAssertions = append(orderedAssertions, a) // Keep last the ones which are not meant to be installed
}
for _, a := range assertions {
tmpMap[a.Package.GetPackageName()] = a
graph.AddNode(a.Package.GetPackageName())
}
sort.Sort(unorderedAssertions)
edges := map[string]string{}
// Build a topological graph
graph := toposort.NewGraph(len(unorderedAssertions))
graph.AddNodes(fingerprints...)
for _, a := range unorderedAssertions {
for _, a := range allAssertions {
for _, req := range a.Package.GetRequires() {
graph.AddEdge(a.Package.GetFingerPrint(), req.GetFingerPrint())
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())
}
}
result, ok := graph.Toposort()
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 {
return nil, fmt.Errorf("cycle found")
if ok {
orderedAssertions = append(orderedAssertions, a)
}
orderedAssertions = append(orderedAssertions, a)
// orderedAssertions = append(PackagesAssertions{a}, orderedAssertions...) // push upfront
}
//helpers.ReverseAny(orderedAssertions)
helpers.ReverseAny(orderedAssertions)
return orderedAssertions, nil
}

View File

@@ -0,0 +1,86 @@
// Copyright © 2021 Ettore Di Giacinto <mudler@mocaccino.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package types_test
import (
types "github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/database"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("Assertions", func() {
Context("Ordering", func() {
It("orders them correctly", func() {
foo := &types.Package{Name: "foo", PackageRequires: []*types.Package{{Name: "bar"}}}
assertions := types.PackagesAssertions{
{Package: foo},
{Package: &types.Package{Name: "baz", PackageRequires: []*types.Package{{Name: "bar"}}}},
{Package: &types.Package{Name: "bar", 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"))
ordered, err := assertions.EnsureOrder(database.NewInMemoryDatabase(false))
Expect(err).ShouldNot(HaveOccurred())
Expect(len(ordered)).To(Equal(3))
Expect(ordered[0].Package.Name).To(Equal("bar"))
})
It("errors on cycles", func() {
foo := &types.Package{Name: "foo", PackageRequires: []*types.Package{{Name: "bar"}}}
assertions := types.PackagesAssertions{
{Package: foo},
{Package: &types.Package{Name: "baz", PackageRequires: []*types.Package{{Name: "bar"}}}},
{Package: &types.Package{Name: "bar", PackageRequires: []*types.Package{{Name: "baz"}}}},
}
_, err := assertions.Order(database.NewInMemoryDatabase(false), foo.GetFingerPrint())
Expect(err).Should(HaveOccurred())
_, err = assertions.EnsureOrder(database.NewInMemoryDatabase(false))
Expect(err).Should(HaveOccurred())
})
It("orders them correctly", func() {
foo := &types.Package{Name: "foo", PackageRequires: []*types.Package{{Name: "bar"}}}
assertions := types.PackagesAssertions{
{Package: foo},
{Package: &types.Package{Name: "baz2", PackageRequires: []*types.Package{{Name: "foobaz"}}}},
{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(5))
Expect(ordered[0].Package.Name).To(Equal("bar"))
Expect(ordered[1].Package.Name).To(Equal("foobaz"))
})
})
})