mirror of
https://github.com/mudler/luet.git
synced 2025-09-04 16:50:50 +00:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ec0b83a811 | ||
|
765261f233 | ||
|
6c7e24fadf | ||
|
de23e0d5b1 | ||
|
8572aa5222 | ||
|
0e0c2f21a6 | ||
|
575079bb77 | ||
|
5bcc8d112a | ||
|
65b17f5283 | ||
|
a0618107a8 | ||
|
25f2abf103 | ||
|
e3ebfd6bfe | ||
|
48df98bcae |
@@ -41,6 +41,7 @@ var installCmd = &cobra.Command{
|
|||||||
LuetCfg.Viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
|
LuetCfg.Viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
|
||||||
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
|
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
|
||||||
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
||||||
|
LuetCfg.Viper.BindPFlag("download-only", cmd.Flags().Lookup("download-only"))
|
||||||
|
|
||||||
},
|
},
|
||||||
Long: `Install packages in parallel`,
|
Long: `Install packages in parallel`,
|
||||||
@@ -73,7 +74,7 @@ var installCmd = &cobra.Command{
|
|||||||
force := LuetCfg.Viper.GetBool("force")
|
force := LuetCfg.Viper.GetBool("force")
|
||||||
nodeps := LuetCfg.Viper.GetBool("nodeps")
|
nodeps := LuetCfg.Viper.GetBool("nodeps")
|
||||||
onlydeps := LuetCfg.Viper.GetBool("onlydeps")
|
onlydeps := LuetCfg.Viper.GetBool("onlydeps")
|
||||||
|
downloadOnly := LuetCfg.Viper.GetBool("download-only")
|
||||||
LuetCfg.GetSolverOptions().Type = stype
|
LuetCfg.GetSolverOptions().Type = stype
|
||||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||||
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
||||||
@@ -82,11 +83,12 @@ var installCmd = &cobra.Command{
|
|||||||
Debug("Solver", LuetCfg.GetSolverOptions().CompactString())
|
Debug("Solver", LuetCfg.GetSolverOptions().CompactString())
|
||||||
|
|
||||||
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
|
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
|
||||||
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
||||||
SolverOptions: *LuetCfg.GetSolverOptions(),
|
SolverOptions: *LuetCfg.GetSolverOptions(),
|
||||||
NoDeps: nodeps,
|
NoDeps: nodeps,
|
||||||
Force: force,
|
Force: force,
|
||||||
OnlyDeps: onlydeps,
|
OnlyDeps: onlydeps,
|
||||||
|
PreserveSystemEssentialData: true,
|
||||||
})
|
})
|
||||||
inst.Repositories(repos)
|
inst.Repositories(repos)
|
||||||
|
|
||||||
@@ -97,7 +99,7 @@ var installCmd = &cobra.Command{
|
|||||||
systemDB = pkg.NewInMemoryDatabase(true)
|
systemDB = pkg.NewInMemoryDatabase(true)
|
||||||
}
|
}
|
||||||
system := &installer.System{Database: systemDB, Target: LuetCfg.GetSystem().Rootfs}
|
system := &installer.System{Database: systemDB, Target: LuetCfg.GetSystem().Rootfs}
|
||||||
err := inst.Install(toInstall, system)
|
err := inst.Install(toInstall, system, downloadOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatal("Error: " + err.Error())
|
Fatal("Error: " + err.Error())
|
||||||
}
|
}
|
||||||
@@ -118,6 +120,7 @@ func init() {
|
|||||||
installCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful!)")
|
installCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful!)")
|
||||||
installCmd.Flags().Bool("onlydeps", false, "Consider **only** package dependencies")
|
installCmd.Flags().Bool("onlydeps", false, "Consider **only** package dependencies")
|
||||||
installCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
|
installCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
|
||||||
|
installCmd.Flags().Bool("download-only", false, "Download dependencies only")
|
||||||
|
|
||||||
RootCmd.AddCommand(installCmd)
|
RootCmd.AddCommand(installCmd)
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ var cfgFile string
|
|||||||
var Verbose bool
|
var Verbose bool
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LuetCLIVersion = "0.6.2"
|
LuetCLIVersion = "0.6.4"
|
||||||
LuetEnvPrefix = "LUET"
|
LuetEnvPrefix = "LUET"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -631,7 +631,7 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, p Compila
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if len(dependencies) > 0 {
|
} else if len(dependencies) > 0 {
|
||||||
lastHash = dependencies[len(dependencies)-1].Hash.PackageHash
|
lastHash = cs.ImageRepository + ":" + dependencies[len(dependencies)-1].Hash.PackageHash
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cs.Options.OnlyDeps {
|
if !cs.Options.OnlyDeps {
|
||||||
|
@@ -21,6 +21,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
@@ -36,11 +37,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type LuetInstallerOptions struct {
|
type LuetInstallerOptions struct {
|
||||||
SolverOptions config.LuetSolverOptions
|
SolverOptions config.LuetSolverOptions
|
||||||
Concurrency int
|
Concurrency int
|
||||||
NoDeps bool
|
NoDeps bool
|
||||||
OnlyDeps bool
|
OnlyDeps bool
|
||||||
Force bool
|
Force bool
|
||||||
|
PreserveSystemEssentialData bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type LuetInstaller struct {
|
type LuetInstaller struct {
|
||||||
@@ -106,24 +108,15 @@ func (l *LuetInstaller) Upgrade(s *System) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// First match packages against repositories by priority
|
// First match packages against repositories by priority
|
||||||
// matches := syncedRepos.PackageMatches(p)
|
|
||||||
allRepos := pkg.NewInMemoryDatabase(false)
|
allRepos := pkg.NewInMemoryDatabase(false)
|
||||||
syncedRepos.SyncDatabase(allRepos)
|
syncedRepos.SyncDatabase(allRepos)
|
||||||
// compute a "big" world
|
// compute a "big" world
|
||||||
solv := solver.NewResolver(s.Database, allRepos, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver())
|
solv := solver.NewResolver(s.Database, allRepos, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver())
|
||||||
uninstall, solution, err := solv.Upgrade()
|
uninstall, solution, err := solv.Upgrade(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "Failed solving solution for upgrade")
|
return errors.Wrap(err, "Failed solving solution for upgrade")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, u := range uninstall {
|
|
||||||
err := l.Uninstall(u, s)
|
|
||||||
if err != nil && !l.Options.Force {
|
|
||||||
Error("Failed uninstall for ", u.HumanReadableString())
|
|
||||||
return errors.Wrap(err, "uninstalling "+u.HumanReadableString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toInstall := []pkg.Package{}
|
toInstall := []pkg.Package{}
|
||||||
for _, assertion := range solution {
|
for _, assertion := range solution {
|
||||||
if assertion.Value {
|
if assertion.Value {
|
||||||
@@ -131,7 +124,7 @@ func (l *LuetInstaller) Upgrade(s *System) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return l.Install(toInstall, s)
|
return l.swap(syncedRepos, uninstall, toInstall, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LuetInstaller) SyncRepositories(inMemory bool) (Repositories, error) {
|
func (l *LuetInstaller) SyncRepositories(inMemory bool) (Repositories, error) {
|
||||||
@@ -156,7 +149,62 @@ func (l *LuetInstaller) SyncRepositories(inMemory bool) (Repositories, error) {
|
|||||||
return syncedRepos, nil
|
return syncedRepos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LuetInstaller) Install(cp []pkg.Package, s *System) error {
|
func (l *LuetInstaller) Swap(toRemove []pkg.Package, toInstall []pkg.Package, s *System) error {
|
||||||
|
syncedRepos, err := l.SyncRepositories(true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return l.swap(syncedRepos, toRemove, toInstall, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LuetInstaller) swap(syncedRepos Repositories, toRemove []pkg.Package, toInstall []pkg.Package, s *System) error {
|
||||||
|
|
||||||
|
// First match packages against repositories by priority
|
||||||
|
allRepos := pkg.NewInMemoryDatabase(false)
|
||||||
|
syncedRepos.SyncDatabase(allRepos)
|
||||||
|
toInstall = syncedRepos.ResolveSelectors(toInstall)
|
||||||
|
|
||||||
|
if err := l.install(syncedRepos, toInstall, s, true); err != nil {
|
||||||
|
return errors.Wrap(err, "Pre-downloading packages")
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want any conflict with the installed to raise during the upgrade.
|
||||||
|
// In this way we both force uninstalls and we avoid to check with conflicts
|
||||||
|
// against the current system state which is pending to deletion
|
||||||
|
// E.g. you can't check for conflicts for an upgrade of a new version of A
|
||||||
|
// if the old A results installed in the system. This is due to the fact that
|
||||||
|
// now the solver enforces the constraints and explictly denies two packages
|
||||||
|
// of the same version installed.
|
||||||
|
forced := false
|
||||||
|
if l.Options.Force {
|
||||||
|
forced = true
|
||||||
|
}
|
||||||
|
l.Options.Force = true
|
||||||
|
|
||||||
|
for _, u := range toRemove {
|
||||||
|
Info(":package: Marked for deletion", u.HumanReadableString())
|
||||||
|
|
||||||
|
err := l.Uninstall(u, s)
|
||||||
|
if err != nil && !l.Options.Force {
|
||||||
|
Error("Failed uninstall for ", u.HumanReadableString())
|
||||||
|
return errors.Wrap(err, "uninstalling "+u.HumanReadableString())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
l.Options.Force = forced
|
||||||
|
|
||||||
|
return l.install(syncedRepos, toInstall, s, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LuetInstaller) Install(cp []pkg.Package, s *System, downloadOnly bool) error {
|
||||||
|
syncedRepos, err := l.SyncRepositories(true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return l.install(syncedRepos, cp, s, downloadOnly)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LuetInstaller) install(syncedRepos Repositories, cp []pkg.Package, s *System, downloadOnly bool) error {
|
||||||
var p []pkg.Package
|
var p []pkg.Package
|
||||||
|
|
||||||
// Check if the package is installed first
|
// Check if the package is installed first
|
||||||
@@ -179,10 +227,6 @@ func (l *LuetInstaller) Install(cp []pkg.Package, s *System) error {
|
|||||||
}
|
}
|
||||||
// First get metas from all repos (and decodes trees)
|
// First get metas from all repos (and decodes trees)
|
||||||
|
|
||||||
syncedRepos, err := l.SyncRepositories(true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// First match packages against repositories by priority
|
// First match packages against repositories by priority
|
||||||
// matches := syncedRepos.PackageMatches(p)
|
// matches := syncedRepos.PackageMatches(p)
|
||||||
|
|
||||||
@@ -192,7 +236,7 @@ func (l *LuetInstaller) Install(cp []pkg.Package, s *System) error {
|
|||||||
p = syncedRepos.ResolveSelectors(p)
|
p = syncedRepos.ResolveSelectors(p)
|
||||||
toInstall := map[string]ArtifactMatch{}
|
toInstall := map[string]ArtifactMatch{}
|
||||||
var packagesToInstall []pkg.Package
|
var packagesToInstall []pkg.Package
|
||||||
|
var err error
|
||||||
var solution solver.PackagesAssertions
|
var solution solver.PackagesAssertions
|
||||||
|
|
||||||
if !l.Options.NoDeps {
|
if !l.Options.NoDeps {
|
||||||
@@ -238,40 +282,73 @@ func (l *LuetInstaller) Install(cp []pkg.Package, s *System) error {
|
|||||||
all := make(chan ArtifactMatch)
|
all := make(chan ArtifactMatch)
|
||||||
|
|
||||||
var wg = new(sync.WaitGroup)
|
var wg = new(sync.WaitGroup)
|
||||||
for i := 0; i < l.Options.Concurrency; i++ {
|
|
||||||
wg.Add(1)
|
if !downloadOnly {
|
||||||
go l.installerWorker(i, wg, all, s)
|
// Download first
|
||||||
|
for i := 0; i < l.Options.Concurrency; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go l.installerWorker(i, wg, all, s, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range toInstall {
|
||||||
|
all <- c
|
||||||
|
}
|
||||||
|
close(all)
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
all = make(chan ArtifactMatch)
|
||||||
|
|
||||||
|
wg = new(sync.WaitGroup)
|
||||||
|
|
||||||
|
// Do the real install
|
||||||
|
for i := 0; i < l.Options.Concurrency; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go l.installerWorker(i, wg, all, s, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range toInstall {
|
||||||
|
all <- c
|
||||||
|
}
|
||||||
|
close(all)
|
||||||
|
wg.Wait()
|
||||||
|
} else {
|
||||||
|
for i := 0; i < l.Options.Concurrency; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go l.installerWorker(i, wg, all, s, downloadOnly)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range toInstall {
|
||||||
|
all <- c
|
||||||
|
}
|
||||||
|
close(all)
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
if downloadOnly {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range toInstall {
|
for _, c := range toInstall {
|
||||||
all <- c
|
// Annotate to the system that the package was installed
|
||||||
|
_, err := s.Database.CreatePackage(c.Package)
|
||||||
|
if err != nil && !l.Options.Force {
|
||||||
|
return errors.Wrap(err, "Failed creating package")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
close(all)
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
executedFinalizer := map[string]bool{}
|
executedFinalizer := map[string]bool{}
|
||||||
|
|
||||||
// TODO: Lower those errors as warning
|
// TODO: Lower those errors as warning
|
||||||
for _, w := range p {
|
for _, w := range p {
|
||||||
// Finalizers needs to run in order and in sequence.
|
// Finalizers needs to run in order and in sequence.
|
||||||
ordered := solution.Order(allRepos, w.GetFingerPrint())
|
ordered := solution.Order(allRepos, w.GetFingerPrint())
|
||||||
|
ORDER:
|
||||||
for _, ass := range ordered {
|
for _, ass := range ordered {
|
||||||
if ass.Value {
|
if ass.Value {
|
||||||
// Annotate to the system that the package was installed
|
|
||||||
if _, err := s.Database.FindPackage(ass.Package); err == nil {
|
|
||||||
err := s.Database.UpdatePackage(ass.Package)
|
|
||||||
if err != nil && !l.Options.Force {
|
|
||||||
return errors.Wrap(err, "Failed updating package")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, err := s.Database.CreatePackage(ass.Package)
|
|
||||||
if err != nil && !l.Options.Force {
|
|
||||||
return errors.Wrap(err, "Failed creating package")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
installed, ok := toInstall[ass.Package.GetFingerPrint()]
|
installed, ok := toInstall[ass.Package.GetFingerPrint()]
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("Couldn't find ArtifactMatch for " + ass.Package.HumanReadableString())
|
// It was a dep already installed in the system, so we can skip it safely
|
||||||
|
continue ORDER
|
||||||
}
|
}
|
||||||
|
|
||||||
treePackage, err := installed.Repository.GetTree().GetDatabase().FindPackage(ass.Package)
|
treePackage, err := installed.Repository.GetTree().GetDatabase().FindPackage(ass.Package)
|
||||||
@@ -304,7 +381,7 @@ func (l *LuetInstaller) Install(cp []pkg.Package, s *System) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LuetInstaller) installPackage(a ArtifactMatch, s *System) error {
|
func (l *LuetInstaller) installPackage(a ArtifactMatch, s *System, downloadOnly bool) error {
|
||||||
|
|
||||||
artifact, err := a.Repository.Client().DownloadArtifact(a.Artifact)
|
artifact, err := a.Repository.Client().DownloadArtifact(a.Artifact)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -315,6 +392,9 @@ func (l *LuetInstaller) installPackage(a ArtifactMatch, s *System) error {
|
|||||||
if err != nil && !l.Options.Force {
|
if err != nil && !l.Options.Force {
|
||||||
return errors.Wrap(err, "Artifact integrity check failure")
|
return errors.Wrap(err, "Artifact integrity check failure")
|
||||||
}
|
}
|
||||||
|
if downloadOnly {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
files, err := artifact.FileList()
|
files, err := artifact.FileList()
|
||||||
if err != nil && !l.Options.Force {
|
if err != nil && !l.Options.Force {
|
||||||
@@ -331,18 +411,20 @@ func (l *LuetInstaller) installPackage(a ArtifactMatch, s *System) error {
|
|||||||
return s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: a.Package.GetFingerPrint(), Files: files})
|
return s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: a.Package.GetFingerPrint(), Files: files})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LuetInstaller) installerWorker(i int, wg *sync.WaitGroup, c <-chan ArtifactMatch, s *System) error {
|
func (l *LuetInstaller) installerWorker(i int, wg *sync.WaitGroup, c <-chan ArtifactMatch, s *System, downloadOnly bool) error {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
for p := range c {
|
for p := range c {
|
||||||
// TODO: Keep trace of what was added from the tar, and save it into system
|
// TODO: Keep trace of what was added from the tar, and save it into system
|
||||||
err := l.installPackage(p, s)
|
err := l.installPackage(p, s, downloadOnly)
|
||||||
if err != nil && !l.Options.Force {
|
if err != nil && !l.Options.Force {
|
||||||
//TODO: Uninstall, rollback.
|
//TODO: Uninstall, rollback.
|
||||||
Fatal("Failed installing package "+p.Package.GetName(), err.Error())
|
Fatal("Failed installing package "+p.Package.GetName(), err.Error())
|
||||||
return errors.Wrap(err, "Failed installing package "+p.Package.GetName())
|
return errors.Wrap(err, "Failed installing package "+p.Package.GetName())
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil && downloadOnly {
|
||||||
|
Info(":package: ", p.Package.HumanReadableString(), "downloaded")
|
||||||
|
} else if err == nil {
|
||||||
Info(":package: ", p.Package.HumanReadableString(), "installed")
|
Info(":package: ", p.Package.HumanReadableString(), "installed")
|
||||||
} else if err != nil && l.Options.Force {
|
} else if err != nil && l.Options.Force {
|
||||||
Info(":package: ", p.Package.HumanReadableString(), "installed with failures (force install)")
|
Info(":package: ", p.Package.HumanReadableString(), "installed with failures (force install)")
|
||||||
@@ -361,7 +443,15 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
|
|||||||
// Remove from target
|
// Remove from target
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
target := filepath.Join(s.Target, f)
|
target := filepath.Join(s.Target, f)
|
||||||
Info("Removing", target)
|
Debug("Removing", target)
|
||||||
|
|
||||||
|
if l.Options.PreserveSystemEssentialData &&
|
||||||
|
strings.HasPrefix(f, config.LuetCfg.GetSystem().GetSystemPkgsCacheDirPath()) ||
|
||||||
|
strings.HasPrefix(f, config.LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath()) {
|
||||||
|
Warning("Preserve ", f, " which is required by luet ( you have to delete it manually if you really need to)")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
err := os.Remove(target)
|
err := os.Remove(target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warning("Failed removing file (not present in the system target ?)", target)
|
Warning("Failed removing file (not present in the system target ?)", target)
|
||||||
@@ -381,12 +471,17 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *LuetInstaller) Uninstall(p pkg.Package, s *System) error {
|
func (l *LuetInstaller) Uninstall(p pkg.Package, s *System) error {
|
||||||
// compute uninstall from all world - remove packages in parallel - run uninstall finalizer (in order) - mark the uninstallation in db
|
// compute uninstall from all world - remove packages in parallel - run uninstall finalizer (in order) TODO - mark the uninstallation in db
|
||||||
// Get installed definition
|
// Get installed definition
|
||||||
|
|
||||||
|
checkConflicts := true
|
||||||
|
if l.Options.Force == true {
|
||||||
|
checkConflicts = false
|
||||||
|
}
|
||||||
|
|
||||||
if !l.Options.NoDeps {
|
if !l.Options.NoDeps {
|
||||||
solv := solver.NewResolver(s.Database, s.Database, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver())
|
solv := solver.NewResolver(s.Database, s.Database, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver())
|
||||||
solution, err := solv.Uninstall(p)
|
solution, err := solv.Uninstall(p, checkConflicts)
|
||||||
if err != nil && !l.Options.Force {
|
if err != nil && !l.Options.Force {
|
||||||
return errors.Wrap(err, "Could not solve the uninstall constraints. Tip: try with --solver-type qlearning or with --force, or by removing packages excluding their dependencies with --nodeps")
|
return errors.Wrap(err, "Could not solve the uninstall constraints. Tip: try with --solver-type qlearning or with --force, or by removing packages excluding their dependencies with --nodeps")
|
||||||
}
|
}
|
||||||
|
@@ -113,7 +113,7 @@ urls:
|
|||||||
Expect(repo.GetType()).To(Equal("disk"))
|
Expect(repo.GetType()).To(Equal("disk"))
|
||||||
systemDB := pkg.NewInMemoryDatabase(false)
|
systemDB := pkg.NewInMemoryDatabase(false)
|
||||||
system := &System{Database: systemDB, Target: fakeroot}
|
system := &System{Database: systemDB, Target: fakeroot}
|
||||||
err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system)
|
err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system, false)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(helpers.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue())
|
Expect(helpers.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue())
|
||||||
@@ -231,7 +231,7 @@ urls:
|
|||||||
|
|
||||||
systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db"))
|
systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db"))
|
||||||
system := &System{Database: systemDB, Target: fakeroot}
|
system := &System{Database: systemDB, Target: fakeroot}
|
||||||
err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system)
|
err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system, false)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(helpers.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue())
|
Expect(helpers.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue())
|
||||||
@@ -339,7 +339,7 @@ urls:
|
|||||||
|
|
||||||
systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db"))
|
systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db"))
|
||||||
system := &System{Database: systemDB, Target: fakeroot}
|
system := &System{Database: systemDB, Target: fakeroot}
|
||||||
err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system)
|
err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system, false)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(helpers.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue())
|
Expect(helpers.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue())
|
||||||
@@ -454,7 +454,7 @@ urls:
|
|||||||
|
|
||||||
systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db"))
|
systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db"))
|
||||||
system := &System{Database: systemDB, Target: fakeroot}
|
system := &System{Database: systemDB, Target: fakeroot}
|
||||||
err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system)
|
err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system, false)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(helpers.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue())
|
Expect(helpers.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue())
|
||||||
|
@@ -23,11 +23,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Installer interface {
|
type Installer interface {
|
||||||
Install([]pkg.Package, *System) error
|
Install([]pkg.Package, *System, bool) error
|
||||||
Uninstall(pkg.Package, *System) error
|
Uninstall(pkg.Package, *System) error
|
||||||
Upgrade(s *System) error
|
Upgrade(s *System) error
|
||||||
Repositories([]Repository)
|
Repositories([]Repository)
|
||||||
SyncRepositories(bool) (Repositories, error)
|
SyncRepositories(bool) (Repositories, error)
|
||||||
|
Swap([]pkg.Package, []pkg.Package, *System) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
|
@@ -468,6 +468,22 @@ func (pack *DefaultPackage) BuildFormula(definitiondb PackageDatabase, db Packag
|
|||||||
A := bf.Var(encodedA)
|
A := bf.Var(encodedA)
|
||||||
|
|
||||||
var formulas []bf.Formula
|
var formulas []bf.Formula
|
||||||
|
|
||||||
|
// Do conflict with other packages versions (if A is selected, then conflict with other versions of A)
|
||||||
|
packages, _ := definitiondb.FindPackageVersions(p)
|
||||||
|
if len(packages) > 0 {
|
||||||
|
for _, cp := range packages {
|
||||||
|
encodedB, err := cp.Encode(db)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
B := bf.Var(encodedB)
|
||||||
|
if !p.Matches(cp) {
|
||||||
|
formulas = append(formulas, bf.Or(bf.Not(A), bf.Or(bf.Not(A), bf.Not(B))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, requiredDef := range p.GetRequires() {
|
for _, requiredDef := range p.GetRequires() {
|
||||||
required, err := definitiondb.FindPackage(requiredDef)
|
required, err := definitiondb.FindPackage(requiredDef)
|
||||||
if err != nil || requiredDef.IsSelector() {
|
if err != nil || requiredDef.IsSelector() {
|
||||||
@@ -479,62 +495,60 @@ func (pack *DefaultPackage) BuildFormula(definitiondb PackageDatabase, db Packag
|
|||||||
if err != nil || len(packages) == 0 {
|
if err != nil || len(packages) == 0 {
|
||||||
required = requiredDef
|
required = requiredDef
|
||||||
} else {
|
} else {
|
||||||
if len(packages) == 1 {
|
|
||||||
required = packages[0]
|
|
||||||
} else {
|
|
||||||
var ALO, priorityConstraints, priorityALO []bf.Formula
|
|
||||||
|
|
||||||
// Try to prio best match
|
var ALO, priorityConstraints, priorityALO []bf.Formula
|
||||||
// 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.Or(C, bf.Or(priorityConstraints...)), bf.Or(bf.Not(C), bf.Or(priorityALO...))))
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMO - At most one
|
// 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 {
|
for _, o := range packages {
|
||||||
encodedB, err := o.Encode(db)
|
encodedB, err := o.Encode(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
B := bf.Var(encodedB)
|
B := bf.Var(encodedB)
|
||||||
ALO = append(ALO, B)
|
if !o.Matches(c) {
|
||||||
for _, i := range packages {
|
priorityConstraints = append(priorityConstraints, bf.Not(B))
|
||||||
encodedI, err := i.Encode(db)
|
priorityALO = append(priorityALO, B)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
I := bf.Var(encodedI)
|
|
||||||
if !o.Matches(i) {
|
|
||||||
formulas = append(formulas, bf.Or(bf.Not(I), bf.Not(B)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formulas = append(formulas, bf.Or(ALO...)) // ALO - At least one
|
encodedC, err := c.Encode(db)
|
||||||
continue
|
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.Or(C, bf.Or(priorityConstraints...)), bf.Or(bf.Not(C), bf.Or(priorityALO...)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AMO - At most one
|
||||||
|
for _, o := range packages {
|
||||||
|
encodedB, err := o.Encode(db)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
B := bf.Var(encodedB)
|
||||||
|
ALO = append(ALO, B)
|
||||||
|
for _, i := range packages {
|
||||||
|
encodedI, err := i.Encode(db)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
I := bf.Var(encodedI)
|
||||||
|
if !o.Matches(i) {
|
||||||
|
formulas = append(formulas, bf.Or(bf.Not(A), bf.Or(bf.Not(I), bf.Not(B))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
formulas = append(formulas, bf.Or(bf.Not(A), bf.Or(ALO...))) // ALO - At least one
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
encodedB, err := required.Encode(db)
|
encodedB, err := required.Encode(db)
|
||||||
@@ -600,6 +614,7 @@ func (pack *DefaultPackage) BuildFormula(definitiondb PackageDatabase, db Packag
|
|||||||
formulas = append(formulas, f...)
|
formulas = append(formulas, f...)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return formulas, nil
|
return formulas, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -211,7 +211,7 @@ var _ = Describe("Package", func() {
|
|||||||
|
|
||||||
f, err := a1.BuildFormula(definitions, db)
|
f, err := a1.BuildFormula(definitions, db)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(len(f)).To(Equal(2))
|
Expect(len(f)).To(Equal(8))
|
||||||
// Expect(f[0].String()).To(Equal("or(not(c31f5842), a4910f77)"))
|
// Expect(f[0].String()).To(Equal("or(not(c31f5842), a4910f77)"))
|
||||||
// Expect(f[1].String()).To(Equal("or(not(c31f5842), not(a97670be))"))
|
// Expect(f[1].String()).To(Equal("or(not(c31f5842), not(a97670be))"))
|
||||||
})
|
})
|
||||||
|
@@ -28,11 +28,11 @@ import (
|
|||||||
type PackageSolver interface {
|
type PackageSolver interface {
|
||||||
SetDefinitionDatabase(pkg.PackageDatabase)
|
SetDefinitionDatabase(pkg.PackageDatabase)
|
||||||
Install(p []pkg.Package) (PackagesAssertions, error)
|
Install(p []pkg.Package) (PackagesAssertions, error)
|
||||||
Uninstall(candidate pkg.Package) ([]pkg.Package, error)
|
Uninstall(candidate pkg.Package, checkconflicts bool) ([]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)
|
||||||
World() []pkg.Package
|
World() []pkg.Package
|
||||||
Upgrade() ([]pkg.Package, PackagesAssertions, error)
|
Upgrade(checkconflicts bool) ([]pkg.Package, PackagesAssertions, error)
|
||||||
|
|
||||||
SetResolver(PackageResolver)
|
SetResolver(PackageResolver)
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ func (s *Solver) ConflictsWithInstalled(p pkg.Package) (bool, error) {
|
|||||||
return s.ConflictsWith(p, s.Installed())
|
return s.ConflictsWith(p, s.Installed())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Solver) Upgrade() ([]pkg.Package, PackagesAssertions, error) {
|
func (s *Solver) Upgrade(checkconflicts bool) ([]pkg.Package, PackagesAssertions, error) {
|
||||||
|
|
||||||
// First get candidates that needs to be upgraded..
|
// First get candidates that needs to be upgraded..
|
||||||
|
|
||||||
@@ -236,12 +236,11 @@ func (s *Solver) Upgrade() ([]pkg.Package, PackagesAssertions, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s2 := NewSolver(installedcopy, s.DefinitionDatabase, pkg.NewInMemoryDatabase(false))
|
s2 := NewSolver(installedcopy, s.DefinitionDatabase, pkg.NewInMemoryDatabase(false))
|
||||||
s2.SetResolver(s.Resolver)
|
s2.SetResolver(s.Resolver)
|
||||||
// Then try to uninstall the versions in the system, and store that tree
|
// Then try to uninstall the versions in the system, and store that tree
|
||||||
for _, p := range toUninstall {
|
for _, p := range toUninstall {
|
||||||
r, err := s.Uninstall(p)
|
r, err := s.Uninstall(p, checkconflicts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't uninstall selected candidate "+p.GetFingerPrint())
|
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't uninstall selected candidate "+p.GetFingerPrint())
|
||||||
}
|
}
|
||||||
@@ -262,7 +261,7 @@ func (s *Solver) Upgrade() ([]pkg.Package, PackagesAssertions, error) {
|
|||||||
|
|
||||||
// Uninstall takes a candidate package and return a list of packages that would be removed
|
// 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.
|
// in order to purge the candidate. Returns error if unsat.
|
||||||
func (s *Solver) Uninstall(c pkg.Package) ([]pkg.Package, error) {
|
func (s *Solver) Uninstall(c pkg.Package, checkconflicts bool) ([]pkg.Package, error) {
|
||||||
var res []pkg.Package
|
var res []pkg.Package
|
||||||
candidate, err := s.InstalledDatabase.FindPackage(c)
|
candidate, err := s.InstalledDatabase.FindPackage(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -294,17 +293,19 @@ func (s *Solver) Uninstall(c pkg.Package) ([]pkg.Package, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s2 := NewSolver(pkg.NewInMemoryDatabase(false), s.DefinitionDatabase, pkg.NewInMemoryDatabase(false))
|
||||||
|
s2.SetResolver(s.Resolver)
|
||||||
// Get the requirements to install the candidate
|
// Get the requirements to install the candidate
|
||||||
saved := s.InstalledDatabase
|
asserts, err := s2.Install([]pkg.Package{candidate})
|
||||||
s.InstalledDatabase = pkg.NewInMemoryDatabase(false)
|
|
||||||
asserts, err := s.Install([]pkg.Package{candidate})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
s.InstalledDatabase = saved
|
|
||||||
|
|
||||||
for _, a := range asserts {
|
for _, a := range asserts {
|
||||||
if a.Value {
|
if a.Value {
|
||||||
|
if !checkconflicts {
|
||||||
|
res = append(res, a.Package.IsFlagged(false))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
c, err := s.ConflictsWithInstalled(a.Package)
|
c, err := s.ConflictsWithInstalled(a.Package)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -429,7 +429,7 @@ var _ = Describe("Solver", func() {
|
|||||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
||||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||||
|
|
||||||
Expect(len(solution)).To(Equal(5))
|
Expect(len(solution)).To(Equal(6))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -470,7 +470,7 @@ var _ = Describe("Solver", func() {
|
|||||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
||||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||||
|
|
||||||
Expect(len(solution)).To(Equal(4))
|
Expect(len(solution)).To(Equal(6))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -511,7 +511,7 @@ var _ = Describe("Solver", func() {
|
|||||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
||||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||||
|
|
||||||
Expect(len(solution)).To(Equal(4))
|
Expect(len(solution)).To(Equal(6))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -533,7 +533,7 @@ var _ = Describe("Solver", func() {
|
|||||||
}
|
}
|
||||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||||
|
|
||||||
solution, err := s.Uninstall(A)
|
solution, err := s.Uninstall(A, true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||||
@@ -559,7 +559,7 @@ var _ = Describe("Solver", func() {
|
|||||||
}
|
}
|
||||||
s = NewSolver(dbInstalled, dbDefinitions, db)
|
s = NewSolver(dbInstalled, dbDefinitions, db)
|
||||||
|
|
||||||
solution, err := s.Uninstall(&pkg.DefaultPackage{Name: "A", Version: ">1.0"})
|
solution, err := s.Uninstall(&pkg.DefaultPackage{Name: "A", Version: ">1.0"}, true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||||
@@ -674,7 +674,7 @@ var _ = Describe("Solver", func() {
|
|||||||
_, err := dbInstalled.CreatePackage(p)
|
_, err := dbInstalled.CreatePackage(p)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
solution, err := s.Uninstall(A)
|
solution, err := s.Uninstall(A, true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||||
@@ -698,7 +698,7 @@ var _ = Describe("Solver", func() {
|
|||||||
_, err := dbInstalled.CreatePackage(p)
|
_, err := dbInstalled.CreatePackage(p)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
solution, err := s.Uninstall(A)
|
solution, err := s.Uninstall(A, true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||||
@@ -721,7 +721,7 @@ var _ = Describe("Solver", func() {
|
|||||||
_, err := dbInstalled.CreatePackage(p)
|
_, err := dbInstalled.CreatePackage(p)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
solution, err := s.Uninstall(A)
|
solution, err := s.Uninstall(A, true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||||
@@ -746,7 +746,7 @@ var _ = Describe("Solver", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
|
|
||||||
solution, err := s.Uninstall(A)
|
solution, err := s.Uninstall(A, true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||||
@@ -772,7 +772,7 @@ var _ = Describe("Solver", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
|
|
||||||
solution, err := s.Uninstall(A)
|
solution, err := s.Uninstall(A, true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
Expect(solution).To(ContainElement(A.IsFlagged(false)))
|
||||||
@@ -893,7 +893,7 @@ var _ = Describe("Solver", func() {
|
|||||||
_, err := dbInstalled.CreatePackage(p)
|
_, err := dbInstalled.CreatePackage(p)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
uninstall, solution, err := s.Upgrade()
|
uninstall, solution, err := s.Upgrade(true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(len(uninstall)).To(Equal(1))
|
Expect(len(uninstall)).To(Equal(1))
|
||||||
|
10
tests/fixtures/upgrade_integration/c/build.yaml
vendored
Normal file
10
tests/fixtures/upgrade_integration/c/build.yaml
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
prelude:
|
||||||
|
- echo foo > /test
|
||||||
|
- echo bar > /test2
|
||||||
|
steps:
|
||||||
|
- echo c > /c
|
||||||
|
- echo c > /cd
|
||||||
|
requires:
|
||||||
|
- category: "test"
|
||||||
|
name: "a"
|
||||||
|
version: ">=1.0"
|
9
tests/fixtures/upgrade_integration/c/definition.yaml
vendored
Normal file
9
tests/fixtures/upgrade_integration/c/definition.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
category: "test"
|
||||||
|
name: "c"
|
||||||
|
version: "1.0"
|
||||||
|
# Boom?
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- category: "test"
|
||||||
|
name: "a"
|
||||||
|
version: ">=0.1"
|
11
tests/fixtures/upgrade_integration/cat/a/a/build.yaml
vendored
Normal file
11
tests/fixtures/upgrade_integration/cat/a/a/build.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
image: "alpine"
|
||||||
|
prelude:
|
||||||
|
- echo foo > /test
|
||||||
|
- echo bar > /test2
|
||||||
|
steps:
|
||||||
|
- echo artifact3 > /test3
|
||||||
|
- echo artifact4 > /test4
|
||||||
|
requires:
|
||||||
|
- category: "test"
|
||||||
|
name: "b"
|
||||||
|
version: "1.0"
|
8
tests/fixtures/upgrade_integration/cat/a/a/definition.yaml
vendored
Normal file
8
tests/fixtures/upgrade_integration/cat/a/a/definition.yaml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
category: "test"
|
||||||
|
name: "a"
|
||||||
|
version: "1.1"
|
||||||
|
requires:
|
||||||
|
- category: "test"
|
||||||
|
name: "b"
|
||||||
|
version: ">=0.1"
|
||||||
|
|
11
tests/fixtures/upgrade_integration/cat/a/a1.0/build.yaml
vendored
Normal file
11
tests/fixtures/upgrade_integration/cat/a/a1.0/build.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
image: "alpine"
|
||||||
|
prelude:
|
||||||
|
- echo foo > /test
|
||||||
|
- echo bar > /test2
|
||||||
|
steps:
|
||||||
|
- echo artifact3 > /testaa
|
||||||
|
- echo artifact4 > /testaa2
|
||||||
|
requires:
|
||||||
|
- category: "test"
|
||||||
|
name: "b"
|
||||||
|
version: "1.0"
|
3
tests/fixtures/upgrade_integration/cat/a/a1.0/definition.yaml
vendored
Normal file
3
tests/fixtures/upgrade_integration/cat/a/a1.0/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
category: "test"
|
||||||
|
name: "a"
|
||||||
|
version: "1.0"
|
11
tests/fixtures/upgrade_integration/cat/a/alatest/build.yaml
vendored
Normal file
11
tests/fixtures/upgrade_integration/cat/a/alatest/build.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
image: "alpine"
|
||||||
|
prelude:
|
||||||
|
- echo foo > /test
|
||||||
|
- echo bar > /test2
|
||||||
|
steps:
|
||||||
|
- echo artifact3 > /testlatest
|
||||||
|
- echo artifact4 > /testlatest2
|
||||||
|
requires:
|
||||||
|
- category: "test"
|
||||||
|
name: "b"
|
||||||
|
version: "1.0"
|
3
tests/fixtures/upgrade_integration/cat/a/alatest/definition.yaml
vendored
Normal file
3
tests/fixtures/upgrade_integration/cat/a/alatest/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
category: "test"
|
||||||
|
name: "a"
|
||||||
|
version: "1.2"
|
9
tests/fixtures/upgrade_integration/cat/b-1.1/build.yaml
vendored
Normal file
9
tests/fixtures/upgrade_integration/cat/b-1.1/build.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
image: "alpine"
|
||||||
|
prelude:
|
||||||
|
- echo foo > /test
|
||||||
|
- echo bar > /test2
|
||||||
|
- chmod +x generate.sh
|
||||||
|
steps:
|
||||||
|
- echo artifact5 > /newc
|
||||||
|
- echo artifact6 > /newnewc
|
||||||
|
- ./generate.sh
|
3
tests/fixtures/upgrade_integration/cat/b-1.1/definition.yaml
vendored
Normal file
3
tests/fixtures/upgrade_integration/cat/b-1.1/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
category: "test"
|
||||||
|
name: "b"
|
||||||
|
version: "1.1"
|
1
tests/fixtures/upgrade_integration/cat/b-1.1/generate.sh
vendored
Normal file
1
tests/fixtures/upgrade_integration/cat/b-1.1/generate.sh
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
echo generated > /sonewc
|
9
tests/fixtures/upgrade_integration/cat/b/build.yaml
vendored
Normal file
9
tests/fixtures/upgrade_integration/cat/b/build.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
image: "alpine"
|
||||||
|
prelude:
|
||||||
|
- echo foo > /test
|
||||||
|
- echo bar > /test2
|
||||||
|
- chmod +x generate.sh
|
||||||
|
steps:
|
||||||
|
- echo artifact5 > /test5
|
||||||
|
- echo artifact6 > /test6
|
||||||
|
- ./generate.sh
|
3
tests/fixtures/upgrade_integration/cat/b/definition.yaml
vendored
Normal file
3
tests/fixtures/upgrade_integration/cat/b/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
category: "test"
|
||||||
|
name: "b"
|
||||||
|
version: "1.0"
|
1
tests/fixtures/upgrade_integration/cat/b/generate.sh
vendored
Normal file
1
tests/fixtures/upgrade_integration/cat/b/generate.sh
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
echo generated > /artifact42
|
@@ -12,7 +12,7 @@ oneTimeTearDown() {
|
|||||||
|
|
||||||
testBuild() {
|
testBuild() {
|
||||||
mkdir $tmpdir/testbuild
|
mkdir $tmpdir/testbuild
|
||||||
luet build --all --tree "$ROOT_DIR/tests/fixtures/qlearning" --destination $tmpdir/testbuild --compression gzip
|
luet build --all --concurrency 1 --tree "$ROOT_DIR/tests/fixtures/qlearning" --destination $tmpdir/testbuild --compression gzip
|
||||||
buildst=$?
|
buildst=$?
|
||||||
assertEquals 'builds successfully' "$buildst" "0"
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
assertTrue 'create package dep B' "[ -e '$tmpdir/testbuild/b-test-1.0.package.tar.gz' ]"
|
assertTrue 'create package dep B' "[ -e '$tmpdir/testbuild/b-test-1.0.package.tar.gz' ]"
|
||||||
|
122
tests/integration/05_upgrade.sh
Executable file
122
tests/integration/05_upgrade.sh
Executable file
@@ -0,0 +1,122 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LUET_NOLOCK=true
|
||||||
|
|
||||||
|
oneTimeSetUp() {
|
||||||
|
export tmpdir="$(mktemp -d)"
|
||||||
|
}
|
||||||
|
|
||||||
|
oneTimeTearDown() {
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
}
|
||||||
|
|
||||||
|
testBuild() {
|
||||||
|
mkdir $tmpdir/testbuild
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/b-1.0
|
||||||
|
buildst=$?
|
||||||
|
assertTrue 'create package B 1.0' "[ -e '$tmpdir/testbuild/b-test-1.0.package.tar.gz' ]"
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/b-1.1
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
assertTrue 'create package B 1.1' "[ -e '$tmpdir/testbuild/b-test-1.1.package.tar.gz' ]"
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/a-1.0
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
assertTrue 'create package A 1.0' "[ -e '$tmpdir/testbuild/a-test-1.0.package.tar.gz' ]"
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/a-1.1
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
|
||||||
|
assertTrue 'create package A 1.1' "[ -e '$tmpdir/testbuild/a-test-1.1.package.tar.gz' ]"
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/a-1.2
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
|
||||||
|
assertTrue 'create package A 1.2' "[ -e '$tmpdir/testbuild/a-test-1.2.package.tar.gz' ]"
|
||||||
|
|
||||||
|
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" --destination $tmpdir/testbuild --compression gzip test/c-1.0
|
||||||
|
buildst=$?
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
assertTrue 'create package C 1.0' "[ -e '$tmpdir/testbuild/c-test-1.0.package.tar.gz' ]"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
testRepo() {
|
||||||
|
assertTrue 'no repository' "[ ! -e '$tmpdir/testbuild/repository.yaml' ]"
|
||||||
|
luet create-repo --tree "$ROOT_DIR/tests/fixtures/upgrade_integration" \
|
||||||
|
--output $tmpdir/testbuild \
|
||||||
|
--packages $tmpdir/testbuild \
|
||||||
|
--name "test" \
|
||||||
|
--descr "Test Repo" \
|
||||||
|
--urls $tmpdir/testrootfs \
|
||||||
|
--type disk
|
||||||
|
|
||||||
|
createst=$?
|
||||||
|
assertEquals 'create repo successfully' "$createst" "0"
|
||||||
|
assertTrue 'create repository' "[ -e '$tmpdir/testbuild/repository.yaml' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testConfig() {
|
||||||
|
mkdir $tmpdir/testrootfs
|
||||||
|
cat <<EOF > $tmpdir/luet.yaml
|
||||||
|
general:
|
||||||
|
debug: true
|
||||||
|
system:
|
||||||
|
rootfs: $tmpdir/testrootfs
|
||||||
|
database_path: "/"
|
||||||
|
database_engine: "boltdb"
|
||||||
|
repositories:
|
||||||
|
- name: "main"
|
||||||
|
type: "disk"
|
||||||
|
enable: true
|
||||||
|
urls:
|
||||||
|
- "$tmpdir/testbuild"
|
||||||
|
EOF
|
||||||
|
luet config --config $tmpdir/luet.yaml
|
||||||
|
res=$?
|
||||||
|
assertEquals 'config test successfully' "$res" "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
testInstall() {
|
||||||
|
luet install --config $tmpdir/luet.yaml test/b-1.0
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package installed B' "[ -e '$tmpdir/testrootfs/test5' ]"
|
||||||
|
|
||||||
|
luet install --config $tmpdir/luet.yaml test/a-1.0
|
||||||
|
assertTrue 'package installed A' "[ -e '$tmpdir/testrootfs/testaa' ]"
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
|
||||||
|
luet install --config $tmpdir/luet.yaml test/a-1.1
|
||||||
|
assertTrue 'package installed A' "[ -e '$tmpdir/testrootfs/testaa' ]"
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package keeps old A' "[ -e '$tmpdir/testrootfs/testaa' ]"
|
||||||
|
assertTrue 'package new A was not installed' "[ ! -e '$tmpdir/testrootfs/testlatest' ]"
|
||||||
|
|
||||||
|
luet install --config $tmpdir/luet.yaml test/c-1.0
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package installed C' "[ -e '$tmpdir/testrootfs/c' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
testUpgrade() {
|
||||||
|
luet --config $tmpdir/luet.yaml upgrade
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'install test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package uninstalled B' "[ ! -e '$tmpdir/testrootfs/test5' ]"
|
||||||
|
assertTrue 'package installed B' "[ -e '$tmpdir/testrootfs/newc' ]"
|
||||||
|
assertTrue 'package uninstalled A' "[ ! -e '$tmpdir/testrootfs/testaa' ]"
|
||||||
|
assertTrue 'package installed new A' "[ -e '$tmpdir/testrootfs/testlatest' ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load shUnit2.
|
||||||
|
. "$ROOT_DIR/tests/integration/shunit2"/shunit2
|
||||||
|
|
Reference in New Issue
Block a user