mirror of
https://github.com/mudler/luet.git
synced 2025-09-01 23:37:07 +00:00
Make solver consume databases instead of world lists
first step - it is slower in the implementation for now, but all cases seems to be sorted out. Drop Flagged() and IsSet() from solver. the solver wont care, and only the assertion value does matter (exception for uninstall)
This commit is contained in:
@@ -22,7 +22,7 @@ import (
|
||||
"unicode"
|
||||
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
"github.com/philopon/go-toposort"
|
||||
toposort "github.com/philopon/go-toposort"
|
||||
"github.com/stevenle/topsort"
|
||||
)
|
||||
|
||||
@@ -88,7 +88,7 @@ func (assertions PackagesAssertions) EnsureOrder() PackagesAssertions {
|
||||
fingerprints = append(fingerprints, a.Package.GetFingerPrint())
|
||||
unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered
|
||||
|
||||
if a.Package.Flagged() && a.Value {
|
||||
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
|
||||
@@ -137,7 +137,7 @@ func (assertions PackagesAssertions) Order(fingerprint string) PackagesAssertion
|
||||
fingerprints = append(fingerprints, a.Package.GetFingerPrint())
|
||||
unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered
|
||||
|
||||
if a.Package.Flagged() && a.Value {
|
||||
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
|
||||
@@ -215,7 +215,7 @@ func (a PackagesAssertions) Less(i, j int) bool {
|
||||
func (assertions PackagesAssertions) AssertionHash() string {
|
||||
var fingerprint string
|
||||
for _, assertion := range assertions { // Note: Always order them first!
|
||||
if assertion.Value && assertion.Package.Flagged() { // Tke into account only dependencies installed (get fingerprint of subgraph)
|
||||
if assertion.Value { // Tke into account only dependencies installed (get fingerprint of subgraph)
|
||||
fingerprint += assertion.ToString() + "\n"
|
||||
}
|
||||
}
|
||||
|
@@ -26,11 +26,22 @@ import (
|
||||
)
|
||||
|
||||
var _ = Describe("Decoder", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
dbInstalled := pkg.NewInMemoryDatabase(false)
|
||||
dbDefinitions := pkg.NewInMemoryDatabase(false)
|
||||
s := NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
BeforeEach(func() {
|
||||
db = pkg.NewInMemoryDatabase(false)
|
||||
dbInstalled = pkg.NewInMemoryDatabase(false)
|
||||
dbDefinitions = pkg.NewInMemoryDatabase(false)
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
})
|
||||
|
||||
Context("Assertion ordering", func() {
|
||||
eq := 0
|
||||
for index := 0; index < 300; index++ { // Just to make sure we don't have false positives
|
||||
It("Orders them correctly #"+strconv.Itoa(index), func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -41,15 +52,23 @@ var _ = Describe("Decoder", func() {
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D, E, F, G}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D, E, F, G} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@@ -73,7 +92,6 @@ var _ = Describe("Decoder", func() {
|
||||
equality := 0
|
||||
for index := 0; index < 300; index++ { // Just to make sure we don't have false positives
|
||||
It("Doesn't order them correctly otherwise #"+strconv.Itoa(index), func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -84,15 +102,23 @@ var _ = Describe("Decoder", func() {
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D, E, F, G}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D, E, F, G} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@@ -132,7 +158,6 @@ var _ = Describe("Decoder", func() {
|
||||
|
||||
Context("Assertion hashing", func() {
|
||||
It("Hashes them, and could be used for comparison", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -143,15 +168,23 @@ var _ = Describe("Decoder", func() {
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D, E, F, G}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D, E, F, G} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@@ -165,11 +198,11 @@ var _ = Describe("Decoder", func() {
|
||||
hash := solution.AssertionHash()
|
||||
|
||||
solution, err = s.Install([]pkg.Package{B})
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@@ -183,18 +216,29 @@ var _ = Describe("Decoder", func() {
|
||||
Expect(solution[3].Package.GetName()).To(Equal("D"))
|
||||
Expect(solution[4].Package.GetName()).To(Equal("B"))
|
||||
Expect(solution[0].Value).ToNot(BeTrue())
|
||||
Expect(solution[0].Package.Flagged()).To(BeTrue())
|
||||
|
||||
Expect(hash).ToNot(Equal(""))
|
||||
Expect(hash2).ToNot(Equal(""))
|
||||
Expect(hash != hash2).To(BeTrue())
|
||||
db2 := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
})
|
||||
It("Hashes them, and could be used for comparison", 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{})
|
||||
s = NewSolver([]pkg.Package{}, []pkg.Package{X, Y, Z}, db2)
|
||||
solution, err = s.Install([]pkg.Package{Y})
|
||||
|
||||
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{Y})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
solution2, err := s.Install([]pkg.Package{Z})
|
||||
|
@@ -16,9 +16,11 @@
|
||||
package solver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
|
||||
//. "github.com/mudler/luet/pkg/logger"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/crillab/gophersat/bf"
|
||||
version "github.com/hashicorp/go-version"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
@@ -26,32 +28,57 @@ import (
|
||||
|
||||
// PackageSolver is an interface to a generic package solving algorithm
|
||||
type PackageSolver interface {
|
||||
SetWorld(p []pkg.Package)
|
||||
SetDefinitionDatabase(pkg.PackageDatabase)
|
||||
Install(p []pkg.Package) (PackagesAssertions, error)
|
||||
Uninstall(candidate pkg.Package) ([]pkg.Package, error)
|
||||
ConflictsWithInstalled(p pkg.Package) (bool, error)
|
||||
ConflictsWith(p pkg.Package, ls []pkg.Package) (bool, error)
|
||||
Best([]pkg.Package) pkg.Package
|
||||
World() []pkg.Package
|
||||
}
|
||||
|
||||
// Solver is the default solver for luet
|
||||
type Solver struct {
|
||||
SolverDatabase pkg.PackageDatabase
|
||||
Wanted []pkg.Package
|
||||
Installed []pkg.Package
|
||||
World []pkg.Package
|
||||
DefinitionDatabase pkg.PackageDatabase
|
||||
SolverDatabase pkg.PackageDatabase
|
||||
Wanted []pkg.Package
|
||||
InstalledDatabase pkg.PackageDatabase
|
||||
}
|
||||
|
||||
// NewSolver accepts as argument two lists of packages, the first is the initial set,
|
||||
// the second represent all the known packages.
|
||||
func NewSolver(init []pkg.Package, w []pkg.Package, solverdb pkg.PackageDatabase) PackageSolver {
|
||||
for _, v := range init {
|
||||
pkg.NormalizeFlagged(v)
|
||||
}
|
||||
for _, v := range w {
|
||||
pkg.NormalizeFlagged(v)
|
||||
}
|
||||
return &Solver{Installed: init, World: w, SolverDatabase: solverdb}
|
||||
func NewSolver(installed pkg.PackageDatabase, definitiondb pkg.PackageDatabase, solverdb pkg.PackageDatabase) PackageSolver {
|
||||
// inst := pkg.NewInMemoryDatabase(false)
|
||||
// def := pkg.NewInMemoryDatabase(false)
|
||||
// // // FIXME: This should all be locked in the db - for now forbid the solver to be run in threads.
|
||||
// for _, k := range installed.GetPackages() {
|
||||
// pack, err := installed.GetPackage(k)
|
||||
// if err == nil {
|
||||
// inst.CreatePackage(pack)
|
||||
// }
|
||||
// }
|
||||
// for _, k := range definitiondb.GetPackages() {
|
||||
// pack, err := definitiondb.GetPackage(k)
|
||||
// if err == nil {
|
||||
// def.CreatePackage(pack)
|
||||
// }
|
||||
// }
|
||||
// // FIXME:
|
||||
// for _, k := range inst.GetPackages() {
|
||||
// pack, err := inst.GetPackage(k)
|
||||
// if err == nil {
|
||||
|
||||
// pkg.NormalizeFlagged(inst, pack)
|
||||
// }
|
||||
// }
|
||||
// for _, k := range def.GetPackages() {
|
||||
// pack, err := def.GetPackage(k)
|
||||
// if err == nil {
|
||||
|
||||
// pkg.NormalizeFlagged(def, pack)
|
||||
// }
|
||||
// }
|
||||
return &Solver{InstalledDatabase: installed, DefinitionDatabase: definitiondb, SolverDatabase: solverdb}
|
||||
}
|
||||
|
||||
// TODO: []pkg.Package should have its own type with this kind of methods in (+Unique, sort, etc.)
|
||||
@@ -81,12 +108,36 @@ func (s *Solver) Best(set []pkg.Package) pkg.Package {
|
||||
|
||||
// SetWorld is a setter for the list of all known packages to the solver
|
||||
|
||||
func (s *Solver) SetWorld(p []pkg.Package) {
|
||||
s.World = p
|
||||
func (s *Solver) SetDefinitionDatabase(db pkg.PackageDatabase) {
|
||||
s.DefinitionDatabase = db
|
||||
}
|
||||
|
||||
func (s *Solver) World() []pkg.Package {
|
||||
var all []pkg.Package
|
||||
// FIXME: This should all be locked in the db - for now forbid the solver to be run in threads.
|
||||
for _, k := range s.DefinitionDatabase.GetPackages() {
|
||||
pack, err := s.DefinitionDatabase.GetPackage(k)
|
||||
if err == nil {
|
||||
all = append(all, pack)
|
||||
}
|
||||
}
|
||||
return all
|
||||
}
|
||||
|
||||
func (s *Solver) Installed() []pkg.Package {
|
||||
var all []pkg.Package
|
||||
// FIXME: This should all be locked in the db - for now forbid the solver to be run in threads.
|
||||
for _, k := range s.InstalledDatabase.GetPackages() {
|
||||
pack, err := s.InstalledDatabase.GetPackage(k)
|
||||
if err == nil {
|
||||
all = append(all, pack)
|
||||
}
|
||||
}
|
||||
return all
|
||||
}
|
||||
|
||||
func (s *Solver) noRulesWorld() bool {
|
||||
for _, p := range s.World {
|
||||
for _, p := range s.World() {
|
||||
if len(p.GetConflicts()) != 0 || len(p.GetRequires()) != 0 {
|
||||
return false
|
||||
}
|
||||
@@ -97,8 +148,8 @@ func (s *Solver) noRulesWorld() bool {
|
||||
|
||||
func (s *Solver) BuildInstalled() (bf.Formula, error) {
|
||||
var formulas []bf.Formula
|
||||
for _, p := range s.Installed {
|
||||
solvable, err := p.BuildFormula(s.SolverDatabase)
|
||||
for _, p := range s.Installed() {
|
||||
solvable, err := p.BuildFormula(s.DefinitionDatabase, s.SolverDatabase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -124,8 +175,8 @@ func (s *Solver) BuildWorld(includeInstalled bool) (bf.Formula, error) {
|
||||
formulas = append(formulas, solvable)
|
||||
}
|
||||
|
||||
for _, p := range s.World {
|
||||
solvable, err := p.BuildFormula(s.SolverDatabase)
|
||||
for _, p := range s.World() {
|
||||
solvable, err := p.BuildFormula(s.DefinitionDatabase, s.SolverDatabase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -134,15 +185,42 @@ func (s *Solver) BuildWorld(includeInstalled bool) (bf.Formula, error) {
|
||||
return bf.And(formulas...), nil
|
||||
}
|
||||
|
||||
func (s *Solver) ConflictsWith(p pkg.Package, ls []pkg.Package) (bool, error) {
|
||||
pkg.NormalizeFlagged(p)
|
||||
func (s *Solver) getList(db pkg.PackageDatabase, lsp []pkg.Package) ([]pkg.Package, error) {
|
||||
var ls []pkg.Package
|
||||
for _, pp := range lsp {
|
||||
cp, err := db.FindPackage(pp)
|
||||
if err != nil {
|
||||
cp = pp //Relax search, otherwise we cannot compute solutions for packages not in definitions
|
||||
|
||||
//return nil, errors.Wrap(err, "Package not found in db")
|
||||
}
|
||||
ls = append(ls, cp)
|
||||
}
|
||||
return ls, nil
|
||||
}
|
||||
|
||||
func (s *Solver) ConflictsWith(pack pkg.Package, lsp []pkg.Package) (bool, error) {
|
||||
p, err := s.DefinitionDatabase.FindPackage(pack)
|
||||
if err != nil {
|
||||
p = pack //Relax search, otherwise we cannot compute solutions for packages not in definitions
|
||||
|
||||
// return false, errors.Wrap(err, "Package not found in definition db")
|
||||
}
|
||||
|
||||
ls, err := s.getList(s.DefinitionDatabase, lsp)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "Package not found in definition db")
|
||||
}
|
||||
|
||||
// TODO: Needs to be find in package def before encoding!
|
||||
// pkg.NormalizeFlagged(s.DefinitionDatabase, p)
|
||||
var formulas []bf.Formula
|
||||
|
||||
if s.noRulesWorld() {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
encodedP, err := p.IsFlagged(true).Encode(s.SolverDatabase)
|
||||
encodedP, err := p.Encode(s.SolverDatabase)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -181,33 +259,45 @@ func (s *Solver) ConflictsWith(p pkg.Package, ls []pkg.Package) (bool, error) {
|
||||
}
|
||||
|
||||
func (s *Solver) ConflictsWithInstalled(p pkg.Package) (bool, error) {
|
||||
return s.ConflictsWith(p, s.Installed)
|
||||
return s.ConflictsWith(p, s.Installed())
|
||||
}
|
||||
|
||||
// Uninstall takes a candidate package and return a list of packages that would be removed
|
||||
// in order to purge the candidate. Returns error if unsat.
|
||||
func (s *Solver) Uninstall(candidate pkg.Package) ([]pkg.Package, error) {
|
||||
func (s *Solver) Uninstall(c pkg.Package) ([]pkg.Package, error) {
|
||||
var res []pkg.Package
|
||||
|
||||
candidate, err := s.InstalledDatabase.FindPackage(c)
|
||||
if err != nil {
|
||||
candidate = c //Relax search, otherwise we cannot compute solutions for packages not in definitions
|
||||
// return nil, errors.Wrap(err, "Package not found between installed")
|
||||
}
|
||||
// Build a fake "Installed" - Candidate and its requires tree
|
||||
var InstalledMinusCandidate []pkg.Package
|
||||
for _, i := range s.Installed {
|
||||
if !i.Matches(candidate) && !candidate.RequiresContains(i) {
|
||||
InstalledMinusCandidate = append(InstalledMinusCandidate, i)
|
||||
|
||||
// TODO: Can be optimized
|
||||
for _, i := range s.Installed() {
|
||||
if !i.Matches(candidate) {
|
||||
contains, err := candidate.RequiresContains(s.SolverDatabase, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed getting installed list")
|
||||
}
|
||||
if !contains {
|
||||
InstalledMinusCandidate = append(InstalledMinusCandidate, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the requirements to install the candidate
|
||||
saved := s.Installed
|
||||
s.Installed = []pkg.Package{}
|
||||
saved := s.InstalledDatabase
|
||||
s.InstalledDatabase = pkg.NewInMemoryDatabase(false)
|
||||
asserts, err := s.Install([]pkg.Package{candidate})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.Installed = saved
|
||||
s.InstalledDatabase = saved
|
||||
|
||||
for _, a := range asserts {
|
||||
if a.Value && a.Package.Flagged() {
|
||||
if a.Value {
|
||||
|
||||
c, err := s.ConflictsWithInstalled(a.Package)
|
||||
if err != nil {
|
||||
@@ -249,13 +339,14 @@ func (s *Solver) BuildFormula() (bf.Formula, error) {
|
||||
return nil, err
|
||||
}
|
||||
W := bf.Var(encodedW)
|
||||
|
||||
if len(s.Installed) == 0 {
|
||||
installedWorld := s.Installed()
|
||||
//TODO:Optimize
|
||||
if len(installedWorld) == 0 {
|
||||
formulas = append(formulas, W) //bf.And(bf.True, W))
|
||||
continue
|
||||
}
|
||||
|
||||
for _, installed := range s.Installed {
|
||||
for _, installed := range installedWorld {
|
||||
encodedI, err := installed.Encode(s.SolverDatabase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -297,23 +388,23 @@ func (s *Solver) Solve() (PackagesAssertions, error) {
|
||||
|
||||
// Install given a list of packages, returns package assertions to indicate the packages that must be installed in the system in order
|
||||
// to statisfy all the constraints
|
||||
func (s *Solver) Install(coll []pkg.Package) (PackagesAssertions, error) {
|
||||
for _, v := range coll {
|
||||
v.IsFlagged(false)
|
||||
func (s *Solver) Install(c []pkg.Package) (PackagesAssertions, error) {
|
||||
|
||||
coll, err := s.getList(s.DefinitionDatabase, c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Packages not found in definition db")
|
||||
}
|
||||
|
||||
s.Wanted = coll
|
||||
|
||||
if s.noRulesWorld() {
|
||||
var ass PackagesAssertions
|
||||
for _, p := range s.Installed {
|
||||
pp := p.IsFlagged(true)
|
||||
ass = append(ass, PackageAssert{Package: pp.(*pkg.DefaultPackage), Value: true})
|
||||
for _, p := range s.Installed() {
|
||||
ass = append(ass, PackageAssert{Package: p.(*pkg.DefaultPackage), Value: true})
|
||||
|
||||
}
|
||||
for _, p := range s.Wanted {
|
||||
pp := p.IsFlagged(true)
|
||||
|
||||
ass = append(ass, PackageAssert{Package: pp.(*pkg.DefaultPackage), Value: true})
|
||||
ass = append(ass, PackageAssert{Package: p.(*pkg.DefaultPackage), Value: true})
|
||||
}
|
||||
return ass, nil
|
||||
}
|
||||
|
@@ -17,7 +17,6 @@ package solver_test
|
||||
|
||||
import (
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
"github.com/mudler/luet/pkg/solver"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
@@ -26,38 +25,66 @@ import (
|
||||
|
||||
var _ = Describe("Solver", func() {
|
||||
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
dbInstalled := pkg.NewInMemoryDatabase(false)
|
||||
dbDefinitions := pkg.NewInMemoryDatabase(false)
|
||||
s := NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
BeforeEach(func() {
|
||||
db = pkg.NewInMemoryDatabase(false)
|
||||
dbInstalled = pkg.NewInMemoryDatabase(false)
|
||||
dbDefinitions = pkg.NewInMemoryDatabase(false)
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
})
|
||||
Context("Simple set", func() {
|
||||
It("Solves correctly if the selected package has no requirements or conflicts and we have nothing installed yet", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{}, []pkg.Package{A, B, C}, db)
|
||||
for _, p := range []pkg.Package{A, B, C} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(len(solution)).To(Equal(1))
|
||||
})
|
||||
|
||||
It("Solves correctly if the selected package has no requirements or conflicts and we have installed one package", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C}, db)
|
||||
for _, p := range []pkg.Package{A, B, C} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Install([]pkg.Package{B})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(len(solution)).To(Equal(2))
|
||||
})
|
||||
|
||||
It("Solves correctly if the selected package to install has no requirement or conflicts, but in the world there is one with a requirement", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -65,72 +92,107 @@ var _ = Describe("Solver", func() {
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{E, C}, []pkg.Package{A, B, C, D, E}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D, E} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{E, C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: E.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: false}))
|
||||
|
||||
Expect(len(solution)).To(Equal(5))
|
||||
})
|
||||
|
||||
It("Solves correctly if the selected package to install has requirements", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(3))
|
||||
})
|
||||
|
||||
It("Solves correctly", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C}, db)
|
||||
for _, p := range []pkg.Package{A, B, C} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(len(solution)).To(Equal(3))
|
||||
})
|
||||
It("Solves correctly more complex ones", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(len(solution)).To(Equal(4))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("Solves correctly more complex ones", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -138,37 +200,53 @@ var _ = Describe("Solver", func() {
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{}, []pkg.Package{A, B, C, D, E}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D, E} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(len(solution)).To(Equal(3))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("Uninstalls simple package correctly", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Uninstall(A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||
|
||||
// Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
// Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(len(solution)).To(Equal(1))
|
||||
})
|
||||
|
||||
It("Find conflicts", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -176,7 +254,16 @@ var _ = Describe("Solver", func() {
|
||||
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
val, err := s.ConflictsWithInstalled(A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).To(BeTrue())
|
||||
@@ -184,7 +271,6 @@ var _ = Describe("Solver", func() {
|
||||
})
|
||||
|
||||
It("Find nested conflicts", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -192,14 +278,22 @@ var _ = Describe("Solver", func() {
|
||||
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
val, err := s.ConflictsWithInstalled(D)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).To(BeTrue())
|
||||
})
|
||||
|
||||
It("Doesn't find nested conflicts", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -207,14 +301,22 @@ var _ = Describe("Solver", func() {
|
||||
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
val, err := s.ConflictsWithInstalled(C)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).ToNot(BeTrue())
|
||||
})
|
||||
|
||||
It("Doesn't find conflicts", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -222,40 +324,59 @@ var _ = Describe("Solver", func() {
|
||||
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
val, err := s.ConflictsWithInstalled(C)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(val).ToNot(BeTrue())
|
||||
})
|
||||
It("Uninstalls simple packages not in world correctly", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{B, C, D}, db)
|
||||
for _, p := range []pkg.Package{B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||
|
||||
// Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
// Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(len(solution)).To(Equal(1))
|
||||
})
|
||||
|
||||
It("Uninstalls complex packages not in world correctly", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{B, C, D}, db)
|
||||
for _, p := range []pkg.Package{B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
@@ -265,15 +386,20 @@ var _ = Describe("Solver", func() {
|
||||
})
|
||||
|
||||
It("Uninstalls complex packages correctly, even if shared deps are required by system packages", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
@@ -284,14 +410,20 @@ var _ = Describe("Solver", func() {
|
||||
})
|
||||
|
||||
It("Uninstalls complex packages in world correctly", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{C}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{A, C, D}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Uninstall(A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@@ -303,23 +435,30 @@ var _ = Describe("Solver", func() {
|
||||
})
|
||||
|
||||
It("Uninstalls complex package correctly", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
C.IsFlagged(true) // installed
|
||||
// C // installed
|
||||
|
||||
s := NewSolver([]pkg.Package{A, B, C, D}, []pkg.Package{A, B, C, D}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Uninstall(A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||
Expect(solution).To(ContainElement(B.IsFlagged(false)))
|
||||
Expect(solution).To(ContainElement(D.IsFlagged(false)))
|
||||
|
||||
Expect(len(solution)).To(Equal(3))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
})
|
||||
|
||||
@@ -328,14 +467,20 @@ var _ = Describe("Solver", func() {
|
||||
Context("Conflict set", func() {
|
||||
|
||||
It("is unsolvable - as we something we ask to install conflict with system stuff", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
// D := pkg.NewPackage("D", "", []pkg.Package{}, []pkg.Package{})
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{C})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C}, db)
|
||||
for _, p := range []pkg.Package{A, B, C} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(len(solution)).To(Equal(0))
|
||||
@@ -346,8 +491,6 @@ var _ = Describe("Solver", func() {
|
||||
|
||||
Context("Complex data sets", func() {
|
||||
It("Solves them correctly", func() {
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -357,18 +500,26 @@ var _ = Describe("Solver", func() {
|
||||
B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{})
|
||||
A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{})
|
||||
|
||||
s := NewSolver([]pkg.Package{C}, []pkg.Package{A, B, C, D, E, F, G}, db)
|
||||
for _, p := range []pkg.Package{A, B, C, D, E, F, G} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{C} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Install([]pkg.Package{A})
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G.IsFlagged(true).(*pkg.DefaultPackage), Value: true}))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -391,7 +542,6 @@ var _ = Describe("Solver", func() {
|
||||
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))
|
||||
})
|
||||
|
Reference in New Issue
Block a user