mirror of
https://github.com/mudler/luet.git
synced 2025-09-05 01:00:44 +00:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ffa6fc3829 | ||
|
07a1058ac1 | ||
|
3af9109b99 | ||
|
6e3650d3af | ||
|
5dcf77c987 | ||
|
ee0e70ed3d | ||
|
364b5648b4 | ||
|
e28a4753f8 | ||
|
d1d7f5aa74 | ||
|
e2260b6956 |
@@ -79,6 +79,7 @@ var buildCmd = &cobra.Command{
|
|||||||
onlydeps := viper.GetBool("onlydeps")
|
onlydeps := viper.GetBool("onlydeps")
|
||||||
keepExportedImages := viper.GetBool("keep-exported-images")
|
keepExportedImages := viper.GetBool("keep-exported-images")
|
||||||
full, _ := cmd.Flags().GetBool("full")
|
full, _ := cmd.Flags().GetBool("full")
|
||||||
|
skip, _ := cmd.Flags().GetBool("skip-if-metadata-exists")
|
||||||
|
|
||||||
compilerSpecs := compiler.NewLuetCompilationspecs()
|
compilerSpecs := compiler.NewLuetCompilationspecs()
|
||||||
var compilerBackend compiler.CompilerBackend
|
var compilerBackend compiler.CompilerBackend
|
||||||
@@ -143,6 +144,7 @@ var buildCmd = &cobra.Command{
|
|||||||
opts.OnlyDeps = onlydeps
|
opts.OnlyDeps = onlydeps
|
||||||
opts.NoDeps = nodeps
|
opts.NoDeps = nodeps
|
||||||
opts.KeepImageExport = keepExportedImages
|
opts.KeepImageExport = keepExportedImages
|
||||||
|
opts.SkipIfMetadataExists = skip
|
||||||
|
|
||||||
luetCompiler := compiler.NewLuetCompiler(compilerBackend, generalRecipe.GetDatabase(), opts)
|
luetCompiler := compiler.NewLuetCompiler(compilerBackend, generalRecipe.GetDatabase(), opts)
|
||||||
luetCompiler.SetConcurrency(concurrency)
|
luetCompiler.SetConcurrency(concurrency)
|
||||||
@@ -231,6 +233,7 @@ func init() {
|
|||||||
buildCmd.Flags().Bool("nodeps", false, "Build only the target packages, skipping deps (it works only if you already built the deps locally, or by using --pull) ")
|
buildCmd.Flags().Bool("nodeps", false, "Build only the target packages, skipping deps (it works only if you already built the deps locally, or by using --pull) ")
|
||||||
buildCmd.Flags().Bool("onlydeps", false, "Build only package dependencies")
|
buildCmd.Flags().Bool("onlydeps", false, "Build only package dependencies")
|
||||||
buildCmd.Flags().Bool("keep-exported-images", false, "Keep exported images used during building")
|
buildCmd.Flags().Bool("keep-exported-images", false, "Keep exported images used during building")
|
||||||
|
buildCmd.Flags().Bool("skip-if-metadata-exists", false, "Skip package if metadata exists")
|
||||||
|
|
||||||
buildCmd.Flags().String("solver-type", "", "Solver strategy")
|
buildCmd.Flags().String("solver-type", "", "Solver strategy")
|
||||||
buildCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
buildCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
||||||
|
11
cmd/root.go
11
cmd/root.go
@@ -38,7 +38,7 @@ var Verbose bool
|
|||||||
var LockedCommands = []string{"install", "uninstall", "upgrade"}
|
var LockedCommands = []string{"install", "uninstall", "upgrade"}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LuetCLIVersion = "0.8.1"
|
LuetCLIVersion = "0.8.3"
|
||||||
LuetEnvPrefix = "LUET"
|
LuetEnvPrefix = "LUET"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -88,8 +88,12 @@ func LoadConfig(c *config.LuetConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
noSpinner := c.Viper.GetBool("no_spinner")
|
||||||
|
|
||||||
InitAurora()
|
InitAurora()
|
||||||
NewSpinner()
|
if !noSpinner {
|
||||||
|
NewSpinner()
|
||||||
|
}
|
||||||
|
|
||||||
Debug("Using config file:", c.Viper.ConfigFileUsed())
|
Debug("Using config file:", c.Viper.ConfigFileUsed())
|
||||||
|
|
||||||
@@ -145,6 +149,7 @@ func init() {
|
|||||||
pflags.BoolP("debug", "d", false, "verbose output")
|
pflags.BoolP("debug", "d", false, "verbose output")
|
||||||
pflags.Bool("fatal", false, "Enables Warnings to exit")
|
pflags.Bool("fatal", false, "Enables Warnings to exit")
|
||||||
pflags.Bool("enable-logfile", false, "Enable log to file")
|
pflags.Bool("enable-logfile", false, "Enable log to file")
|
||||||
|
pflags.Bool("no-spinner", false, "Disable spinner.")
|
||||||
pflags.Bool("color", config.LuetCfg.GetLogging().Color, "Enable/Disable color.")
|
pflags.Bool("color", config.LuetCfg.GetLogging().Color, "Enable/Disable color.")
|
||||||
pflags.Bool("emoji", config.LuetCfg.GetLogging().EnableEmoji, "Enable/Disable emoji.")
|
pflags.Bool("emoji", config.LuetCfg.GetLogging().EnableEmoji, "Enable/Disable emoji.")
|
||||||
pflags.StringP("logfile", "l", config.LuetCfg.GetLogging().Path,
|
pflags.StringP("logfile", "l", config.LuetCfg.GetLogging().Path,
|
||||||
@@ -168,6 +173,8 @@ func init() {
|
|||||||
config.LuetCfg.Viper.BindPFlag("general.debug", pflags.Lookup("debug"))
|
config.LuetCfg.Viper.BindPFlag("general.debug", pflags.Lookup("debug"))
|
||||||
config.LuetCfg.Viper.BindPFlag("general.fatal_warnings", pflags.Lookup("fatal"))
|
config.LuetCfg.Viper.BindPFlag("general.fatal_warnings", pflags.Lookup("fatal"))
|
||||||
config.LuetCfg.Viper.BindPFlag("general.same_owner", pflags.Lookup("same-owner"))
|
config.LuetCfg.Viper.BindPFlag("general.same_owner", pflags.Lookup("same-owner"))
|
||||||
|
// Currently I maintain this only from cli.
|
||||||
|
config.LuetCfg.Viper.BindPFlag("no_spinner", pflags.Lookup("no-spinner"))
|
||||||
|
|
||||||
// Extensions must be binary with the "luet-" prefix to be able to be shown in the help.
|
// Extensions must be binary with the "luet-" prefix to be able to be shown in the help.
|
||||||
// we also accept extensions in the relative path where luet is being started, "extensions/"
|
// we also accept extensions in the relative path where luet is being started, "extensions/"
|
||||||
|
@@ -26,6 +26,7 @@ import (
|
|||||||
. "github.com/mudler/luet/pkg/config"
|
. "github.com/mudler/luet/pkg/config"
|
||||||
. "github.com/mudler/luet/pkg/logger"
|
. "github.com/mudler/luet/pkg/logger"
|
||||||
pkg "github.com/mudler/luet/pkg/package"
|
pkg "github.com/mudler/luet/pkg/package"
|
||||||
|
"github.com/mudler/luet/pkg/solver"
|
||||||
tree "github.com/mudler/luet/pkg/tree"
|
tree "github.com/mudler/luet/pkg/tree"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -74,15 +75,24 @@ func NewTreePkglistCommand() *cobra.Command {
|
|||||||
if len(t) == 0 {
|
if len(t) == 0 {
|
||||||
Fatal("Mandatory tree param missing.")
|
Fatal("Mandatory tree param missing.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
revdeps, _ := cmd.Flags().GetBool("revdeps")
|
||||||
|
deps, _ := cmd.Flags().GetBool("deps")
|
||||||
|
if revdeps && deps {
|
||||||
|
Fatal("Both revdeps and deps option used. Choice only one.")
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
var results TreeResults
|
var results TreeResults
|
||||||
|
var depSolver solver.PackageSolver
|
||||||
|
|
||||||
treePath, _ := cmd.Flags().GetStringArray("tree")
|
treePath, _ := cmd.Flags().GetStringArray("tree")
|
||||||
verbose, _ := cmd.Flags().GetBool("verbose")
|
verbose, _ := cmd.Flags().GetBool("verbose")
|
||||||
buildtime, _ := cmd.Flags().GetBool("buildtime")
|
buildtime, _ := cmd.Flags().GetBool("buildtime")
|
||||||
full, _ := cmd.Flags().GetBool("full")
|
full, _ := cmd.Flags().GetBool("full")
|
||||||
revdeps, _ := cmd.Flags().GetBool("revdeps")
|
revdeps, _ := cmd.Flags().GetBool("revdeps")
|
||||||
|
deps, _ := cmd.Flags().GetBool("deps")
|
||||||
|
|
||||||
out, _ := cmd.Flags().GetString("output")
|
out, _ := cmd.Flags().GetString("output")
|
||||||
if out != "terminal" {
|
if out != "terminal" {
|
||||||
@@ -95,6 +105,7 @@ func NewTreePkglistCommand() *cobra.Command {
|
|||||||
} else {
|
} else {
|
||||||
reciper = tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false))
|
reciper = tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range treePath {
|
for _, t := range treePath {
|
||||||
err := reciper.Load(t)
|
err := reciper.Load(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -102,6 +113,15 @@ func NewTreePkglistCommand() *cobra.Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if deps {
|
||||||
|
emptyInstallationDb := pkg.NewInMemoryDatabase(false)
|
||||||
|
|
||||||
|
depSolver = solver.NewSolver(pkg.NewInMemoryDatabase(false),
|
||||||
|
reciper.GetDatabase(),
|
||||||
|
emptyInstallationDb)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
regExcludes, err := helpers.CreateRegexArray(excludes)
|
regExcludes, err := helpers.CreateRegexArray(excludes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatal(err.Error())
|
Fatal(err.Error())
|
||||||
@@ -146,15 +166,8 @@ func NewTreePkglistCommand() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if addPkg {
|
if addPkg {
|
||||||
if !revdeps {
|
if revdeps {
|
||||||
plist = append(plist, pkgstr)
|
|
||||||
results.Packages = append(results.Packages, TreePackageResult{
|
|
||||||
Name: p.GetName(),
|
|
||||||
Version: p.GetVersion(),
|
|
||||||
Category: p.GetCategory(),
|
|
||||||
Path: p.GetPath(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
visited := make(map[string]interface{})
|
visited := make(map[string]interface{})
|
||||||
for _, revdep := range p.ExpandedRevdeps(reciper.GetDatabase(), visited) {
|
for _, revdep := range p.ExpandedRevdeps(reciper.GetDatabase(), visited) {
|
||||||
if full {
|
if full {
|
||||||
@@ -172,7 +185,58 @@ func NewTreePkglistCommand() *cobra.Command {
|
|||||||
Path: revdep.GetPath(),
|
Path: revdep.GetPath(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
} else if deps {
|
||||||
|
|
||||||
|
Spinner(32)
|
||||||
|
solution, err := depSolver.Install(pkg.Packages{p})
|
||||||
|
if err != nil {
|
||||||
|
Fatal(err.Error())
|
||||||
|
}
|
||||||
|
ass := solution.SearchByName(p.GetPackageName())
|
||||||
|
solution, err = solution.Order(reciper.GetDatabase(), ass.Package.GetFingerPrint())
|
||||||
|
if err != nil {
|
||||||
|
Fatal(err.Error())
|
||||||
|
}
|
||||||
|
SpinnerStop()
|
||||||
|
|
||||||
|
for _, pa := range solution {
|
||||||
|
|
||||||
|
if pa.Value {
|
||||||
|
// Exclude itself
|
||||||
|
if pa.Package.GetName() == p.GetName() && pa.Package.GetCategory() == p.GetCategory() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if full {
|
||||||
|
pkgstr = pkgDetail(pa.Package)
|
||||||
|
} else if verbose {
|
||||||
|
pkgstr = pa.Package.HumanReadableString()
|
||||||
|
} else {
|
||||||
|
pkgstr = fmt.Sprintf("%s/%s", pa.Package.GetCategory(), pa.Package.GetName())
|
||||||
|
}
|
||||||
|
plist = append(plist, pkgstr)
|
||||||
|
results.Packages = append(results.Packages, TreePackageResult{
|
||||||
|
Name: pa.Package.GetName(),
|
||||||
|
Version: pa.Package.GetVersion(),
|
||||||
|
Category: pa.Package.GetCategory(),
|
||||||
|
Path: pa.Package.GetPath(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
plist = append(plist, pkgstr)
|
||||||
|
results.Packages = append(results.Packages, TreePackageResult{
|
||||||
|
Name: p.GetName(),
|
||||||
|
Version: p.GetVersion(),
|
||||||
|
Category: p.GetCategory(),
|
||||||
|
Path: p.GetPath(),
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +256,9 @@ func NewTreePkglistCommand() *cobra.Command {
|
|||||||
}
|
}
|
||||||
fmt.Println(string(j2))
|
fmt.Println(string(j2))
|
||||||
default:
|
default:
|
||||||
sort.Strings(plist)
|
if !deps {
|
||||||
|
sort.Strings(plist)
|
||||||
|
}
|
||||||
for _, p := range plist {
|
for _, p := range plist {
|
||||||
fmt.Println(p)
|
fmt.Println(p)
|
||||||
}
|
}
|
||||||
@@ -204,6 +270,7 @@ func NewTreePkglistCommand() *cobra.Command {
|
|||||||
ans.Flags().BoolP("buildtime", "b", false, "Build time match")
|
ans.Flags().BoolP("buildtime", "b", false, "Build time match")
|
||||||
ans.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )")
|
ans.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )")
|
||||||
ans.Flags().Bool("revdeps", false, "Search package reverse dependencies")
|
ans.Flags().Bool("revdeps", false, "Search package reverse dependencies")
|
||||||
|
ans.Flags().Bool("deps", false, "Search package dependencies")
|
||||||
|
|
||||||
ans.Flags().BoolP("verbose", "v", false, "Add package version")
|
ans.Flags().BoolP("verbose", "v", false, "Add package version")
|
||||||
ans.Flags().BoolP("full", "f", false, "Show package detail")
|
ans.Flags().BoolP("full", "f", false, "Show package detail")
|
||||||
|
@@ -62,6 +62,7 @@ var upgradeCmd = &cobra.Command{
|
|||||||
full, _ := cmd.Flags().GetBool("full")
|
full, _ := cmd.Flags().GetBool("full")
|
||||||
universe, _ := cmd.Flags().GetBool("universe")
|
universe, _ := cmd.Flags().GetBool("universe")
|
||||||
clean, _ := cmd.Flags().GetBool("clean")
|
clean, _ := cmd.Flags().GetBool("clean")
|
||||||
|
sync, _ := cmd.Flags().GetBool("sync")
|
||||||
|
|
||||||
LuetCfg.GetSolverOptions().Type = stype
|
LuetCfg.GetSolverOptions().Type = stype
|
||||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||||
@@ -78,6 +79,7 @@ var upgradeCmd = &cobra.Command{
|
|||||||
NoDeps: nodeps,
|
NoDeps: nodeps,
|
||||||
SolverUpgrade: universe,
|
SolverUpgrade: universe,
|
||||||
RemoveUnavailableOnUpgrade: clean,
|
RemoveUnavailableOnUpgrade: clean,
|
||||||
|
UpgradeNewRevisions: sync,
|
||||||
})
|
})
|
||||||
inst.Repositories(repos)
|
inst.Repositories(repos)
|
||||||
_, err := inst.SyncRepositories(false)
|
_, err := inst.SyncRepositories(false)
|
||||||
@@ -115,6 +117,7 @@ func init() {
|
|||||||
upgradeCmd.Flags().Bool("full", true, "Attempts to remove as much packages as possible which aren't required (slow)")
|
upgradeCmd.Flags().Bool("full", true, "Attempts to remove as much packages as possible which aren't required (slow)")
|
||||||
upgradeCmd.Flags().Bool("universe", false, "Use ONLY the SAT solver to compute upgrades (experimental)")
|
upgradeCmd.Flags().Bool("universe", false, "Use ONLY the SAT solver to compute upgrades (experimental)")
|
||||||
upgradeCmd.Flags().Bool("clean", false, "Try to drop removed packages (experimental, only when --universe is enabled)")
|
upgradeCmd.Flags().Bool("clean", false, "Try to drop removed packages (experimental, only when --universe is enabled)")
|
||||||
|
upgradeCmd.Flags().Bool("sync", false, "Upgrade packages with new revisions (experimental)")
|
||||||
|
|
||||||
RootCmd.AddCommand(upgradeCmd)
|
RootCmd.AddCommand(upgradeCmd)
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/mudler/luet/pkg/helpers"
|
"github.com/mudler/luet/pkg/helpers"
|
||||||
. "github.com/mudler/luet/pkg/logger"
|
. "github.com/mudler/luet/pkg/logger"
|
||||||
@@ -255,7 +256,7 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
|
|||||||
|
|
||||||
if !cs.Clean {
|
if !cs.Clean {
|
||||||
exists := cs.Backend.ImageExists(buildertaggedImage) && cs.Backend.ImageExists(packageImage)
|
exists := cs.Backend.ImageExists(buildertaggedImage) && cs.Backend.ImageExists(packageImage)
|
||||||
if art, err := LoadArtifactFromYaml(p); err == nil && exists {
|
if art, err := LoadArtifactFromYaml(p); err == nil && (cs.Options.SkipIfMetadataExists || exists) {
|
||||||
Debug("Artifact reloaded. Skipping build")
|
Debug("Artifact reloaded. Skipping build")
|
||||||
return art, err
|
return art, err
|
||||||
}
|
}
|
||||||
@@ -455,6 +456,8 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
|
|||||||
|
|
||||||
artifact.SetFiles(filelist)
|
artifact.SetFiles(filelist)
|
||||||
|
|
||||||
|
artifact.GetCompileSpec().GetPackage().SetBuildTimestamp(time.Now().String())
|
||||||
|
|
||||||
err = artifact.WriteYaml(p.GetOutputPath())
|
err = artifact.WriteYaml(p.GetOutputPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return artifact, errors.Wrap(err, "Failed while writing metadata file")
|
return artifact, errors.Wrap(err, "Failed while writing metadata file")
|
||||||
|
@@ -52,9 +52,10 @@ type CompilerOptions struct {
|
|||||||
Clean bool
|
Clean bool
|
||||||
KeepImageExport bool
|
KeepImageExport bool
|
||||||
|
|
||||||
OnlyDeps bool
|
OnlyDeps bool
|
||||||
NoDeps bool
|
NoDeps bool
|
||||||
SolverOptions config.LuetSolverOptions
|
SolverOptions config.LuetSolverOptions
|
||||||
|
SkipIfMetadataExists bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultCompilerOptions() *CompilerOptions {
|
func NewDefaultCompilerOptions() *CompilerOptions {
|
||||||
|
@@ -36,15 +36,15 @@ 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
|
PreserveSystemEssentialData bool
|
||||||
FullUninstall, FullCleanUninstall bool
|
FullUninstall, FullCleanUninstall bool
|
||||||
CheckConflicts bool
|
CheckConflicts bool
|
||||||
SolverUpgrade, RemoveUnavailableOnUpgrade bool
|
SolverUpgrade, RemoveUnavailableOnUpgrade, UpgradeNewRevisions bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type LuetInstaller struct {
|
type LuetInstaller struct {
|
||||||
@@ -90,12 +90,18 @@ func (l *LuetInstaller) Upgrade(s *System) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Info("Marked for uninstall")
|
if len(uninstall) > 0 {
|
||||||
|
Info("Packages marked for uninstall:")
|
||||||
|
}
|
||||||
|
|
||||||
for _, p := range uninstall {
|
for _, p := range uninstall {
|
||||||
Info(fmt.Sprintf("- %s", p.HumanReadableString()))
|
Info(fmt.Sprintf("- %s", p.HumanReadableString()))
|
||||||
}
|
}
|
||||||
|
|
||||||
Info("Marked for upgrade")
|
if len(solution) > 0 {
|
||||||
|
Info("Packages marked for upgrade:")
|
||||||
|
}
|
||||||
|
|
||||||
toInstall := pkg.Packages{}
|
toInstall := pkg.Packages{}
|
||||||
for _, assertion := range solution {
|
for _, assertion := range solution {
|
||||||
// Be sure to filter from solutions packages already installed in the system
|
// Be sure to filter from solutions packages already installed in the system
|
||||||
@@ -105,6 +111,37 @@ func (l *LuetInstaller) Upgrade(s *System) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if l.Options.UpgradeNewRevisions {
|
||||||
|
Info("Checking packages with new revisions available")
|
||||||
|
for _, p := range s.Database.World() {
|
||||||
|
matches := syncedRepos.PackageMatches(pkg.Packages{p})
|
||||||
|
if len(matches) == 0 {
|
||||||
|
// Package missing. the user should run luet upgrade --universe
|
||||||
|
Info("Installed packages seems to be missing from remote repositories.")
|
||||||
|
Info("It is suggested to run 'luet upgrade --universe'")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, artefact := range matches[0].Repo.GetIndex() {
|
||||||
|
if artefact.GetCompileSpec().GetPackage() == nil {
|
||||||
|
return errors.New("Package in compilespec empty")
|
||||||
|
|
||||||
|
}
|
||||||
|
if artefact.GetCompileSpec().GetPackage().Matches(p) && artefact.GetCompileSpec().GetPackage().GetBuildTimestamp() != p.GetBuildTimestamp() {
|
||||||
|
toInstall = append(toInstall, matches[0].Package).Unique()
|
||||||
|
uninstall = append(uninstall, p).Unique()
|
||||||
|
Info(
|
||||||
|
fmt.Sprintf("- %s ( %s vs %s ) repo: %s (date: %s)",
|
||||||
|
p.HumanReadableString(),
|
||||||
|
artefact.GetCompileSpec().GetPackage().GetBuildTimestamp(),
|
||||||
|
p.GetBuildTimestamp(),
|
||||||
|
matches[0].Repo.GetName(),
|
||||||
|
matches[0].Repo.GetLastUpdate(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return l.swap(syncedRepos, uninstall, toInstall, s)
|
return l.swap(syncedRepos, uninstall, toInstall, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,6 +386,7 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
|
|||||||
|
|
||||||
}
|
}
|
||||||
if matches[0].Package.Matches(artefact.GetCompileSpec().GetPackage()) {
|
if matches[0].Package.Matches(artefact.GetCompileSpec().GetPackage()) {
|
||||||
|
currentPack.SetBuildTimestamp(artefact.GetCompileSpec().GetPackage().GetBuildTimestamp())
|
||||||
// Filter out already installed
|
// Filter out already installed
|
||||||
if _, err := s.Database.FindPackage(currentPack); err != nil {
|
if _, err := s.Database.FindPackage(currentPack); err != nil {
|
||||||
toInstall[currentPack.GetFingerPrint()] = ArtifactMatch{Package: currentPack, Artifact: artefact, Repository: matches[0].Repo}
|
toInstall[currentPack.GetFingerPrint()] = ArtifactMatch{Package: currentPack, Artifact: artefact, Repository: matches[0].Repo}
|
||||||
|
@@ -78,23 +78,25 @@ func Spinner(i int) {
|
|||||||
i = 43
|
i = 43
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.Active() {
|
if s != nil && !s.Active() {
|
||||||
// s.UpdateCharSet(spinner.CharSets[i])
|
// s.UpdateCharSet(spinner.CharSets[i])
|
||||||
s.Start() // Start the spinner
|
s.Start() // Start the spinner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SpinnerText(suffix, prefix string) {
|
func SpinnerText(suffix, prefix string) {
|
||||||
s.Lock()
|
if s != nil {
|
||||||
defer s.Unlock()
|
s.Lock()
|
||||||
if LuetCfg.GetGeneral().Debug {
|
defer s.Unlock()
|
||||||
fmt.Println(fmt.Sprintf("%s %s",
|
if LuetCfg.GetGeneral().Debug {
|
||||||
Bold(Cyan(prefix)).String(),
|
fmt.Println(fmt.Sprintf("%s %s",
|
||||||
Bold(Magenta(suffix)).BgBlack().String(),
|
Bold(Cyan(prefix)).String(),
|
||||||
))
|
Bold(Magenta(suffix)).BgBlack().String(),
|
||||||
} else {
|
))
|
||||||
s.Suffix = Bold(Magenta(suffix)).BgBlack().String()
|
} else {
|
||||||
s.Prefix = Bold(Cyan(prefix)).String()
|
s.Suffix = Bold(Magenta(suffix)).BgBlack().String()
|
||||||
|
s.Prefix = Bold(Cyan(prefix)).String()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +110,9 @@ func SpinnerStop() {
|
|||||||
if 2 > confLevel {
|
if 2 > confLevel {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.Stop()
|
if s != nil {
|
||||||
|
s.Stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func level2Number(level string) int {
|
func level2Number(level string) int {
|
||||||
|
@@ -107,6 +107,9 @@ type Package interface {
|
|||||||
HumanReadableString() string
|
HumanReadableString() string
|
||||||
HashFingerprint(string) string
|
HashFingerprint(string) string
|
||||||
|
|
||||||
|
SetBuildTimestamp(s string)
|
||||||
|
GetBuildTimestamp() string
|
||||||
|
|
||||||
Clone() Package
|
Clone() Package
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,9 +173,10 @@ type DefaultPackage struct {
|
|||||||
// Path is set only internally when tree is loaded from disk
|
// Path is set only internally when tree is loaded from disk
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
|
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
Uri []string `json:"uri,omitempty"`
|
Uri []string `json:"uri,omitempty"`
|
||||||
License string `json:"license,omitempty"`
|
License string `json:"license,omitempty"`
|
||||||
|
BuildTimestamp string `json:"buildtimestamp,omitempty"`
|
||||||
|
|
||||||
Labels map[string]string `json:"labels,omitempty"` // Affects YAML field names too.
|
Labels map[string]string `json:"labels,omitempty"` // Affects YAML field names too.
|
||||||
}
|
}
|
||||||
@@ -207,7 +211,7 @@ func (p *DefaultPackage) GetFingerPrint() string {
|
|||||||
|
|
||||||
func (p *DefaultPackage) HashFingerprint(salt string) string {
|
func (p *DefaultPackage) HashFingerprint(salt string) string {
|
||||||
h := md5.New()
|
h := md5.New()
|
||||||
io.WriteString(h, fmt.Sprintf("%s-%s",p.GetFingerPrint(),salt))
|
io.WriteString(h, fmt.Sprintf("%s-%s", p.GetFingerPrint(), salt))
|
||||||
return fmt.Sprintf("%x", h.Sum(nil))
|
return fmt.Sprintf("%x", h.Sum(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,6 +233,16 @@ func (p *DefaultPackage) GetPackageName() string {
|
|||||||
return fmt.Sprintf("%s-%s", p.Name, p.Category)
|
return fmt.Sprintf("%s-%s", p.Name, p.Category)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetBuildTimestamp returns the package build timestamp
|
||||||
|
func (p *DefaultPackage) GetBuildTimestamp() string {
|
||||||
|
return p.BuildTimestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBuildTimestamp sets the package Build timestamp
|
||||||
|
func (p *DefaultPackage) SetBuildTimestamp(s string) {
|
||||||
|
p.BuildTimestamp = s
|
||||||
|
}
|
||||||
|
|
||||||
// GetPath returns the path where the definition file was found
|
// GetPath returns the path where the definition file was found
|
||||||
func (p *DefaultPackage) GetPath() string {
|
func (p *DefaultPackage) GetPath() string {
|
||||||
return p.Path
|
return p.Path
|
||||||
|
@@ -28,7 +28,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func LoadRepositories(c *LuetConfig) error {
|
func LoadRepositories(c *LuetConfig) error {
|
||||||
var regexRepo = regexp.MustCompile(`.yml$`)
|
var regexRepo = regexp.MustCompile(`.yml$|.yaml$`)
|
||||||
|
|
||||||
for _, rdir := range c.RepositoriesConfDir {
|
for _, rdir := range c.RepositoriesConfDir {
|
||||||
Debug("Parsing Repository Directory", rdir, "...")
|
Debug("Parsing Repository Directory", rdir, "...")
|
||||||
|
@@ -35,12 +35,22 @@ var _ = Describe("Repository", func() {
|
|||||||
|
|
||||||
It("Chec Load Repository 1", func() {
|
It("Chec Load Repository 1", func() {
|
||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
Expect(len(cfg.SystemRepositories)).Should(Equal(1))
|
Expect(len(cfg.SystemRepositories)).Should(Equal(2))
|
||||||
Expect(cfg.SystemRepositories[0].Name).Should(Equal("test1"))
|
Expect(cfg.SystemRepositories[0].Name).Should(Equal("test1"))
|
||||||
Expect(cfg.SystemRepositories[0].Priority).Should(Equal(999))
|
Expect(cfg.SystemRepositories[0].Priority).Should(Equal(999))
|
||||||
Expect(cfg.SystemRepositories[0].Type).Should(Equal("disk"))
|
Expect(cfg.SystemRepositories[0].Type).Should(Equal("disk"))
|
||||||
Expect(len(cfg.SystemRepositories[0].Urls)).Should(Equal(1))
|
Expect(len(cfg.SystemRepositories[0].Urls)).Should(Equal(1))
|
||||||
Expect(cfg.SystemRepositories[0].Urls[0]).Should(Equal("tests/repos/test1"))
|
Expect(cfg.SystemRepositories[0].Urls[0]).Should(Equal("tests/repos/test1"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Chec Load Repository 2", func() {
|
||||||
|
Expect(err).Should(BeNil())
|
||||||
|
Expect(len(cfg.SystemRepositories)).Should(Equal(2))
|
||||||
|
Expect(cfg.SystemRepositories[1].Name).Should(Equal("test2"))
|
||||||
|
Expect(cfg.SystemRepositories[1].Priority).Should(Equal(1000))
|
||||||
|
Expect(cfg.SystemRepositories[1].Type).Should(Equal("disk"))
|
||||||
|
Expect(len(cfg.SystemRepositories[1].Urls)).Should(Equal(1))
|
||||||
|
Expect(cfg.SystemRepositories[1].Urls[0]).Should(Equal("tests/repos/test2"))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
9
tests/fixtures/repos.conf.d/repo-test2.yaml
vendored
Normal file
9
tests/fixtures/repos.conf.d/repo-test2.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
name: "test2"
|
||||||
|
description: "Test2 Repository"
|
||||||
|
type: "disk"
|
||||||
|
urls:
|
||||||
|
- "tests/repos/test2"
|
||||||
|
priority: 1000
|
||||||
|
enable: true
|
||||||
|
# auth:
|
||||||
|
# token: "xxxxx"
|
10
tests/fixtures/upgrade_old_repo_revision/c/build.yaml
vendored
Normal file
10
tests/fixtures/upgrade_old_repo_revision/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"
|
3
tests/fixtures/upgrade_old_repo_revision/c/definition.yaml
vendored
Normal file
3
tests/fixtures/upgrade_old_repo_revision/c/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
category: "test"
|
||||||
|
name: "c"
|
||||||
|
version: "1.0"
|
11
tests/fixtures/upgrade_old_repo_revision/cat/a/a/build.yaml
vendored
Normal file
11
tests/fixtures/upgrade_old_repo_revision/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_old_repo_revision/cat/a/a/definition.yaml
vendored
Normal file
8
tests/fixtures/upgrade_old_repo_revision/cat/a/a/definition.yaml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
category: "test"
|
||||||
|
name: "a"
|
||||||
|
version: "1.1"
|
||||||
|
requires:
|
||||||
|
- category: "test2"
|
||||||
|
name: "b"
|
||||||
|
version: "1.0"
|
||||||
|
|
9
tests/fixtures/upgrade_old_repo_revision/cat/b-1.1/build.yaml
vendored
Normal file
9
tests/fixtures/upgrade_old_repo_revision/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_old_repo_revision/cat/b-1.1/definition.yaml
vendored
Normal file
3
tests/fixtures/upgrade_old_repo_revision/cat/b-1.1/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
category: "test"
|
||||||
|
name: "b"
|
||||||
|
version: "1.0"
|
1
tests/fixtures/upgrade_old_repo_revision/cat/b-1.1/generate.sh
vendored
Normal file
1
tests/fixtures/upgrade_old_repo_revision/cat/b-1.1/generate.sh
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
echo generated > /sonewc
|
116
tests/integration/14_upgrade_revision.sh
Executable file
116
tests/integration/14_upgrade_revision.sh
Executable file
@@ -0,0 +1,116 @@
|
|||||||
|
#!/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_old_repo" --destination $tmpdir/testbuild --compression gzip --full --clean=true
|
||||||
|
buildst=$?
|
||||||
|
assertTrue 'create package B 1.0' "[ -e '$tmpdir/testbuild/b-test-1.0.package.tar.gz' ]"
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
|
||||||
|
mkdir $tmpdir/testbuild_revision
|
||||||
|
luet build --tree "$ROOT_DIR/tests/fixtures/upgrade_old_repo_revision" --destination $tmpdir/testbuild_revision --compression gzip --full --clean=true
|
||||||
|
buildst=$?
|
||||||
|
assertTrue 'create package B 1.0' "[ -e '$tmpdir/testbuild_revision/b-test-1.0.package.tar.gz' ]"
|
||||||
|
assertEquals 'builds successfully' "$buildst" "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
testRepo() {
|
||||||
|
assertTrue 'no repository' "[ ! -e '$tmpdir/testbuild/repository.yaml' ]"
|
||||||
|
luet create-repo --tree "$ROOT_DIR/tests/fixtures/upgrade_old_repo" \
|
||||||
|
--output $tmpdir/testbuild \
|
||||||
|
--packages $tmpdir/testbuild \
|
||||||
|
--name "test" \
|
||||||
|
--descr "Test Repo" \
|
||||||
|
--urls $tmpdir/testrootfs \
|
||||||
|
--type http
|
||||||
|
|
||||||
|
createst=$?
|
||||||
|
assertEquals 'create repo successfully' "$createst" "0"
|
||||||
|
assertTrue 'create repository' "[ -e '$tmpdir/testbuild/repository.yaml' ]"
|
||||||
|
|
||||||
|
assertTrue 'no repository' "[ ! -e '$tmpdir/testbuild_revision/repository.yaml' ]"
|
||||||
|
luet create-repo --tree "$ROOT_DIR/tests/fixtures/upgrade_old_repo_revision" \
|
||||||
|
--output $tmpdir/testbuild_revision \
|
||||||
|
--packages $tmpdir/testbuild_revision \
|
||||||
|
--name "test" \
|
||||||
|
--descr "Test Repo" \
|
||||||
|
--urls $tmpdir/testrootfs \
|
||||||
|
--type http
|
||||||
|
|
||||||
|
createst=$?
|
||||||
|
assertEquals 'create repo successfully' "$createst" "0"
|
||||||
|
assertTrue 'create repository' "[ -e '$tmpdir/testbuild_revision/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"
|
||||||
|
}
|
||||||
|
|
||||||
|
testUpgrade() {
|
||||||
|
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' ]"
|
||||||
|
|
||||||
|
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_revision"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
luet cleanup --config $tmpdir/luet.yaml
|
||||||
|
luet config --config $tmpdir/luet.yaml
|
||||||
|
res=$?
|
||||||
|
assertEquals 'config test successfully' "$res" "0"
|
||||||
|
|
||||||
|
luet upgrade --sync --config $tmpdir/luet.yaml
|
||||||
|
installst=$?
|
||||||
|
assertEquals 'upgrade test successfully' "$installst" "0"
|
||||||
|
assertTrue 'package uninstalled B' "[ ! -e '$tmpdir/testrootfs/test5' ]"
|
||||||
|
assertTrue 'package installed B' "[ -e '$tmpdir/testrootfs/newc' ]"
|
||||||
|
|
||||||
|
content=$(luet upgrade --sync --config $tmpdir/luet.yaml)
|
||||||
|
installst=$?
|
||||||
|
assertNotContains 'didn not upgrade' "$content" "Uninstalling"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Load shUnit2.
|
||||||
|
. "$ROOT_DIR/tests/integration/shunit2"/shunit2
|
||||||
|
|
Reference in New Issue
Block a user