Add Best() to solver for package selection based on version

This commit is contained in:
Ettore Di Giacinto
2019-11-16 14:40:58 +01:00
parent 602f5c68d5
commit 32dea6f7fd
4 changed files with 62 additions and 1 deletions

View File

@@ -113,7 +113,7 @@ func (cs *LuetCompiler) CompileWithReverseDeps(concurrency int, keepPermissions
uniques := toCompile.Unique().Remove(ps) uniques := toCompile.Unique().Remove(ps)
for _, u := range uniques.All() { for _, u := range uniques.All() {
Info(" :arrow_right_hook:", u.GetPackage().GetName(), "🍃", u.GetPackage().GetVersion(), "(", u.GetPackage().GetCategory(), ")") Info(" :arrow_right_hook:", u.GetPackage().GetName(), ":leaves:", u.GetPackage().GetVersion(), "(", u.GetPackage().GetCategory(), ")")
} }
artifacts2, err := cs.CompileParallel(concurrency, keepPermissions, uniques) artifacts2, err := cs.CompileParallel(concurrency, keepPermissions, uniques)
@@ -121,6 +121,8 @@ func (cs *LuetCompiler) CompileWithReverseDeps(concurrency int, keepPermissions
} }
func (cs *LuetCompiler) CompileParallel(concurrency int, keepPermissions bool, ps CompilationSpecs) ([]Artifact, []error) { func (cs *LuetCompiler) CompileParallel(concurrency int, keepPermissions bool, ps CompilationSpecs) ([]Artifact, []error) {
Spinner(22)
defer SpinnerStop()
all := make(chan CompilationSpec) all := make(chan CompilationSpec)
artifacts := []Artifact{} artifacts := []Artifact{}
mutex := &sync.Mutex{} mutex := &sync.Mutex{}

View File

@@ -17,6 +17,8 @@ package pkg_test
import ( import (
. "github.com/mudler/luet/pkg/package" . "github.com/mudler/luet/pkg/package"
pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
@@ -35,6 +37,9 @@ var _ = Describe("Package", func() {
Expect(lst).To(ContainElement(a1)) Expect(lst).To(ContainElement(a1))
Expect(lst).ToNot(ContainElement(a01)) Expect(lst).ToNot(ContainElement(a01))
Expect(len(lst)).To(Equal(2)) Expect(len(lst)).To(Equal(2))
s := solver.NewSolver([]pkg.Package{}, []pkg.Package{}, NewInMemoryDatabase(false))
p := s.Best(lst)
Expect(p).To(Equal(a11))
}) })
}) })

View File

@@ -17,8 +17,10 @@ package solver
import ( import (
"errors" "errors"
"sort"
"github.com/crillab/gophersat/bf" "github.com/crillab/gophersat/bf"
"github.com/hashicorp/go-version"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
) )
@@ -29,6 +31,7 @@ type PackageSolver interface {
Uninstall(candidate pkg.Package) ([]pkg.Package, error) Uninstall(candidate pkg.Package) ([]pkg.Package, error)
ConflictsWithInstalled(p pkg.Package) (bool, error) ConflictsWithInstalled(p pkg.Package) (bool, error)
ConflictsWith(p pkg.Package, ls []pkg.Package) (bool, error) ConflictsWith(p pkg.Package, ls []pkg.Package) (bool, error)
Best([]pkg.Package) pkg.Package
} }
// Solver is the default solver for luet // Solver is the default solver for luet
@@ -51,6 +54,31 @@ func NewSolver(init []pkg.Package, w []pkg.Package, db pkg.PackageDatabase) Pack
return &Solver{Installed: init, World: w, Database: db} return &Solver{Installed: init, World: w, Database: db}
} }
// TODO: []pkg.Package should have its own type with this kind of methods in (+Unique, sort, etc.)
func (s *Solver) Best(set []pkg.Package) pkg.Package {
var versionsMap map[string]pkg.Package = make(map[string]pkg.Package)
if len(set) == 0 {
panic("Best needs a list with elements")
}
versionsRaw := []string{}
for _, p := range set {
versionsRaw = append(versionsRaw, p.GetVersion())
versionsMap[p.GetVersion()] = p
}
versions := make([]*version.Version, len(versionsRaw))
for i, raw := range versionsRaw {
v, _ := version.NewVersion(raw)
versions[i] = v
}
// After this, the versions are properly sorted
sort.Sort(version.Collection(versions))
return versionsMap[versions[len(versions)-1].Original()]
}
// SetWorld is a setter for the list of all known packages to the solver // SetWorld is a setter for the list of all known packages to the solver
func (s *Solver) SetWorld(p []pkg.Package) { func (s *Solver) SetWorld(p []pkg.Package) {

View File

@@ -17,6 +17,7 @@ package solver_test
import ( import (
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@@ -371,4 +372,29 @@ var _ = Describe("Solver", func() {
}) })
}) })
Context("Selection", func() {
a := pkg.NewPackage("A", ">=2.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
a1 := pkg.NewPackage("A", "2.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
a11 := pkg.NewPackage("A", "2.1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
a01 := pkg.NewPackage("A", "2.2", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
a02 := pkg.NewPackage("A", "2.3", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
a03 := pkg.NewPackage("A", "2.3.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
old := pkg.NewPackage("A", "1.3.1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
It("Expands correctly", func() {
lst, err := a.Expand(&[]pkg.Package{a1, a11, a01, a02, a03, old})
Expect(err).ToNot(HaveOccurred())
Expect(lst).To(ContainElement(a11))
Expect(lst).To(ContainElement(a1))
Expect(lst).To(ContainElement(a01))
Expect(lst).To(ContainElement(a02))
Expect(lst).To(ContainElement(a03))
Expect(lst).ToNot(ContainElement(old))
Expect(len(lst)).To(Equal(5))
s := solver.NewSolver([]pkg.Package{}, []pkg.Package{}, pkg.NewInMemoryDatabase(false))
p := s.Best(lst)
Expect(p).To(Equal(a03))
})
})
}) })