mirror of
https://github.com/mudler/luet.git
synced 2025-09-06 01:30:29 +00:00
Introduce install --relaxed
It introduces a relaxed way to install packages with loose deps. Default installation now will by default prefer up-to-date packages during selection. Also: - Upgrade now it's used in install so it have to return the full system view also when there is nothing to upgrade - Avoid checking upgrade upfront if relaxed is on
This commit is contained in:
@@ -104,6 +104,7 @@ To force install a package:
|
||||
PreserveSystemEssentialData: true,
|
||||
DownloadOnly: downloadOnly,
|
||||
Ask: !yes,
|
||||
Relaxed: relax,
|
||||
})
|
||||
inst.Repositories(repos)
|
||||
|
||||
@@ -125,6 +126,8 @@ func init() {
|
||||
installCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
||||
installCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
|
||||
installCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful!)")
|
||||
installCmd.Flags().Bool("relax", false, "Relax installation constraints")
|
||||
|
||||
installCmd.Flags().Bool("onlydeps", false, "Consider **only** package dependencies")
|
||||
installCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
|
||||
installCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
|
||||
|
@@ -50,6 +50,7 @@ type LuetInstallerOptions struct {
|
||||
SolverUpgrade, RemoveUnavailableOnUpgrade, UpgradeNewRevisions bool
|
||||
Ask bool
|
||||
DownloadOnly bool
|
||||
Relaxed bool
|
||||
}
|
||||
|
||||
type LuetInstaller struct {
|
||||
@@ -513,7 +514,7 @@ func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(s.Database.World()) > 0 {
|
||||
if len(s.Database.World()) > 0 && !l.Options.Relaxed {
|
||||
Info(":thinking: Checking for available upgrades")
|
||||
if err := l.checkAndUpgrade(syncedRepos, s); err != nil {
|
||||
return errors.Wrap(err, "while checking upgrades before install")
|
||||
@@ -684,7 +685,12 @@ func (l *LuetInstaller) computeInstall(o Option, syncedRepos Repositories, cp pk
|
||||
|
||||
if !o.NoDeps {
|
||||
solv := solver.NewResolver(solver.Options{Type: l.Options.SolverOptions.Implementation, Concurrency: l.Options.Concurrency}, s.Database, allRepos, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver())
|
||||
|
||||
if l.Options.Relaxed {
|
||||
solution, err = solv.RelaxedInstall(p)
|
||||
} else {
|
||||
solution, err = solv.Install(p)
|
||||
}
|
||||
/// TODO: PackageAssertions needs to be a map[fingerprint]pack so lookup is in O(1)
|
||||
if err != nil && !o.Force {
|
||||
return toInstall, p, solution, allRepos, errors.Wrap(err, "Failed solving solution for package")
|
||||
|
@@ -72,6 +72,7 @@ type Package interface {
|
||||
SetVersion(string)
|
||||
RequiresContains(PackageDatabase, Package) (bool, error)
|
||||
Matches(m Package) bool
|
||||
AtomMatches(m Package) bool
|
||||
BumpBuildVersion() error
|
||||
|
||||
AddUse(use string)
|
||||
@@ -536,6 +537,13 @@ func (p *DefaultPackage) Matches(m Package) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *DefaultPackage) AtomMatches(m Package) bool {
|
||||
if p.GetName() == m.GetName() && p.GetCategory() == m.GetCategory() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *DefaultPackage) Mark() Package {
|
||||
marked := p.Clone()
|
||||
marked.SetName("@@" + marked.GetName())
|
||||
@@ -795,37 +803,38 @@ func (pack *DefaultPackage) buildFormula(definitiondb PackageDatabase, db Packag
|
||||
required = requiredDef
|
||||
} else {
|
||||
|
||||
var ALO, priorityConstraints, priorityALO []bf.Formula
|
||||
var ALO []bf.Formula // , priorityConstraints, priorityALO []bf.Formula
|
||||
|
||||
// Try to prio best match
|
||||
// Force the solver to consider first our candidate (if does exists).
|
||||
// Then builds ALO and AMO for the requires.
|
||||
c, candidateErr := definitiondb.FindPackageCandidate(requiredDef)
|
||||
var C bf.Formula
|
||||
if candidateErr == nil {
|
||||
// We have a desired candidate, try to look a solution with that included first
|
||||
for _, o := range packages {
|
||||
encodedB, err := o.Encode(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
B := bf.Var(encodedB)
|
||||
if !o.Matches(c) {
|
||||
priorityConstraints = append(priorityConstraints, bf.Not(B))
|
||||
priorityALO = append(priorityALO, B)
|
||||
}
|
||||
}
|
||||
encodedC, err := c.Encode(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
C = bf.Var(encodedC)
|
||||
// Or the Candidate is true, or all the others might be not true
|
||||
// This forces the CDCL sat implementation to look first at a solution with C=true
|
||||
formulas = append(formulas, bf.Or(bf.Not(A), bf.Or(bf.And(C, bf.Or(priorityConstraints...)), bf.And(bf.Not(C), bf.Or(priorityALO...)))))
|
||||
}
|
||||
// c, candidateErr := definitiondb.FindPackageCandidate(requiredDef)
|
||||
// var C bf.Formula
|
||||
// if candidateErr == nil {
|
||||
// // We have a desired candidate, try to look a solution with that included first
|
||||
// for _, o := range packages {
|
||||
// encodedB, err := o.Encode(db)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// B := bf.Var(encodedB)
|
||||
// if !o.Matches(c) {
|
||||
// priorityConstraints = append(priorityConstraints, bf.Not(B))
|
||||
// priorityALO = append(priorityALO, B)
|
||||
// }
|
||||
// }
|
||||
// encodedC, err := c.Encode(db)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// C = bf.Var(encodedC)
|
||||
// // Or the Candidate is true, or all the others might be not true
|
||||
// // This forces the CDCL sat implementation to look first at a solution with C=true
|
||||
// //formulas = append(formulas, bf.Or(bf.Not(A), bf.Or(bf.And(C, bf.Or(priorityConstraints...)), bf.And(bf.Not(C), bf.Or(priorityALO...)))))
|
||||
// formulas = append(formulas, bf.Or(C, bf.Or(priorityConstraints...)))
|
||||
// }
|
||||
|
||||
// AMO - At most one
|
||||
// AMO/ALO - At most/least one
|
||||
for _, o := range packages {
|
||||
encodedB, err := o.Encode(db)
|
||||
if err != nil {
|
||||
|
@@ -415,6 +415,7 @@ var _ = Describe("Decoder", func() {
|
||||
|
||||
orderW, err := solution.Order(dbDefinitions, W.GetFingerPrint())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(orderW) > 0).To(BeTrue())
|
||||
Expect(orderW[0].Package.GetName()).To(Equal("X"))
|
||||
Expect(orderW[1].Package.GetName()).To(Equal("Y"))
|
||||
Expect(orderW[2].Package.GetName()).To(Equal("Z"))
|
||||
|
@@ -550,6 +550,13 @@ func (s *Parallel) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAsse
|
||||
// Upgrade compute upgrades of the package against the world definition.
|
||||
// It accepts two boolean indicating if it has to check for conflicts or try to attempt a full upgrade
|
||||
func (s *Parallel) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAssertions, error) {
|
||||
return s.upgrade(s.DefinitionDatabase, s.InstalledDatabase, checkconflicts, full)
|
||||
|
||||
}
|
||||
|
||||
// Upgrade compute upgrades of the package against the world definition.
|
||||
// It accepts two boolean indicating if it has to check for conflicts or try to attempt a full upgrade
|
||||
func (s *Parallel) upgrade(defDB pkg.PackageDatabase, installDB pkg.PackageDatabase, checkconflicts, full bool) (pkg.Packages, PackagesAssertions, error) {
|
||||
|
||||
// First get candidates that needs to be upgraded..
|
||||
|
||||
@@ -557,7 +564,7 @@ func (s *Parallel) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAss
|
||||
toInstall := pkg.Packages{}
|
||||
|
||||
// we do this in memory so we take into account of provides
|
||||
universe, err := s.DefinitionDatabase.Copy()
|
||||
universe, err := defDB.Copy()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Could not copy def db")
|
||||
}
|
||||
@@ -595,7 +602,7 @@ func (s *Parallel) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAss
|
||||
}
|
||||
}()
|
||||
|
||||
for _, p := range s.InstalledDatabase.World() {
|
||||
for _, p := range installDB.World() {
|
||||
all <- p
|
||||
}
|
||||
|
||||
@@ -604,7 +611,7 @@ func (s *Parallel) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAss
|
||||
close(results)
|
||||
wg2.Wait()
|
||||
|
||||
s2 := &Parallel{Concurrency: s.Concurrency, InstalledDatabase: installedcopy, DefinitionDatabase: s.DefinitionDatabase, ParallelDatabase: pkg.NewInMemoryDatabase(false)}
|
||||
s2 := &Parallel{Concurrency: s.Concurrency, InstalledDatabase: installedcopy, DefinitionDatabase: defDB, ParallelDatabase: pkg.NewInMemoryDatabase(false)}
|
||||
s2.SetResolver(s.Resolver)
|
||||
if !full {
|
||||
ass := PackagesAssertions{}
|
||||
@@ -855,6 +862,32 @@ func (s *Parallel) Install(c pkg.Packages) (PackagesAssertions, error) {
|
||||
}
|
||||
return ass, nil
|
||||
}
|
||||
|
||||
return s.Solve()
|
||||
assertions, err := s.Solve()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.upgradeAssertions(assertions)
|
||||
}
|
||||
|
||||
func (s *Parallel) upgradeAssertions(assertions PackagesAssertions) (PackagesAssertions, error) {
|
||||
|
||||
systemAfterInstall := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
for _, p := range assertions {
|
||||
if p.Value {
|
||||
systemAfterInstall.CreatePackage(p.Package)
|
||||
}
|
||||
}
|
||||
|
||||
_, assertions, err := s.upgrade(s.DefinitionDatabase, systemAfterInstall, false, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// for _, u := range toUninstall {
|
||||
// systemAfterInstall.RemovePackage()
|
||||
|
||||
// }
|
||||
return assertions, nil
|
||||
}
|
||||
|
@@ -37,6 +37,8 @@ const (
|
||||
type PackageSolver interface {
|
||||
SetDefinitionDatabase(pkg.PackageDatabase)
|
||||
Install(p pkg.Packages) (PackagesAssertions, error)
|
||||
RelaxedInstall(p pkg.Packages) (PackagesAssertions, error)
|
||||
|
||||
Uninstall(checkconflicts, full bool, candidate ...pkg.Package) (pkg.Packages, error)
|
||||
ConflictsWithInstalled(p pkg.Package) (bool, error)
|
||||
ConflictsWith(p pkg.Package, ls pkg.Packages) (bool, error)
|
||||
@@ -51,6 +53,7 @@ type PackageSolver interface {
|
||||
SetResolver(PackageResolver)
|
||||
|
||||
Solve() (PackagesAssertions, error)
|
||||
// BestInstall(c pkg.Packages) (PackagesAssertions, error)
|
||||
}
|
||||
|
||||
// Solver is the default solver for luet
|
||||
@@ -493,34 +496,47 @@ func (s *Solver) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAssert
|
||||
return markedForRemoval, assertion, nil
|
||||
}
|
||||
|
||||
func (s *Solver) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAssertions, error) {
|
||||
|
||||
// First get candidates that needs to be upgraded..
|
||||
func inPackage(list []pkg.Package, p pkg.Package) bool {
|
||||
for _, l := range list {
|
||||
if l.AtomMatches(p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Compute upgrade between packages if specified, or all if none is specified
|
||||
func (s *Solver) computeUpgrade(pps ...pkg.Package) func(defDB pkg.PackageDatabase, installDB pkg.PackageDatabase) (pkg.Packages, pkg.Packages, pkg.PackageDatabase) {
|
||||
return func(defDB pkg.PackageDatabase, installDB pkg.PackageDatabase) (pkg.Packages, pkg.Packages, pkg.PackageDatabase) {
|
||||
toUninstall := pkg.Packages{}
|
||||
toInstall := pkg.Packages{}
|
||||
|
||||
// we do this in memory so we take into account of provides, and its faster
|
||||
universe, err := s.DefinitionDatabase.Copy()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed creating db copy")
|
||||
}
|
||||
universe, _ := defDB.Copy()
|
||||
|
||||
installedcopy := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
for _, p := range s.InstalledDatabase.World() {
|
||||
for _, p := range installDB.World() {
|
||||
installedcopy.CreatePackage(p)
|
||||
packages, err := universe.FindPackageVersions(p)
|
||||
if err == nil && len(packages) != 0 {
|
||||
best := packages.Best(nil)
|
||||
if !best.Matches(p) {
|
||||
if !best.Matches(p) && len(pps) == 0 ||
|
||||
len(pps) != 0 && inPackage(pps, p) {
|
||||
toUninstall = append(toUninstall, p)
|
||||
toInstall = append(toInstall, best)
|
||||
}
|
||||
}
|
||||
}
|
||||
return toUninstall, toInstall, installedcopy
|
||||
}
|
||||
}
|
||||
|
||||
s2 := NewSolver(Options{Type: SingleCoreSimple}, installedcopy, s.DefinitionDatabase, pkg.NewInMemoryDatabase(false))
|
||||
func (s *Solver) upgrade(fn func(defDB pkg.PackageDatabase, installDB pkg.PackageDatabase) (pkg.Packages, pkg.Packages, pkg.PackageDatabase), defDB pkg.PackageDatabase, installDB pkg.PackageDatabase, checkconflicts, full bool) (pkg.Packages, PackagesAssertions, error) {
|
||||
|
||||
toUninstall, toInstall, installedcopy := fn(defDB, installDB)
|
||||
|
||||
s2 := NewSolver(Options{Type: SingleCoreSimple}, installedcopy, defDB, pkg.NewInMemoryDatabase(false))
|
||||
s2.SetResolver(s.Resolver)
|
||||
if !full {
|
||||
ass := PackagesAssertions{}
|
||||
@@ -541,15 +557,20 @@ func (s *Solver) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAsser
|
||||
}
|
||||
|
||||
if len(toInstall) == 0 {
|
||||
return toUninstall, PackagesAssertions{}, nil
|
||||
ass := PackagesAssertions{}
|
||||
for _, i := range installDB.World() {
|
||||
ass = append(ass, PackageAssert{Package: i.(*pkg.DefaultPackage), Value: true})
|
||||
}
|
||||
return toUninstall, ass, nil
|
||||
}
|
||||
|
||||
assertions, err := s2.Install(toInstall.Unique())
|
||||
assertions, err := s2.RelaxedInstall(toInstall.Unique())
|
||||
|
||||
return toUninstall, assertions, err
|
||||
// To that tree, ask to install the versions that should be upgraded, and try to solve
|
||||
// Return the solution
|
||||
}
|
||||
|
||||
func (s *Solver) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAssertions, error) {
|
||||
return s.upgrade(s.computeUpgrade(), s.DefinitionDatabase, s.InstalledDatabase, checkconflicts, full)
|
||||
}
|
||||
|
||||
// Uninstall takes a candidate package and return a list of packages that would be removed
|
||||
@@ -619,7 +640,7 @@ func (s *Solver) Uninstall(checkconflicts, full bool, packs ...pkg.Package) (pkg
|
||||
s2.SetResolver(s.Resolver)
|
||||
|
||||
// Get the requirements to install the candidate
|
||||
asserts, err := s2.Install(toRemove)
|
||||
asserts, err := s2.RelaxedInstall(toRemove)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -729,7 +750,7 @@ 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(c pkg.Packages) (PackagesAssertions, error) {
|
||||
func (s *Solver) RelaxedInstall(c pkg.Packages) (PackagesAssertions, error) {
|
||||
|
||||
coll, err := s.getList(s.DefinitionDatabase, c)
|
||||
if err != nil {
|
||||
@@ -749,6 +770,59 @@ func (s *Solver) Install(c pkg.Packages) (PackagesAssertions, error) {
|
||||
}
|
||||
return ass, nil
|
||||
}
|
||||
|
||||
return s.Solve()
|
||||
assertions, err := s.Solve()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return assertions, nil
|
||||
}
|
||||
|
||||
// Install returns the assertions necessary in order to install the packages in
|
||||
// a system.
|
||||
// It calculates the best result possible, trying to maximize new packages.
|
||||
func (s *Solver) Install(c pkg.Packages) (PackagesAssertions, error) {
|
||||
assertions, err := s.RelaxedInstall(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
systemAfterInstall := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
toUpgrade := pkg.Packages{}
|
||||
|
||||
for _, p := range c {
|
||||
if p.GetVersion() == ">=0" || p.GetVersion() == ">0" {
|
||||
toUpgrade = append(toUpgrade, p)
|
||||
}
|
||||
}
|
||||
for _, p := range assertions {
|
||||
if p.Value {
|
||||
systemAfterInstall.CreatePackage(p.Package)
|
||||
if !inPackage(c, p.Package) {
|
||||
toUpgrade = append(toUpgrade, p.Package)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(toUpgrade) == 0 {
|
||||
return assertions, nil
|
||||
}
|
||||
// do partial upgrade based on input.
|
||||
// IF there is no version specified in the input, or >=0 is specified,
|
||||
// then compute upgrade for those
|
||||
_, newassertions, err := s.upgrade(s.computeUpgrade(toUpgrade...), s.DefinitionDatabase, systemAfterInstall, false, false)
|
||||
if err != nil {
|
||||
// TODO: Emit warning.
|
||||
// We were not able to compute upgrades (maybe for some pinned packages, or a conflict)
|
||||
// so we return the relaxed result
|
||||
return assertions, nil
|
||||
}
|
||||
|
||||
// Protect if we return no assertion at all
|
||||
if len(newassertions) == 0 && len(assertions) > 0 {
|
||||
return assertions, nil
|
||||
}
|
||||
|
||||
return newassertions, nil
|
||||
}
|
||||
|
@@ -16,6 +16,8 @@
|
||||
package solver_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
@@ -36,6 +38,143 @@ var _ = Describe("Solver", func() {
|
||||
dbDefinitions = pkg.NewInMemoryDatabase(false)
|
||||
s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db)
|
||||
})
|
||||
|
||||
Context("Select of best available package", func() {
|
||||
|
||||
It("picks the best versions available for each package, excluding the ones manually specified while installing", func() {
|
||||
|
||||
B1 := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B2 := pkg.NewPackage("B", "1.2", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B3 := pkg.NewPackage("B", "1.3", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B4 := pkg.NewPackage("B", "1.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
A1 := pkg.NewPackage("A", "1.1", []*pkg.DefaultPackage{
|
||||
pkg.NewPackage("B", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}),
|
||||
}, []*pkg.DefaultPackage{})
|
||||
A2 := pkg.NewPackage("A", "1.2", []*pkg.DefaultPackage{
|
||||
pkg.NewPackage("B", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}),
|
||||
}, []*pkg.DefaultPackage{})
|
||||
|
||||
D := pkg.NewPackage("D", "1.0", []*pkg.DefaultPackage{
|
||||
pkg.NewPackage("A", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}),
|
||||
}, []*pkg.DefaultPackage{})
|
||||
|
||||
C := pkg.NewPackage("C", "1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
for _, p := range []pkg.Package{A1, A2, B1, B2, B3, B4, 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(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.(*Solver).Install([]pkg.Package{D})
|
||||
fmt.Println(solution)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(solution)).To(Equal(8))
|
||||
|
||||
// Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B4, Value: true}))
|
||||
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A1, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B1, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B2, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B3, Value: false}))
|
||||
|
||||
s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err = s.(*Solver).Install([]pkg.Package{D, B2})
|
||||
fmt.Println(solution)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(solution)).To(Equal(8))
|
||||
|
||||
// Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B2, Value: true}))
|
||||
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A1, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B1, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B4, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B3, Value: false}))
|
||||
|
||||
})
|
||||
|
||||
It("picks the best available excluding those manually input. In this case we the input is a selector >=0", func() {
|
||||
|
||||
B1 := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B2 := pkg.NewPackage("B", "1.2", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B3 := pkg.NewPackage("B", "1.3", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B4 := pkg.NewPackage("B", "1.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
A1 := pkg.NewPackage("A", "1.1", []*pkg.DefaultPackage{
|
||||
pkg.NewPackage("B", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}),
|
||||
}, []*pkg.DefaultPackage{})
|
||||
A2 := pkg.NewPackage("A", "1.2", []*pkg.DefaultPackage{
|
||||
pkg.NewPackage("B", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}),
|
||||
}, []*pkg.DefaultPackage{})
|
||||
|
||||
D := pkg.NewPackage("D", "1.0", []*pkg.DefaultPackage{
|
||||
pkg.NewPackage("A", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}),
|
||||
}, []*pkg.DefaultPackage{})
|
||||
|
||||
C := pkg.NewPackage("C", "1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
|
||||
for _, p := range []pkg.Package{A1, A2, B1, B2, B3, B4, 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(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.(*Solver).Install([]pkg.Package{pkg.NewPackage("D", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})})
|
||||
fmt.Println(solution)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(solution)).To(Equal(8))
|
||||
|
||||
// Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B4, Value: true}))
|
||||
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A1, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B1, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B2, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B3, Value: false}))
|
||||
|
||||
s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err = s.(*Solver).Install([]pkg.Package{pkg.NewPackage("D", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}), B2})
|
||||
fmt.Println(solution)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(solution)).To(Equal(8))
|
||||
|
||||
// Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B2, Value: true}))
|
||||
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A1, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B1, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B4, Value: false}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B3, Value: false}))
|
||||
|
||||
})
|
||||
})
|
||||
Context("Simple set", func() {
|
||||
It("Solves correctly if the selected package has no requirements or conflicts and we have nothing installed yet", func() {
|
||||
|
||||
|
Reference in New Issue
Block a user