diff --git a/cmd/build.go b/cmd/build.go index 8d5aa27b..c4acede8 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -22,6 +22,7 @@ import ( "github.com/ghodss/yaml" helpers "github.com/mudler/luet/cmd/helpers" "github.com/mudler/luet/cmd/util" + "github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/compiler" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" @@ -29,8 +30,8 @@ import ( "github.com/mudler/luet/pkg/compiler/types/compression" "github.com/mudler/luet/pkg/compiler/types/options" + pkg "github.com/mudler/luet/pkg/database" fileHelpers "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" tree "github.com/mudler/luet/pkg/tree" "github.com/spf13/cobra" @@ -121,7 +122,7 @@ Build packages specifying multiple definition trees: fromRepo, _ := cmd.Flags().GetBool("from-repositories") compilerSpecs := compilerspec.NewLuetCompilationspecs() - var db pkg.PackageDatabase + var db types.PackageDatabase compilerBackend, err := compiler.NewBackend(util.DefaultContext, backendType) helpers.CheckErr(err) diff --git a/cmd/create-repo.go b/cmd/create-repo.go index 44705dc8..b82b4403 100644 --- a/cmd/create-repo.go +++ b/cmd/create-repo.go @@ -25,7 +25,7 @@ import ( installer "github.com/mudler/luet/pkg/installer" // . "github.com/mudler/luet/pkg/logger" - pkg "github.com/mudler/luet/pkg/package" + pkg "github.com/mudler/luet/pkg/database" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/cmd/database/create.go b/cmd/database/create.go index 0fbe4914..9d698216 100644 --- a/cmd/database/create.go +++ b/cmd/database/create.go @@ -19,10 +19,9 @@ import ( "io/ioutil" "github.com/mudler/luet/cmd/util" + "github.com/mudler/luet/pkg/api/core/types" artifact "github.com/mudler/luet/pkg/api/core/types/artifact" - pkg "github.com/mudler/luet/pkg/package" - "github.com/spf13/cobra" ) @@ -44,7 +43,7 @@ For reference, inspect a "metadata.yaml" file generated while running "luet buil Args: cobra.OnlyValidArgs, Run: func(cmd *cobra.Command, args []string) { - systemDB := util.DefaultContext.Config.GetSystemDB() + systemDB := util.SystemDB(util.DefaultContext.Config) for _, a := range args { dat, err := ioutil.ReadFile(a) @@ -67,7 +66,7 @@ For reference, inspect a "metadata.yaml" file generated while running "luet buil if _, err := systemDB.CreatePackage(art.CompileSpec.GetPackage()); err != nil { util.DefaultContext.Fatal("Failed to create ", a, ": ", err.Error()) } - if err := systemDB.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: art.CompileSpec.GetPackage().GetFingerPrint(), Files: files}); err != nil { + if err := systemDB.SetPackageFiles(&types.PackageFile{PackageFingerprint: art.CompileSpec.GetPackage().GetFingerPrint(), Files: files}); err != nil { util.DefaultContext.Fatal("Failed setting package files for ", a, ": ", err.Error()) } diff --git a/cmd/database/get.go b/cmd/database/get.go index 011471cd..796daaaf 100644 --- a/cmd/database/get.go +++ b/cmd/database/get.go @@ -40,7 +40,7 @@ To return also files: Run: func(cmd *cobra.Command, args []string) { showFiles, _ := cmd.Flags().GetBool("files") - systemDB := util.DefaultContext.Config.GetSystemDB() + systemDB := util.SystemDB(util.DefaultContext.Config) for _, a := range args { pack, err := helpers.ParsePackageStr(a) diff --git a/cmd/database/remove.go b/cmd/database/remove.go index f71a87ae..90388b4b 100644 --- a/cmd/database/remove.go +++ b/cmd/database/remove.go @@ -36,7 +36,7 @@ This commands takes multiple packages as arguments and prunes their entries from Run: func(cmd *cobra.Command, args []string) { - systemDB := util.DefaultContext.Config.GetSystemDB() + systemDB := util.SystemDB(util.DefaultContext.Config) for _, a := range args { pack, err := helpers.ParsePackageStr(a) diff --git a/cmd/helpers/cli.go b/cmd/helpers/cli.go index 899e5811..1082729c 100644 --- a/cmd/helpers/cli.go +++ b/cmd/helpers/cli.go @@ -22,9 +22,10 @@ import ( "regexp" "strings" + "github.com/mudler/luet/pkg/api/core/types" + _gentoo "github.com/Sabayon/pkgs-checker/pkg/gentoo" "github.com/mudler/luet/cmd/util" - pkg "github.com/mudler/luet/pkg/package" ) func CreateRegexArray(rgx []string) ([]*regexp.Regexp, error) { @@ -83,7 +84,7 @@ func gentooVersion(gp *_gentoo.GentooPackage) string { return pkgVersion } -func ParsePackageStr(p string) (*pkg.DefaultPackage, error) { +func ParsePackageStr(p string) (*types.Package, error) { if packageHasGentooSelector(p) { gp, err := _gentoo.ParsePackageStr(p) @@ -95,7 +96,7 @@ func ParsePackageStr(p string) (*pkg.DefaultPackage, error) { gp.Condition = _gentoo.PkgCondGreaterEqual } - return &pkg.DefaultPackage{ + return &types.Package{ Name: gp.Name, Category: gp.Category, Version: gentooVersion(gp), @@ -115,7 +116,7 @@ func ParsePackageStr(p string) (*pkg.DefaultPackage, error) { cat, name = packageData(p) } - return &pkg.DefaultPackage{ + return &types.Package{ Name: name, Category: cat, Version: ver, diff --git a/cmd/install.go b/cmd/install.go index 5ee79641..aab67a41 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -15,11 +15,11 @@ package cmd import ( + "github.com/mudler/luet/pkg/api/core/types" installer "github.com/mudler/luet/pkg/installer" helpers "github.com/mudler/luet/cmd/helpers" "github.com/mudler/luet/cmd/util" - pkg "github.com/mudler/luet/pkg/package" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -52,7 +52,7 @@ To force install a package: viper.BindPFlag("yes", cmd.Flags().Lookup("yes")) }, Run: func(cmd *cobra.Command, args []string) { - var toInstall pkg.Packages + var toInstall types.Packages for _, a := range args { pack, err := helpers.ParsePackageStr(a) @@ -86,7 +86,7 @@ To force install a package: }) system := &installer.System{ - Database: util.DefaultContext.Config.GetSystemDB(), + Database: util.SystemDB(util.DefaultContext.Config), Target: util.DefaultContext.Config.System.Rootfs, } err := inst.Install(toInstall, system) diff --git a/cmd/oscheck.go b/cmd/oscheck.go index 4a41e7ab..12ab5e99 100644 --- a/cmd/oscheck.go +++ b/cmd/oscheck.go @@ -19,8 +19,8 @@ import ( "os" "strings" + "github.com/mudler/luet/pkg/api/core/types" installer "github.com/mudler/luet/pkg/installer" - pkg "github.com/mudler/luet/pkg/package" "github.com/mudler/luet/cmd/util" @@ -55,7 +55,7 @@ To reinstall packages in the list: downloadOnly, _ := cmd.Flags().GetBool("download-only") system := &installer.System{ - Database: util.DefaultContext.Config.GetSystemDB(), + Database: util.SystemDB(util.DefaultContext.Config), Target: util.DefaultContext.Config.System.Rootfs, } packs := system.OSCheck(util.DefaultContext) @@ -81,7 +81,7 @@ To reinstall packages in the list: if reinstall { // Strip version for reinstall - toInstall := pkg.Packages{} + toInstall := types.Packages{} for _, p := range packs { new := p.Clone() new.SetVersion(">=0") diff --git a/cmd/reclaim.go b/cmd/reclaim.go index ad1c0830..ea477780 100644 --- a/cmd/reclaim.go +++ b/cmd/reclaim.go @@ -49,7 +49,7 @@ It scans the target file system, and if finds a match with a package available i }) system := &installer.System{ - Database: util.DefaultContext.Config.GetSystemDB(), + Database: util.SystemDB(util.DefaultContext.Config), Target: util.DefaultContext.Config.System.Rootfs, } err := inst.Reclaim(system) diff --git a/cmd/reinstall.go b/cmd/reinstall.go index c3a5443d..7ddad09a 100644 --- a/cmd/reinstall.go +++ b/cmd/reinstall.go @@ -15,11 +15,11 @@ package cmd import ( + "github.com/mudler/luet/pkg/api/core/types" installer "github.com/mudler/luet/pkg/installer" helpers "github.com/mudler/luet/cmd/helpers" "github.com/mudler/luet/cmd/util" - pkg "github.com/mudler/luet/pkg/package" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -40,8 +40,8 @@ var reinstallCmd = &cobra.Command{ viper.BindPFlag("yes", cmd.Flags().Lookup("yes")) }, Run: func(cmd *cobra.Command, args []string) { - var toUninstall pkg.Packages - var toAdd pkg.Packages + var toUninstall types.Packages + var toAdd types.Packages force := viper.GetBool("force") onlydeps := viper.GetBool("onlydeps") @@ -65,7 +65,7 @@ var reinstallCmd = &cobra.Command{ PackageRepositories: util.DefaultContext.Config.SystemRepositories, }) - system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs} + system := &installer.System{Database: util.SystemDB(util.DefaultContext.Config), Target: util.DefaultContext.Config.System.Rootfs} if installed { for _, p := range system.Database.World() { diff --git a/cmd/replace.go b/cmd/replace.go index 191c6e4e..e690ffb7 100644 --- a/cmd/replace.go +++ b/cmd/replace.go @@ -15,14 +15,12 @@ package cmd import ( + "github.com/mudler/luet/pkg/api/core/types" installer "github.com/mudler/luet/pkg/installer" - "github.com/mudler/luet/pkg/solver" helpers "github.com/mudler/luet/cmd/helpers" "github.com/mudler/luet/cmd/util" - pkg "github.com/mudler/luet/pkg/package" - "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -44,8 +42,8 @@ var replaceCmd = &cobra.Command{ viper.BindPFlag("yes", cmd.Flags().Lookup("yes")) }, Run: func(cmd *cobra.Command, args []string) { - var toUninstall pkg.Packages - var toAdd pkg.Packages + var toUninstall types.Packages + var toAdd types.Packages f := viper.GetStringSlice("for") force := viper.GetBool("force") @@ -70,7 +68,7 @@ var replaceCmd = &cobra.Command{ toAdd = append(toAdd, pack) } - util.DefaultContext.Config.Solver.Implementation = solver.SingleCoreSimple + util.DefaultContext.Config.Solver.Implementation = types.SolverSingleCoreSimple util.DefaultContext.Debug("Solver", util.DefaultContext.Config.Solver.CompactString()) @@ -87,7 +85,7 @@ var replaceCmd = &cobra.Command{ Context: util.DefaultContext, }) - system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs} + system := &installer.System{Database: util.SystemDB(util.DefaultContext.Config), Target: util.DefaultContext.Config.System.Rootfs} err := inst.Swap(toUninstall, toAdd, system) if err != nil { util.DefaultContext.Fatal("Error: " + err.Error()) diff --git a/cmd/search.go b/cmd/search.go index 519248b1..95399e47 100644 --- a/cmd/search.go +++ b/cmd/search.go @@ -20,8 +20,8 @@ import ( "github.com/ghodss/yaml" "github.com/mudler/luet/cmd/util" + "github.com/mudler/luet/pkg/api/core/types" installer "github.com/mudler/luet/pkg/installer" - pkg "github.com/mudler/luet/pkg/package" "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -48,11 +48,11 @@ func (r PackageResult) String() string { var rows []string = []string{"Package", "Category", "Name", "Version", "Repository", "License", "Installed"} -func packageToRow(repo string, p pkg.Package, installed bool) []string { +func packageToRow(repo string, p *types.Package, installed bool) []string { return []string{p.HumanReadableString(), p.GetCategory(), p.GetName(), p.GetVersion(), repo, p.GetLicense(), fmt.Sprintf("%t", installed)} } -func packageToList(l *util.ListWriter, repo string, p pkg.Package, installed bool) { +func packageToList(l *util.ListWriter, repo string, p *types.Package, installed bool) { l.AppendItem(pterm.BulletListItem{ Level: 0, Text: p.HumanReadableString(), TextStyle: pterm.NewStyle(pterm.FgCyan), Bullet: ">", BulletStyle: pterm.NewStyle(pterm.FgYellow), @@ -93,11 +93,11 @@ func sys() *installer.System { if s != nil { return s } - s = &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs} + s = &installer.System{Database: util.SystemDB(util.DefaultContext.Config), Target: util.DefaultContext.Config.System.Rootfs} return s } -func installed(p pkg.Package) bool { +func installed(p *types.Package) bool { s := sys() _, err := s.Database.FindPackage(p) return err == nil @@ -109,7 +109,7 @@ func searchLocally(term string, l *util.ListWriter, t *util.TableWriter, label, system := sys() var err error - iMatches := pkg.Packages{} + iMatches := types.Packages{} if label { iMatches, err = system.Database.FindPackageLabel(term) } else if labelMatch { @@ -240,12 +240,12 @@ func searchLocalFiles(term string, l *util.ListWriter, t *util.TableWriter) Resu var results Results util.DefaultContext.Info("--- Search results (" + term + "): ---") - matches, _ := util.DefaultContext.Config.GetSystemDB().FindPackageByFile(term) + matches, _ := util.SystemDB(util.DefaultContext.Config).FindPackageByFile(term) for _, pack := range matches { i := installed(pack) t.AppendRow(packageToRow("system", pack, i)) packageToList(l, "system", pack, i) - f, _ := util.DefaultContext.Config.GetSystemDB().GetPackageFiles(pack) + f, _ := util.SystemDB(util.DefaultContext.Config).GetPackageFiles(pack) results.Packages = append(results.Packages, PackageResult{ Name: pack.GetName(), diff --git a/cmd/tree/images.go b/cmd/tree/images.go index 001afd5e..c497c9d9 100644 --- a/cmd/tree/images.go +++ b/cmd/tree/images.go @@ -23,12 +23,12 @@ import ( "github.com/ghodss/yaml" helpers "github.com/mudler/luet/cmd/helpers" "github.com/mudler/luet/cmd/util" + "github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/compiler/types/options" - pkg "github.com/mudler/luet/pkg/package" - "github.com/mudler/luet/pkg/solver" + pkg "github.com/mudler/luet/pkg/database" tree "github.com/mudler/luet/pkg/tree" "github.com/spf13/cobra" @@ -76,7 +76,7 @@ func NewTreeImageCommand() *cobra.Command { compilerBackend := backend.NewSimpleDockerBackend(util.DefaultContext) opts := util.DefaultContext.Config.Solver - opts.Options = solver.Options{Type: solver.SingleCoreSimple, Concurrency: 1} + opts.SolverOptions = types.SolverOptions{Type: types.SolverSingleCoreSimple, Concurrency: 1} luetCompiler := compiler.NewLuetCompiler( compilerBackend, reciper.GetDatabase(), diff --git a/cmd/tree/pkglist.go b/cmd/tree/pkglist.go index 37d865a6..c475d622 100644 --- a/cmd/tree/pkglist.go +++ b/cmd/tree/pkglist.go @@ -24,7 +24,8 @@ import ( "github.com/ghodss/yaml" helpers "github.com/mudler/luet/cmd/helpers" "github.com/mudler/luet/cmd/util" - pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" + pkg "github.com/mudler/luet/pkg/database" "github.com/mudler/luet/pkg/solver" tree "github.com/mudler/luet/pkg/tree" @@ -43,7 +44,7 @@ type TreeResults struct { Packages []TreePackageResult `json:"packages"` } -func pkgDetail(pkg pkg.Package) string { +func pkgDetail(pkg *types.Package) string { ans := fmt.Sprintf(` @@ Package: %s/%s-%s Description: %s @@ -89,7 +90,7 @@ func NewTreePkglistCommand() *cobra.Command { }, Run: func(cmd *cobra.Command, args []string) { var results TreeResults - var depSolver solver.PackageSolver + var depSolver types.PackageSolver treePath, _ := cmd.Flags().GetStringArray("tree") verbose, _ := cmd.Flags().GetBool("verbose") @@ -117,7 +118,7 @@ func NewTreePkglistCommand() *cobra.Command { if deps { emptyInstallationDb := pkg.NewInMemoryDatabase(false) - depSolver = solver.NewSolver(solver.Options{Type: solver.SingleCoreSimple}, pkg.NewInMemoryDatabase(false), + depSolver = solver.NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, pkg.NewInMemoryDatabase(false), reciper.GetDatabase(), emptyInstallationDb) @@ -191,7 +192,7 @@ func NewTreePkglistCommand() *cobra.Command { } } else if deps { - solution, err := depSolver.Install(pkg.Packages{p}) + solution, err := depSolver.Install(types.Packages{p}) if err != nil { util.DefaultContext.Fatal(err.Error()) } diff --git a/cmd/tree/validate.go b/cmd/tree/validate.go index 1a71a461..46009bce 100644 --- a/cmd/tree/validate.go +++ b/cmd/tree/validate.go @@ -25,10 +25,12 @@ import ( "strconv" "sync" + "github.com/mudler/luet/pkg/api/core/types" + helpers "github.com/mudler/luet/cmd/helpers" "github.com/mudler/luet/cmd/util" - pkg "github.com/mudler/luet/pkg/package" + pkg "github.com/mudler/luet/pkg/database" "github.com/mudler/luet/pkg/solver" tree "github.com/mudler/luet/pkg/tree" @@ -77,21 +79,21 @@ func (o *ValidateOpts) AddError(err error) { o.Errors = append(o.Errors, err) } -func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, reciper tree.Builder, cacheDeps *pkg.InMemoryDatabase) error { +func validatePackage(p *types.Package, checkType string, opts *ValidateOpts, reciper tree.Builder, cacheDeps *pkg.InMemoryDatabase) error { var errstr string var ans error - var depSolver solver.PackageSolver + var depSolver types.PackageSolver if opts.WithSolver { emptyInstallationDb := pkg.NewInMemoryDatabase(false) - depSolver = solver.NewSolver(solver.Options{Type: solver.SingleCoreSimple}, pkg.NewInMemoryDatabase(false), + depSolver = solver.NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, pkg.NewInMemoryDatabase(false), reciper.GetDatabase(), emptyInstallationDb) } found, err := reciper.GetDatabase().FindPackages( - &pkg.DefaultPackage{ + &types.Package{ Name: p.GetName(), Category: p.GetCategory(), Version: ">=0", @@ -122,7 +124,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe // Ensure that we use the right package from right recipier for deps pReciper, err := reciper.GetDatabase().FindPackage( - &pkg.DefaultPackage{ + &types.Package{ Name: p.GetName(), Category: p.GetCategory(), Version: p.GetVersion(), @@ -181,11 +183,11 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe all = append(all, p.GetConflicts()...) for idx, r := range all { - var deps pkg.Packages + var deps types.Packages var err error if r.IsSelector() { deps, err = reciper.GetDatabase().FindPackages( - &pkg.DefaultPackage{ + &types.Package{ Name: r.GetName(), Category: r.GetCategory(), Version: r.GetVersion(), @@ -242,7 +244,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe } util.DefaultContext.Spinner() - solution, err := depSolver.Install(pkg.Packages{r}) + solution, err := depSolver.Install(types.Packages{r}) ass := solution.SearchByName(r.GetPackageName()) util.DefaultContext.SpinnerStop() if err == nil { @@ -309,7 +311,7 @@ func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, recipe func validateWorker(i int, wg *sync.WaitGroup, - c <-chan pkg.Package, + c <-chan *types.Package, opts *ValidateOpts) { defer wg.Done() @@ -443,7 +445,7 @@ func NewTreeValidateCommand() *cobra.Command { reciper = opts.RuntimeReciper } - all := make(chan pkg.Package) + all := make(chan *types.Package) var wg = new(sync.WaitGroup) diff --git a/cmd/uninstall.go b/cmd/uninstall.go index c0247f18..dbc7ae97 100644 --- a/cmd/uninstall.go +++ b/cmd/uninstall.go @@ -17,9 +17,8 @@ package cmd import ( helpers "github.com/mudler/luet/cmd/helpers" "github.com/mudler/luet/cmd/util" + "github.com/mudler/luet/pkg/api/core/types" installer "github.com/mudler/luet/pkg/installer" - pkg "github.com/mudler/luet/pkg/package" - "github.com/mudler/luet/pkg/solver" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -37,7 +36,7 @@ var uninstallCmd = &cobra.Command{ viper.BindPFlag("yes", cmd.Flags().Lookup("yes")) }, Run: func(cmd *cobra.Command, args []string) { - toRemove := []pkg.Package{} + toRemove := []*types.Package{} for _, a := range args { pack, err := helpers.ParsePackageStr(a) @@ -57,7 +56,7 @@ var uninstallCmd = &cobra.Command{ util.DefaultContext.Config.ConfigProtectSkip = !keepProtected - util.DefaultContext.Config.Solver.Implementation = solver.SingleCoreSimple + util.DefaultContext.Config.Solver.Implementation = types.SolverSingleCoreSimple util.DefaultContext.Debug("Solver", util.DefaultContext.Config.Solver.CompactString()) @@ -74,7 +73,7 @@ var uninstallCmd = &cobra.Command{ Context: util.DefaultContext, }) - system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs} + system := &installer.System{Database: util.SystemDB(util.DefaultContext.Config), Target: util.DefaultContext.Config.System.Rootfs} if err := inst.Uninstall(system, toRemove...); err != nil { util.DefaultContext.Fatal("Error: " + err.Error()) diff --git a/cmd/upgrade.go b/cmd/upgrade.go index 971eaa84..8f81b90c 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -16,8 +16,8 @@ package cmd import ( "github.com/mudler/luet/cmd/util" + "github.com/mudler/luet/pkg/api/core/types" installer "github.com/mudler/luet/pkg/installer" - "github.com/mudler/luet/pkg/solver" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -46,7 +46,7 @@ var upgradeCmd = &cobra.Command{ yes := viper.GetBool("yes") downloadOnly, _ := cmd.Flags().GetBool("download-only") - util.DefaultContext.Config.Solver.Implementation = solver.SingleCoreSimple + util.DefaultContext.Config.Solver.Implementation = types.SolverSingleCoreSimple util.DefaultContext.Debug("Solver", util.DefaultContext.GetConfig().Solver) @@ -67,7 +67,7 @@ var upgradeCmd = &cobra.Command{ Context: util.DefaultContext, }) - system := &installer.System{Database: util.DefaultContext.Config.GetSystemDB(), Target: util.DefaultContext.Config.System.Rootfs} + system := &installer.System{Database: util.SystemDB(util.DefaultContext.Config), Target: util.DefaultContext.Config.System.Rootfs} if err := inst.Upgrade(system); err != nil { util.DefaultContext.Fatal("Error: " + err.Error()) } diff --git a/cmd/util/config.go b/cmd/util/config.go index 095b0f21..92fc8ff3 100644 --- a/cmd/util/config.go +++ b/cmd/util/config.go @@ -115,7 +115,7 @@ func InitContext(cmd *cobra.Command) (ctx *context.Context, err error) { finalizerEnvs, _ := cmd.Flags().GetStringArray("finalizer-env") setCliFinalizerEnvs(c, finalizerEnvs) - c.Solver.Options = solver.Options{Type: solver.SingleCoreSimple, Concurrency: c.General.Concurrency} + c.Solver.SolverOptions = types.SolverOptions{Type: types.SolverSingleCoreSimple, Concurrency: c.General.Concurrency} ctx = context.NewContext( context.WithConfig(c), @@ -187,7 +187,7 @@ func initContext(cmd *cobra.Command, c *context.Context) (err error) { if c.Config.Logging.EnableLogFile && c.Config.Logging.Path != "" { f := "console" - if c.Config.Logging.JsonFormat { + if c.Config.Logging.JSONFormat { f = "json" } opts = append(opts, logger.WithFileLogging(c.Config.Logging.Path, f)) @@ -274,7 +274,7 @@ func InitViper(RootCmd *cobra.Command) { pflags.String("system-target", "", "System rootpath") pflags.String("system-engine", "", "System DB engine") - pflags.String("solver-type", "", "Solver strategy ( Defaults none, available: "+types.AvailableResolvers+" )") + pflags.String("solver-type", "", "Solver strategy ( Defaults none, available: "+solver.AvailableResolvers+" )") pflags.Float32("solver-rate", 0.7, "Solver learning rate") pflags.Float32("solver-discount", 1.0, "Solver discount rate") pflags.Int("solver-attempts", 9000, "Solver maximum attempts") diff --git a/pkg/package/annotations.go b/cmd/util/system.go similarity index 60% rename from pkg/package/annotations.go rename to cmd/util/system.go index 583d4b93..da31a78e 100644 --- a/pkg/package/annotations.go +++ b/cmd/util/system.go @@ -1,5 +1,4 @@ -// Copyright © 2019-2020 Ettore Di Giacinto -// Daniele Rondina +// Copyright © 2022 Ettore Di Giacinto // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -14,10 +13,21 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg +package util -type AnnotationKey string +import ( + "path/filepath" -const ( - ConfigProtectAnnnotation AnnotationKey = "config_protect" + "github.com/mudler/luet/pkg/api/core/types" + pkg "github.com/mudler/luet/pkg/database" ) + +func SystemDB(c *types.LuetConfig) types.PackageDatabase { + switch c.System.DatabaseEngine { + case "boltdb": + return pkg.NewBoltDatabase( + filepath.Join(c.System.DatabasePath, "luet.db")) + default: + return pkg.NewInMemoryDatabase(true) + } +} diff --git a/go.mod b/go.mod index 37948978..c7013333 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/Sabayon/pkgs-checker v0.8.4 - github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154 github.com/cavaliercoder/grab v1.0.1-0.20201108051000-98a5bfe305ec github.com/containerd/containerd v1.5.7 diff --git a/go.sum b/go.sum index a1404026..33b81344 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,6 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154 h1:2lbe+CPe6eQf2EA3jjLdLFZKGv3cbYqVIDjKnzcyOXg= github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154/go.mod h1:cMLKpjHSP4q0P133fV15ojQgwWWB2IMv+hrFsmBF/wI= github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU= diff --git a/pkg/api/core/types/artifact/artifact.go b/pkg/api/core/types/artifact/artifact.go index 6d532a47..18892d49 100644 --- a/pkg/api/core/types/artifact/artifact.go +++ b/pkg/api/core/types/artifact/artifact.go @@ -47,8 +47,6 @@ import ( compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" "github.com/mudler/luet/pkg/helpers" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" - "github.com/mudler/luet/pkg/solver" "github.com/pkg/errors" yaml "gopkg.in/yaml.v2" @@ -63,11 +61,11 @@ type PackageArtifact struct { Dependencies []*PackageArtifact `json:"dependencies"` CompileSpec *compilerspec.LuetCompilationSpec `json:"compilationspec"` Checksums Checksums `json:"checksums"` - SourceAssertion solver.PackagesAssertions `json:"-"` + SourceAssertion types.PackagesAssertions `json:"-"` CompressionType compression.Implementation `json:"compressiontype"` Files []string `json:"files"` PackageCacheImage string `json:"package_cacheimage"` - Runtime *pkg.DefaultPackage `json:"runtime,omitempty"` + Runtime *types.Package `json:"runtime,omitempty"` } func ImageToArtifact(ctx types.Context, img v1.Image, t compression.Implementation, output string, filter func(h *tar.Header) (bool, error)) (*PackageArtifact, error) { @@ -97,7 +95,7 @@ func NewPackageArtifact(path string) *PackageArtifact { func NewPackageArtifactFromYaml(data []byte) (*PackageArtifact, error) { p := &PackageArtifact{Checksums: Checksums{}} - err := yaml.Unmarshal(data, &p) + err := yaml.Unmarshal(data, p) if err != nil { return p, err } @@ -499,14 +497,9 @@ func (a *PackageArtifact) GetProtectFiles(ctx types.Context) (res []string) { annotationDir := "" if !ctx.GetConfig().ConfigProtectSkip { - // a.CompileSpec could be nil when artifact.Unpack is used for tree tarball - if a.CompileSpec != nil && - a.CompileSpec.GetPackage().HasAnnotation(string(pkg.ConfigProtectAnnnotation)) { - dir, ok := a.CompileSpec.GetPackage().GetAnnotations()[string(pkg.ConfigProtectAnnnotation)] - if ok { - annotationDir = dir - } + if a.CompileSpec != nil { + annotationDir, _ = a.CompileSpec.GetPackage().Annotations[types.ConfigProtectAnnotation] } // TODO: check if skip this if we have a.CompileSpec nil diff --git a/pkg/api/core/types/artifact/artifact_test.go b/pkg/api/core/types/artifact/artifact_test.go index cdf4150a..0f4059f5 100644 --- a/pkg/api/core/types/artifact/artifact_test.go +++ b/pkg/api/core/types/artifact/artifact_test.go @@ -20,6 +20,8 @@ import ( "os" "path/filepath" + "github.com/mudler/luet/pkg/api/core/types" + "github.com/mudler/luet/pkg/api/core/context" "github.com/mudler/luet/pkg/api/core/image" . "github.com/mudler/luet/pkg/api/core/types/artifact" @@ -29,8 +31,8 @@ import ( compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" . "github.com/mudler/luet/pkg/compiler" + pkg "github.com/mudler/luet/pkg/database" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" "github.com/mudler/luet/pkg/tree" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -49,7 +51,7 @@ var _ = Describe("Artifact", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) cc := NewLuetCompiler(nil, generalRecipe.GetDatabase(), options.WithContext(context.NewContext())) - lspec, err := cc.FromPackage(&pkg.DefaultPackage{Name: "enman", Category: "app-admin", Version: "1.4.0"}) + lspec, err := cc.FromPackage(&types.Package{Name: "enman", Category: "app-admin", Version: "1.4.0"}) Expect(err).ToNot(HaveOccurred()) Expect(lspec.Steps).To(Equal([]string{"echo foo > /test", "echo bar > /test2"})) @@ -140,7 +142,7 @@ RUN echo bar > /test2`)) Expect(err).ToNot(HaveOccurred()) a := NewPackageArtifact(filepath.Join(tmpWork, "fake.tar")) - a.CompileSpec = &compilerspec.LuetCompilationSpec{Package: &pkg.DefaultPackage{Name: "foo", Version: "1.0"}} + a.CompileSpec = &compilerspec.LuetCompilationSpec{Package: &types.Package{Name: "foo", Version: "1.0"}} err = a.Compress(tmpdir, 1) Expect(err).ToNot(HaveOccurred()) @@ -188,7 +190,7 @@ RUN echo bar > /test2`)) defer os.RemoveAll(tmpWork) // clean up a := NewPackageArtifact(filepath.Join(tmpWork, "fake.tar")) - a.CompileSpec = &compilerspec.LuetCompilationSpec{Package: &pkg.DefaultPackage{Name: "foo", Version: "1.0"}} + a.CompileSpec = &compilerspec.LuetCompilationSpec{Package: &types.Package{Name: "foo", Version: "1.0"}} err = a.Compress(tmpdir, 1) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/api/core/types/artifact/cache_test.go b/pkg/api/core/types/artifact/cache_test.go index 258bacf4..66615afc 100644 --- a/pkg/api/core/types/artifact/cache_test.go +++ b/pkg/api/core/types/artifact/cache_test.go @@ -20,11 +20,12 @@ import ( "os" "path/filepath" + "github.com/mudler/luet/pkg/api/core/types" + "github.com/mudler/luet/pkg/api/core/context" . "github.com/mudler/luet/pkg/api/core/types/artifact" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -76,13 +77,13 @@ var _ = Describe("Cache", func() { _, err = cache.Get(a) Expect(err).To(HaveOccurred()) - a.CompileSpec = &compilerspec.LuetCompilationSpec{Package: &pkg.DefaultPackage{Name: "foo", Category: "bar"}} + a.CompileSpec = &compilerspec.LuetCompilationSpec{Package: &types.Package{Name: "foo", Category: "bar"}} _, _, err = cache.Put(a) Expect(err).ToNot(HaveOccurred()) c := NewPackageArtifact(filepath.Join(tmpdir, "foo.tar.gz")) c.Hash() - c.CompileSpec = &compilerspec.LuetCompilationSpec{Package: &pkg.DefaultPackage{Name: "foo", Category: "bar"}} + c.CompileSpec = &compilerspec.LuetCompilationSpec{Package: &types.Package{Name: "foo", Category: "bar"}} _, err = cache.Get(c) Expect(err).ToNot(HaveOccurred()) }) diff --git a/pkg/api/core/types/assertion.go b/pkg/api/core/types/assertion.go new file mode 100644 index 00000000..15c76c91 --- /dev/null +++ b/pkg/api/core/types/assertion.go @@ -0,0 +1,292 @@ +package types + +import ( + "crypto/sha256" + "fmt" + "sort" + "unicode" + + "github.com/mudler/topsort" + "github.com/philopon/go-toposort" + "github.com/pkg/errors" +) + +// PackageAssert represent a package assertion. +// It is composed of a Package and a Value which is indicating the absence or not +// of the associated package state. +type PackageAssert struct { + Package *Package + Value bool + Hash PackageHash +} + +func (a *PackageAssert) String() string { + var msg string + if a.Value { + msg = "installed" + } else { + msg = "not installed" + } + return fmt.Sprintf("%s/%s %s %s", a.Package.GetCategory(), a.Package.GetName(), a.Package.GetVersion(), msg) +} + +func (assertions PackagesAssertions) EnsureOrder() PackagesAssertions { + + orderedAssertions := PackagesAssertions{} + unorderedAssertions := PackagesAssertions{} + fingerprints := []string{} + + tmpMap := map[string]PackageAssert{} + + for _, a := range assertions { + tmpMap[a.Package.GetFingerPrint()] = a + fingerprints = append(fingerprints, a.Package.GetFingerPrint()) + unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered + + if a.Value { + unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered + } else { + orderedAssertions = append(orderedAssertions, a) // Keep last the ones which are not meant to be installed + } + } + + sort.Sort(unorderedAssertions) + + // Build a topological graph + graph := toposort.NewGraph(len(unorderedAssertions)) + graph.AddNodes(fingerprints...) + for _, a := range unorderedAssertions { + for _, req := range a.Package.GetRequires() { + graph.AddEdge(a.Package.GetFingerPrint(), req.GetFingerPrint()) + } + } + result, ok := graph.Toposort() + if !ok { + panic("Cycle found") + } + for _, res := range result { + a, ok := tmpMap[res] + if !ok { + panic("fail") + // continue + } + orderedAssertions = append(orderedAssertions, a) + // orderedAssertions = append(PackagesAssertions{a}, orderedAssertions...) // push upfront + } + //helpers.ReverseAny(orderedAssertions) + return orderedAssertions +} + +// SearchByName searches a string matching a package in the assetion list +// in the category/name format +func (assertions PackagesAssertions) SearchByName(f string) *PackageAssert { + for _, a := range assertions { + if a.Value { + if a.Package.GetPackageName() == f { + return &a + } + } + } + + return nil +} +func (assertions PackagesAssertions) Search(f string) *PackageAssert { + for _, a := range assertions { + if a.Value { + if a.Package.GetFingerPrint() == f { + return &a + } + } + } + + return nil +} + +func (assertions PackagesAssertions) Order(definitiondb PackageDatabase, fingerprint string) (PackagesAssertions, error) { + + orderedAssertions := PackagesAssertions{} + unorderedAssertions := PackagesAssertions{} + + tmpMap := map[string]PackageAssert{} + graph := topsort.NewGraph() + for _, a := range assertions { + graph.AddNode(a.Package.GetFingerPrint()) + tmpMap[a.Package.GetFingerPrint()] = a + unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered + } + + sort.Sort(unorderedAssertions) + // Build a topological graph + for _, a := range unorderedAssertions { + currentPkg := a.Package + added := map[string]interface{}{} + REQUIRES: + for _, requiredDef := range currentPkg.GetRequires() { + if def, err := definitiondb.FindPackage(requiredDef); err == nil { // Provides: Get a chance of being override here + requiredDef = def + } + + // We cannot search for fingerprint, as we could have selector in versions. + // We know that the assertions are unique for packages, so look for a package with such name in the assertions + req := assertions.SearchByName(requiredDef.GetPackageName()) + if req != nil { + requiredDef = req.Package + } + if _, ok := added[requiredDef.GetFingerPrint()]; ok { + continue REQUIRES + } + // Expand also here, as we need to order them (or instead the solver should give back the dep correctly?) + graph.AddEdge(currentPkg.GetFingerPrint(), requiredDef.GetFingerPrint()) + added[requiredDef.GetFingerPrint()] = true + } + } + result, err := graph.TopSort(fingerprint) + if err != nil { + return nil, errors.Wrap(err, "fail on sorting "+fingerprint) + } + for _, res := range result { + a, ok := tmpMap[res] + if !ok { + //return nil, errors.New("fail looking for " + res) + // Since now we don't return the entire world as part of assertions + // if we don't find any reference must be because fingerprint we are analyzing (which is the one we are ordering against) + // is not part of the assertions, thus we can omit it from the result + continue + } + orderedAssertions = append(orderedAssertions, a) + // orderedAssertions = append(PackagesAssertions{a}, orderedAssertions...) // push upfront + } + //helpers.ReverseAny(orderedAssertions) + return orderedAssertions, nil +} + +func (a PackagesAssertions) Len() int { return len(a) } +func (a PackagesAssertions) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a PackagesAssertions) Less(i, j int) bool { + + iRunes := []rune(a[i].Package.GetName()) + jRunes := []rune(a[j].Package.GetName()) + + max := len(iRunes) + if max > len(jRunes) { + max = len(jRunes) + } + + for idx := 0; idx < max; idx++ { + ir := iRunes[idx] + jr := jRunes[idx] + + lir := unicode.ToLower(ir) + ljr := unicode.ToLower(jr) + + if lir != ljr { + return lir < ljr + } + + // the lowercase runes are the same, so compare the original + if ir != jr { + return ir < jr + } + } + + return false + +} + +// TrueLen returns the lenth of true assertions in the slice +func (assertions PackagesAssertions) TrueLen() int { + count := 0 + for _, ass := range assertions { + if ass.Value { + count++ + } + } + + return count +} + +// HashFrom computes the assertion hash From a given package. It drops it from the assertions +// and checks it's not the only one. if it's unique it marks it specially - so the hash +// which is generated is unique for the selected package +func (assertions PackagesAssertions) HashFrom(p *Package) string { + return assertions.SaltedHashFrom(p, map[string]string{}) +} + +func (assertions PackagesAssertions) AssertionHash() string { + return assertions.SaltedAssertionHash(map[string]string{}) +} + +func (assertions PackagesAssertions) SaltedHashFrom(p *Package, salts map[string]string) string { + var assertionhash string + + // When we don't have any solution to hash for, we need to generate an UUID by ourselves + latestsolution := assertions.Drop(p) + if latestsolution.TrueLen() == 0 { + // Preserve the hash if supplied of marked packages + marked := p.Mark() + if markedHash, exists := salts[p.GetFingerPrint()]; exists { + salts[marked.GetFingerPrint()] = markedHash + } + assertionhash = assertions.Mark(p).SaltedAssertionHash(salts) + } else { + assertionhash = latestsolution.SaltedAssertionHash(salts) + } + return assertionhash +} + +func (assertions PackagesAssertions) SaltedAssertionHash(salts map[string]string) string { + var fingerprint string + for _, assertion := range assertions { // Note: Always order them first! + if assertion.Value { // Tke into account only dependencies installed (get fingerprint of subgraph) + salt, exists := salts[assertion.Package.GetFingerPrint()] + if exists { + fingerprint += assertion.String() + salt + "\n" + + } else { + fingerprint += assertion.String() + "\n" + } + } + } + hash := sha256.Sum256([]byte(fingerprint)) + return fmt.Sprintf("%x", hash) +} + +func (assertions PackagesAssertions) Drop(p *Package) PackagesAssertions { + ass := PackagesAssertions{} + + for _, a := range assertions { + if !a.Package.Matches(p) { + ass = append(ass, a) + } + } + return ass +} + +// Cut returns an assertion list of installed (filter by Value) "cutted" until the package is found (included) +func (assertions PackagesAssertions) Cut(p *Package) PackagesAssertions { + ass := PackagesAssertions{} + + for _, a := range assertions { + if a.Value { + ass = append(ass, a) + if a.Package.Matches(p) { + break + } + } + } + return ass +} + +// Mark returns a new assertion with the package marked +func (assertions PackagesAssertions) Mark(p *Package) PackagesAssertions { + ass := PackagesAssertions{} + + for _, a := range assertions { + if a.Package.Matches(p) { + marked := a.Package.Mark() + a = PackageAssert{Package: marked, Value: a.Value, Hash: a.Hash} + } + ass = append(ass, a) + } + return ass +} diff --git a/pkg/api/core/types/config.go b/pkg/api/core/types/config.go index 4db7169a..5aa27768 100644 --- a/pkg/api/core/types/config.go +++ b/pkg/api/core/types/config.go @@ -22,26 +22,23 @@ import ( "path" "path/filepath" "regexp" - "strings" "github.com/mudler/luet/pkg/api/core/config" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" - solver "github.com/mudler/luet/pkg/solver" "github.com/pkg/errors" "gopkg.in/yaml.v2" ) -var AvailableResolvers = strings.Join([]string{solver.QLearningResolverType}, " ") - +// LuetLoggingConfig is the config +// relative to logging of luet type LuetLoggingConfig struct { // Path of the logfile Path string `yaml:"path" mapstructure:"path"` // Enable/Disable logging to file EnableLogFile bool `yaml:"enable_logfile" mapstructure:"enable_logfile"` // Enable JSON format logging in file - JsonFormat bool `yaml:"json_format" mapstructure:"json_format"` + JSONFormat bool `yaml:"json_format" mapstructure:"json_format"` // Log level Level string `yaml:"level" mapstructure:"level"` @@ -55,6 +52,8 @@ type LuetLoggingConfig struct { NoSpinner bool `yaml:"no_spinner" mapstructure:"no_spinner"` } +// LuetGeneralConfig is the general configuration structure +// which applies to all the luet actions type LuetGeneralConfig struct { SameOwner bool `yaml:"same_owner,omitempty" mapstructure:"same_owner"` Concurrency int `yaml:"concurrency,omitempty" mapstructure:"concurrency"` @@ -65,42 +64,25 @@ type LuetGeneralConfig struct { Quiet bool `yaml:"quiet" mapstructure:"quiet"` } +// LuetSolverOptions this is the option struct for the luet solver type LuetSolverOptions struct { - solver.Options `yaml:"options,omitempty"` - Type string `yaml:"type,omitempty" mapstructure:"type"` - LearnRate float32 `yaml:"rate,omitempty" mapstructure:"rate"` - Discount float32 `yaml:"discount,omitempty" mapstructure:"discount"` - MaxAttempts int `yaml:"max_attempts,omitempty" mapstructure:"max_attempts"` - Implementation solver.SolverType `yaml:"implementation,omitempty" mapstructure:"implementation"` -} - -func (opts LuetSolverOptions) ResolverIsSet() bool { - switch opts.Type { - case solver.QLearningResolverType: - return true - default: - return false - } -} - -func (opts LuetSolverOptions) Resolver() solver.PackageResolver { - switch opts.Type { - case solver.QLearningResolverType: - if opts.LearnRate != 0.0 { - return solver.NewQLearningResolver(opts.LearnRate, opts.Discount, opts.MaxAttempts, 999999) - - } - return solver.SimpleQLearningSolver() - } - - return &solver.Explainer{} + SolverOptions `yaml:"options,omitempty"` + Type string `yaml:"type,omitempty" mapstructure:"type"` + LearnRate float32 `yaml:"rate,omitempty" mapstructure:"rate"` + Discount float32 `yaml:"discount,omitempty" mapstructure:"discount"` + MaxAttempts int `yaml:"max_attempts,omitempty" mapstructure:"max_attempts"` + Implementation SolverType `yaml:"implementation,omitempty" mapstructure:"implementation"` } +// CompactString returns a compact string to display solver options over CLI func (opts *LuetSolverOptions) CompactString() string { return fmt.Sprintf("type: %s rate: %f, discount: %f, attempts: %d, initialobserved: %d", opts.Type, opts.LearnRate, opts.Discount, opts.MaxAttempts, 999999) } +// LuetSystemConfig is the system configuration. +// Typically this represent a host system that is about to perform +// operations on a Rootfs. Note all the fields needs to be in absolute form. type LuetSystemConfig struct { DatabaseEngine string `yaml:"database_engine" mapstructure:"database_engine"` DatabasePath string `yaml:"database_path" mapstructure:"database_path"` @@ -153,8 +135,10 @@ func (s *LuetSystemConfig) setRootfs() error { return nil } -func (sc LuetSystemConfig) GetRepoDatabaseDirPath(name string) string { - dbpath := filepath.Join(sc.DatabasePath, "repos/"+name) +// GetRepoDatabaseDirPath is synatx sugar to return the repository path given +// a repository name in the system target +func (s LuetSystemConfig) GetRepoDatabaseDirPath(name string) string { + dbpath := filepath.Join(s.DatabasePath, "repos/"+name) err := os.MkdirAll(dbpath, os.ModePerm) if err != nil { panic(err) @@ -162,41 +146,49 @@ func (sc LuetSystemConfig) GetRepoDatabaseDirPath(name string) string { return dbpath } -func (sc *LuetSystemConfig) setDBPath() error { - dbpath := filepath.Join(sc.Rootfs, - sc.DatabasePath) +func (s *LuetSystemConfig) setDBPath() error { + dbpath := filepath.Join( + s.Rootfs, + s.DatabasePath, + ) err := os.MkdirAll(dbpath, os.ModePerm) if err != nil { return err } - sc.DatabasePath = dbpath + s.DatabasePath = dbpath return nil } -func (sc *LuetSystemConfig) setCachePath() { +func (s *LuetSystemConfig) setCachePath() { var cachepath string - if sc.PkgsCachePath != "" { + if s.PkgsCachePath != "" { if !filepath.IsAbs(cachepath) { - cachepath = filepath.Join(sc.DatabasePath, sc.PkgsCachePath) + cachepath = filepath.Join(s.DatabasePath, s.PkgsCachePath) os.MkdirAll(cachepath, os.ModePerm) } else { - cachepath = sc.PkgsCachePath + cachepath = s.PkgsCachePath } } else { // Create dynamic cache for test suites cachepath, _ = ioutil.TempDir(os.TempDir(), "cachepkgs") } - sc.PkgsCachePath = cachepath // Be consistent with the path we set + s.PkgsCachePath = cachepath // Be consistent with the path we set } +// FinalizerEnv represent a K/V environment to be set +// while running a package finalizer type FinalizerEnv struct { Key string `json:"key" yaml:"key" mapstructure:"key"` Value string `json:"value" yaml:"value" mapstructure:"value"` } +// Finalizers are a slice of K/V environments to set +// while running package finalizers type Finalizers []FinalizerEnv +// Slice returns the finalizers as a string slice in +// k=v form. func (f Finalizers) Slice() (sl []string) { for _, kv := range f { sl = append(sl, fmt.Sprintf("%s=%s", kv.Key, kv.Value)) @@ -204,6 +196,9 @@ func (f Finalizers) Slice() (sl []string) { return } +// LuetConfig is the general structure which holds +// all the configuration fields. +// It includes, Logging, General, System and Solver sub configurations. type LuetConfig struct { Logging LuetLoggingConfig `yaml:"logging,omitempty" mapstructure:"logging"` General LuetGeneralConfig `yaml:"general,omitempty" mapstructure:"general"` @@ -221,20 +216,13 @@ type LuetConfig struct { ConfigProtectConfFiles []config.ConfigProtectConfFile `yaml:"-" mapstructure:"-"` } -func (c *LuetConfig) GetSystemDB() pkg.PackageDatabase { - switch c.System.DatabaseEngine { - case "boltdb": - return pkg.NewBoltDatabase( - filepath.Join(c.System.DatabasePath, "luet.db")) - default: - return pkg.NewInMemoryDatabase(true) - } -} - +// AddSystemRepository is just syntax sugar to add a repository in the system set func (c *LuetConfig) AddSystemRepository(r LuetRepository) { c.SystemRepositories = append(c.SystemRepositories, r) } +// SetFinalizerEnv sets a k,v couple among the finalizers +// It ensures that the key is unique, and if set again it gets updated func (c *LuetConfig) SetFinalizerEnv(k, v string) { keyPresent := false envs := []FinalizerEnv{} @@ -254,6 +242,7 @@ func (c *LuetConfig) SetFinalizerEnv(k, v string) { c.FinalizerEnvs = envs } +// YAML returns the config in yaml format func (c *LuetConfig) YAML() ([]byte, error) { return yaml.Marshal(c) } @@ -313,8 +302,10 @@ func (c *LuetConfig) loadRepositories() error { return nil } +// GetSystemRepository retrieve the system repository inside the configuration +// Note, the configuration needs to be loaded first. func (c *LuetConfig) GetSystemRepository(name string) (*LuetRepository, error) { - var ans *LuetRepository = nil + var ans *LuetRepository for idx, repo := range c.SystemRepositories { if repo.Name == name { diff --git a/pkg/api/core/types/garbagecollector.go b/pkg/api/core/types/garbagecollector.go index 7ce49b12..d2259819 100644 --- a/pkg/api/core/types/garbagecollector.go +++ b/pkg/api/core/types/garbagecollector.go @@ -17,6 +17,8 @@ package types import "os" +// GarbageCollector is a general garbage collector for temporary files +// It is responsible of assigning temporary files and cleaning up afterwards type GarbageCollector interface { Clean() error TempDir(pattern string) (string, error) diff --git a/pkg/package/package.go b/pkg/api/core/types/package.go similarity index 60% rename from pkg/package/package.go rename to pkg/api/core/types/package.go index 812c0558..c7a5cdee 100644 --- a/pkg/package/package.go +++ b/pkg/api/core/types/package.go @@ -1,4 +1,4 @@ -// Copyright © 2019 Ettore Di Giacinto +// Copyright © 2019-2022 Ettore Di Giacinto // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg +package types import ( "bytes" @@ -30,7 +30,6 @@ import ( "github.com/mudler/luet/pkg/helpers" fileHelper "github.com/mudler/luet/pkg/helpers/file" - "github.com/mudler/luet/pkg/helpers/match" version "github.com/mudler/luet/pkg/versioner" gentoo "github.com/Sabayon/pkgs-checker/pkg/gentoo" @@ -40,93 +39,11 @@ import ( "github.com/pkg/errors" ) -// Package is a package interface (TBD) -// FIXME: Currently some of the methods are returning DefaultPackages due to JSON serialization of the package -type Package interface { - Encode(PackageDatabase) (string, error) - Related(definitiondb PackageDatabase) Packages +type PackageAnnotation string - BuildFormula(PackageDatabase, PackageDatabase) ([]bf.Formula, error) - - GetFingerPrint() string - GetPackageName() string - ImageID() string - Requires([]*DefaultPackage) Package - Conflicts([]*DefaultPackage) Package - Revdeps(PackageDatabase) Packages - LabelDeps(PackageDatabase, string) Packages - - GetProvides() []*DefaultPackage - SetProvides([]*DefaultPackage) Package - - GetRequires() []*DefaultPackage - GetConflicts() []*DefaultPackage - Expand(PackageDatabase) (Packages, error) - SetCategory(string) - - GetName() string - SetName(string) - GetCategory() string - - GetVersion() string - SetVersion(string) - RequiresContains(PackageDatabase, Package) (bool, error) - Matches(m Package) bool - AtomMatches(m Package) bool - BumpBuildVersion() error - - AddUse(use string) - RemoveUse(use string) - GetUses() []string - - Yaml() ([]byte, error) - Explain() - - SetPath(string) - GetPath() string - Rel(string) string - - GetDescription() string - SetDescription(string) - - AddURI(string) - GetURI() []string - - SetLicense(string) - GetLicense() string - - AddLabel(string, string) - GetLabels() map[string]string - HasLabel(string) bool - MatchLabel(*regexp.Regexp) bool - - AddAnnotation(string, string) - GetAnnotations() map[string]string - HasAnnotation(string) bool - MatchAnnotation(*regexp.Regexp) bool - - IsHidden() bool - IsSelector() bool - VersionMatchSelector(string, version.Versioner) (bool, error) - SelectorMatchVersion(string, version.Versioner) (bool, error) - - String() string - HumanReadableString() string - HashFingerprint(string) string - - SetBuildTimestamp(s string) - GetBuildTimestamp() string - - Clone() Package - - GetMetadataFilePath() string - SetTreeDir(s string) - GetTreeDir() string - - Mark() Package - - JSON() ([]byte, error) -} +const ( + ConfigProtectAnnotation PackageAnnotation = "config_protect" +) const ( PackageMetaSuffix = "metadata.yaml" @@ -134,19 +51,55 @@ const ( PackageDefinitionFile = "definition.yaml" ) -type Tree interface { - GetPackageSet() PackageDatabase - Prelude() string // A tree might have a prelude to be able to consume a tree - SetPackageSet(s PackageDatabase) - World() (Packages, error) - FindPackage(Package) (Package, error) +type Packages []*Package + +type PackageMap map[string]*Package + +// Database is a merely simple in-memory db. +// FIXME: Use a proper structure or delegate to third-party +type PackageDatabase interface { + PackageSet + + Get(s string) (string, error) + Set(k, v string) error + + Create(string, []byte) (string, error) + Retrieve(ID string) ([]byte, error) } -type Packages []Package +type PackageFile struct { + ID int `storm:"id,increment"` // primary key with auto increment + PackageFingerprint string + Files []string +} -type DefaultPackages []*DefaultPackage +type PackageSet interface { + Clone(PackageDatabase) error + Copy() (PackageDatabase, error) -type PackageMap map[string]Package + GetRevdeps(p *Package) (Packages, error) + GetPackages() []string //Ids + CreatePackage(pkg *Package) (string, error) + GetPackage(ID string) (*Package, error) + Clean() error + FindPackage(*Package) (*Package, error) + FindPackages(p *Package) (Packages, error) + UpdatePackage(p *Package) error + GetAllPackages(packages chan *Package) error + RemovePackage(*Package) error + + GetPackageFiles(*Package) ([]string, error) + SetPackageFiles(*PackageFile) error + RemovePackageFiles(*Package) error + FindPackageVersions(p *Package) (Packages, error) + World() Packages + + FindPackageCandidate(p *Package) (*Package, error) + FindPackageLabel(labelKey string) (Packages, error) + FindPackageLabelMatch(pattern string) (Packages, error) + FindPackageMatch(pattern string) (Packages, error) + FindPackageByFile(pattern string) (Packages, error) +} func (pm PackageMap) String() string { rr := []string{} @@ -158,7 +111,7 @@ func (pm PackageMap) String() string { return fmt.Sprint(rr) } -func (d DefaultPackages) Hash(salt string) string { +func (d Packages) Hash(salt string) string { overallFp := "" for _, c := range d { @@ -170,23 +123,23 @@ func (d DefaultPackages) Hash(salt string) string { } // >> Unmarshallers -// DefaultPackageFromYaml decodes a package from yaml bytes -func DefaultPackageFromYaml(yml []byte) (DefaultPackage, error) { +// PackageFromYaml decodes a package from yaml bytes +func PackageFromYaml(yml []byte) (Package, error) { - var unescaped DefaultPackage + var unescaped Package source, err := yaml.YAMLToJSON(yml) if err != nil { - return DefaultPackage{}, err + return Package{}, err } rawIn := json.RawMessage(source) bytes, err := rawIn.MarshalJSON() if err != nil { - return DefaultPackage{}, err + return Package{}, err } err = json.Unmarshal(bytes, &unescaped) if err != nil { - return DefaultPackage{}, err + return Package{}, err } return unescaped, nil } @@ -225,31 +178,34 @@ func GetRawPackages(yml []byte) (rawPackages, error) { } type Collection struct { - Packages []DefaultPackage `json:"packages"` + Packages []Package `json:"packages"` } -func DefaultPackagesFromYAML(yml []byte) ([]DefaultPackage, error) { +func PackagesFromYAML(yml []byte) ([]Package, error) { var unescaped Collection source, err := yaml.YAMLToJSON(yml) if err != nil { - return []DefaultPackage{}, err + return []Package{}, err } rawIn := json.RawMessage(source) bytes, err := rawIn.MarshalJSON() if err != nil { - return []DefaultPackage{}, err + return []Package{}, err } err = json.Unmarshal(bytes, &unescaped) if err != nil { - return []DefaultPackage{}, err + return []Package{}, err } return unescaped.Packages, nil } -// Major and minor gets escaped when marshalling in JSON, making compiler fails recognizing selectors for expansion -func (t *DefaultPackage) JSON() ([]byte, error) { +// JSON returns the package in JSON form. +// Note this function sets a specific encoder as +// major and minor gets escaped when marshalling in JSON, +// making compiler fails recognizing selectors for expansion +func (t *Package) JSON() ([]byte, error) { buffer := &bytes.Buffer{} encoder := json.NewEncoder(buffer) encoder.SetEscapeHTML(false) @@ -258,25 +214,25 @@ func (t *DefaultPackage) JSON() ([]byte, error) { } // GetMetadataFilePath returns the canonical name of an artifact metadata file -func (d *DefaultPackage) GetMetadataFilePath() string { +func (d *Package) GetMetadataFilePath() string { return fmt.Sprintf("%s.%s", d.GetFingerPrint(), PackageMetaSuffix) } -// DefaultPackage represent a standard package definition -type DefaultPackage struct { - ID int `storm:"id,increment" json:"id"` // primary key with auto increment - Name string `json:"name"` // Affects YAML field names too. - Version string `json:"version"` // Affects YAML field names too. - Category string `json:"category"` // Affects YAML field names too. - UseFlags []string `json:"use_flags,omitempty"` // Affects YAML field names too. - State State `json:"state,omitempty"` - PackageRequires []*DefaultPackage `json:"requires"` // Affects YAML field names too. - PackageConflicts []*DefaultPackage `json:"conflicts"` // Affects YAML field names too. - Provides []*DefaultPackage `json:"provides,omitempty"` // Affects YAML field names too. - Hidden bool `json:"hidden,omitempty"` // Affects YAML field names too. +// Package represent a standard package definition +type Package struct { + ID int `storm:"id,increment" json:"id"` // primary key with auto increment + Name string `json:"name"` // Affects YAML field names too. + Version string `json:"version"` // Affects YAML field names too. + Category string `json:"category"` // Affects YAML field names too. + UseFlags []string `json:"use_flags,omitempty"` // Affects YAML field names too. + State State `json:"state,omitempty"` + PackageRequires []*Package `json:"requires"` // Affects YAML field names too. + PackageConflicts []*Package `json:"conflicts"` // Affects YAML field names too. + Provides []*Package `json:"provides,omitempty"` // Affects YAML field names too. + Hidden bool `json:"hidden,omitempty"` // Affects YAML field names too. // Annotations are used for core features/options - Annotations map[string]string `json:"annotations,omitempty"` // Affects YAML field names too + Annotations map[PackageAnnotation]string `json:"annotations,omitempty"` // Affects YAML field names too // Path is set only internally when tree is loaded from disk Path string `json:"path,omitempty"` @@ -295,8 +251,8 @@ type DefaultPackage struct { type State string // NewPackage returns a new package -func NewPackage(name, version string, requires []*DefaultPackage, conflicts []*DefaultPackage) *DefaultPackage { - return &DefaultPackage{ +func NewPackage(name, version string, requires []*Package, conflicts []*Package) *Package { + return &Package{ Name: name, Version: version, PackageRequires: requires, @@ -305,13 +261,13 @@ func NewPackage(name, version string, requires []*DefaultPackage, conflicts []*D } } -func (p *DefaultPackage) SetTreeDir(s string) { +func (p *Package) SetTreeDir(s string) { p.TreeDir = s } -func (p *DefaultPackage) GetTreeDir() string { +func (p *Package) GetTreeDir() string { return p.TreeDir } -func (p *DefaultPackage) String() string { +func (p *Package) String() string { b, err := p.JSON() if err != nil { return fmt.Sprintf("{ id: \"%d\", name: \"%s\", version: \"%s\", category: \"%s\" }", p.ID, p.Name, p.Version, p.Category) @@ -321,22 +277,22 @@ func (p *DefaultPackage) String() string { // GetFingerPrint returns a UUID of the package. // FIXME: this needs to be unique, now just name is generalized -func (p *DefaultPackage) GetFingerPrint() string { +func (p *Package) GetFingerPrint() string { return fmt.Sprintf("%s-%s-%s", p.Name, p.Category, p.Version) } -func (p *DefaultPackage) HashFingerprint(salt string) string { +func (p *Package) HashFingerprint(salt string) string { h := md5.New() io.WriteString(h, fmt.Sprintf("%s-%s", p.GetFingerPrint(), salt)) return fmt.Sprintf("%x", h.Sum(nil)) } -func (p *DefaultPackage) HumanReadableString() string { +func (p *Package) HumanReadableString() string { return fmt.Sprintf("%s/%s-%s", p.Category, p.Name, p.Version) } -func FromString(s string) Package { - var unescaped DefaultPackage +func PackageFromString(s string) *Package { + var unescaped Package err := json.Unmarshal([]byte(s), &unescaped) if err != nil { @@ -345,67 +301,82 @@ func FromString(s string) Package { return &unescaped } -func (p *DefaultPackage) GetPackageName() string { +func (p *Package) GetPackageName() string { return fmt.Sprintf("%s-%s", p.Name, p.Category) } -func (p *DefaultPackage) ImageID() string { +func (p *Package) ImageID() string { return helpers.SanitizeImageString(p.GetFingerPrint()) } // GetBuildTimestamp returns the package build timestamp -func (p *DefaultPackage) GetBuildTimestamp() string { +func (p *Package) GetBuildTimestamp() string { return p.BuildTimestamp } // SetBuildTimestamp sets the package Build timestamp -func (p *DefaultPackage) SetBuildTimestamp(s string) { +func (p *Package) SetBuildTimestamp(s string) { p.BuildTimestamp = s } // GetPath returns the path where the definition file was found -func (p *DefaultPackage) GetPath() string { +func (p *Package) GetPath() string { return p.Path } -func (p *DefaultPackage) Rel(s string) string { +func (p *Package) Rel(s string) string { return filepath.Join(p.GetPath(), s) } -func (p *DefaultPackage) SetPath(s string) { +func (p *Package) SetPath(s string) { p.Path = s } -func (p *DefaultPackage) IsSelector() bool { +func (p *Package) IsSelector() bool { return strings.ContainsAny(p.GetVersion(), "<>=") } -func (p *DefaultPackage) IsHidden() bool { +func (p *Package) IsHidden() bool { return p.Hidden } -func (p *DefaultPackage) HasLabel(label string) bool { - return match.MapHasKey(&p.Labels, label) +func (p *Package) HasLabel(label string) (b bool) { + for k := range p.Labels { + if k == label { + b = true + return + } + } + + return } -func (p *DefaultPackage) MatchLabel(r *regexp.Regexp) bool { - return match.MapMatchRegex(&p.Labels, r) +func (p *Package) MatchLabel(r *regexp.Regexp) (b bool) { + for k, v := range p.Labels { + if r.MatchString(k + "=" + v) { + b = true + return + } + } + return } -func (p DefaultPackage) IsCollection() bool { +func (p Package) IsCollection() bool { return fileHelper.Exists(filepath.Join(p.Path, PackageCollectionFile)) } -func (p *DefaultPackage) HasAnnotation(label string) bool { - return match.MapHasKey(&p.Annotations, label) -} - -func (p *DefaultPackage) MatchAnnotation(r *regexp.Regexp) bool { - return match.MapMatchRegex(&p.Annotations, r) +func (p *Package) MatchAnnotation(r *regexp.Regexp) (b bool) { + for k, v := range p.Annotations { + if r.MatchString(string(k) + "=" + v) { + b = true + return + } + } + return } // AddUse adds a use to a package -func (p *DefaultPackage) AddUse(use string) { +func (p *Package) AddUse(use string) { for _, v := range p.UseFlags { if v == use { return @@ -415,7 +386,7 @@ func (p *DefaultPackage) AddUse(use string) { } // RemoveUse removes a use to a package -func (p *DefaultPackage) RemoveUse(use string) { +func (p *Package) RemoveUse(use string) { for i := len(p.UseFlags) - 1; i >= 0; i-- { if p.UseFlags[i] == use { @@ -427,11 +398,11 @@ func (p *DefaultPackage) RemoveUse(use string) { // Encode encodes the package to string. // It returns an ID which can be used to retrieve the package later on. -func (p *DefaultPackage) Encode(db PackageDatabase) (string, error) { +func (p *Package) Encode(db PackageDatabase) (string, error) { return db.CreatePackage(p) } -func (p *DefaultPackage) Yaml() ([]byte, error) { +func (p *Package) Yaml() ([]byte, error) { j, err := p.JSON() if err != nil { return []byte{}, err @@ -444,113 +415,111 @@ func (p *DefaultPackage) Yaml() ([]byte, error) { return y, nil } -func (p *DefaultPackage) GetName() string { +func (p *Package) GetName() string { return p.Name } -func (p *DefaultPackage) GetVersion() string { +func (p *Package) GetVersion() string { return p.Version } -func (p *DefaultPackage) SetVersion(v string) { +func (p *Package) SetVersion(v string) { p.Version = v } -func (p *DefaultPackage) GetDescription() string { +func (p *Package) GetDescription() string { return p.Description } -func (p *DefaultPackage) SetDescription(s string) { +func (p *Package) SetDescription(s string) { p.Description = s } -func (p *DefaultPackage) GetLicense() string { +func (p *Package) GetLicense() string { return p.License } -func (p *DefaultPackage) SetLicense(s string) { +func (p *Package) SetLicense(s string) { p.License = s } -func (p *DefaultPackage) AddURI(s string) { +func (p *Package) AddURI(s string) { p.Uri = append(p.Uri, s) } -func (p *DefaultPackage) GetURI() []string { +func (p *Package) GetURI() []string { return p.Uri } -func (p *DefaultPackage) GetCategory() string { +func (p *Package) GetCategory() string { return p.Category } -func (p *DefaultPackage) SetCategory(s string) { +func (p *Package) SetCategory(s string) { p.Category = s } -func (p *DefaultPackage) SetName(s string) { +func (p *Package) SetName(s string) { p.Name = s } -func (p *DefaultPackage) GetUses() []string { +func (p *Package) GetUses() []string { return p.UseFlags } -func (p *DefaultPackage) AddLabel(k, v string) { +func (p *Package) AddLabel(k, v string) { if p.Labels == nil { p.Labels = make(map[string]string, 0) } p.Labels[k] = v } -func (p *DefaultPackage) AddAnnotation(k, v string) { +func (p *Package) AddAnnotation(k, v string) { if p.Annotations == nil { - p.Annotations = make(map[string]string, 0) + p.Annotations = make(map[PackageAnnotation]string, 0) } - p.Annotations[k] = v + p.Annotations[PackageAnnotation(k)] = v } -func (p *DefaultPackage) GetLabels() map[string]string { +func (p *Package) GetLabels() map[string]string { return p.Labels } -func (p *DefaultPackage) GetAnnotations() map[string]string { - return p.Annotations -} -func (p *DefaultPackage) GetProvides() []*DefaultPackage { + +func (p *Package) GetProvides() []*Package { return p.Provides } -func (p *DefaultPackage) SetProvides(req []*DefaultPackage) Package { +func (p *Package) SetProvides(req []*Package) *Package { p.Provides = req return p } -func (p *DefaultPackage) GetRequires() []*DefaultPackage { +func (p *Package) GetRequires() []*Package { return p.PackageRequires } -func (p *DefaultPackage) GetConflicts() []*DefaultPackage { +func (p *Package) GetConflicts() []*Package { return p.PackageConflicts } -func (p *DefaultPackage) Requires(req []*DefaultPackage) Package { +func (p *Package) Requires(req []*Package) *Package { p.PackageRequires = req return p } -func (p *DefaultPackage) Conflicts(req []*DefaultPackage) Package { +func (p *Package) Conflicts(req []*Package) *Package { p.PackageConflicts = req return p } -func (p *DefaultPackage) Clone() Package { - new := &DefaultPackage{} +func (p *Package) Clone() *Package { + new := &Package{} copier.Copy(&new, &p) return new } -func (p *DefaultPackage) Matches(m Package) bool { +func (p *Package) Matches(m *Package) bool { if p.GetFingerPrint() == m.GetFingerPrint() { return true } return false } -func (p *DefaultPackage) AtomMatches(m Package) bool { +func (p *Package) AtomMatches(m *Package) bool { if p.GetName() == m.GetName() && p.GetCategory() == m.GetCategory() { return true } return false } -func (p *DefaultPackage) Mark() Package { +func (p *Package) Mark() *Package { marked := p.Clone() marked.SetName("@@" + marked.GetName()) return marked } -func (p *DefaultPackage) Expand(definitiondb PackageDatabase) (Packages, error) { +func (p *Package) Expand(definitiondb PackageDatabase) (Packages, error) { var versionsInWorld Packages all, err := definitiondb.FindPackages(p) @@ -570,7 +539,7 @@ func (p *DefaultPackage) Expand(definitiondb PackageDatabase) (Packages, error) return versionsInWorld, nil } -func (p *DefaultPackage) Revdeps(definitiondb PackageDatabase) Packages { +func (p *Package) Revdeps(definitiondb PackageDatabase) Packages { var versionsInWorld Packages for _, w := range definitiondb.World() { if w.Matches(p) { @@ -587,7 +556,7 @@ func (p *DefaultPackage) Revdeps(definitiondb PackageDatabase) Packages { return versionsInWorld } -func walkPackage(p Package, definitiondb PackageDatabase, visited map[string]interface{}) Packages { +func walkPackage(p *Package, definitiondb PackageDatabase, visited map[string]interface{}) Packages { var versionsInWorld Packages if _, ok := visited[p.HumanReadableString()]; ok { return versionsInWorld @@ -624,11 +593,11 @@ func walkPackage(p Package, definitiondb PackageDatabase, visited map[string]int return versionsInWorld.Unique() } -func (p *DefaultPackage) Related(definitiondb PackageDatabase) Packages { +func (p *Package) Related(definitiondb PackageDatabase) Packages { return walkPackage(p, definitiondb, map[string]interface{}{}) } -func (p *DefaultPackage) LabelDeps(definitiondb PackageDatabase, labelKey string) Packages { +func (p *Package) LabelDeps(definitiondb PackageDatabase, labelKey string) Packages { var pkgsWithLabelInWorld Packages // TODO: check if integrate some index to improve // research instead of iterate all list. @@ -641,11 +610,11 @@ func (p *DefaultPackage) LabelDeps(definitiondb PackageDatabase, labelKey string return pkgsWithLabelInWorld } -func DecodePackage(ID string, db PackageDatabase) (Package, error) { +func DecodePackage(ID string, db PackageDatabase) (*Package, error) { return db.GetPackage(ID) } -func (pack *DefaultPackage) scanRequires(definitiondb PackageDatabase, s Package, visited map[string]interface{}) (bool, error) { +func (pack *Package) scanRequires(definitiondb PackageDatabase, s *Package, visited map[string]interface{}) (bool, error) { if _, ok := visited[pack.HumanReadableString()]; ok { return false, nil } @@ -677,18 +646,18 @@ func (pack *DefaultPackage) scanRequires(definitiondb PackageDatabase, s Package // RequiresContains recursively scans into the database packages dependencies to find a match with the given package // It is used by the solver during uninstall. -func (pack *DefaultPackage) RequiresContains(definitiondb PackageDatabase, s Package) (bool, error) { +func (pack *Package) RequiresContains(definitiondb PackageDatabase, s *Package) (bool, error) { return pack.scanRequires(definitiondb, s, make(map[string]interface{})) } // Best returns the best version of the package (the most bigger) from a list // Accepts a versioner interface to change the ordering policy. If null is supplied // It defaults to version.WrappedVersioner which supports both semver and debian versioning -func (set Packages) Best(v version.Versioner) Package { +func (set Packages) Best(v version.Versioner) *Package { if v == nil { v = &version.WrappedVersioner{} } - var versionsMap map[string]Package = make(map[string]Package) + var versionsMap map[string]*Package = make(map[string]*Package) if len(set) == 0 { panic("Best needs a list with elements") } @@ -703,19 +672,19 @@ func (set Packages) Best(v version.Versioner) Package { return versionsMap[sorted[len(sorted)-1]] } -func (set Packages) Find(packageName string) (Package, error) { +func (set Packages) Find(packageName string) (*Package, error) { for _, p := range set { if p.GetPackageName() == packageName { return p, nil } } - return &DefaultPackage{}, errors.New("package not found") + return nil, errors.New("package not found") } func (set Packages) Unique() Packages { var result Packages - uniq := make(map[string]Package) + uniq := make(map[string]*Package) for _, p := range set { uniq[p.GetFingerPrint()] = p } @@ -725,15 +694,15 @@ func (set Packages) Unique() Packages { return result } -func (p *DefaultPackage) GetRuntimePackage() (*DefaultPackage, error) { - var r *DefaultPackage +func (p *Package) GetRuntimePackage() (*Package, error) { + var r *Package if p.IsCollection() { collectionFile := filepath.Join(p.Path, PackageCollectionFile) dat, err := ioutil.ReadFile(collectionFile) if err != nil { return r, errors.Wrapf(err, "failed while reading '%s'", collectionFile) } - coll, err := DefaultPackagesFromYAML(dat) + coll, err := PackagesFromYAML(dat) if err != nil { return r, errors.Wrapf(err, "failed while parsing YAML '%s'", collectionFile) } @@ -749,7 +718,7 @@ func (p *DefaultPackage) GetRuntimePackage() (*DefaultPackage, error) { if err != nil { return r, errors.Wrapf(err, "failed while reading '%s'", definitionFile) } - d, err := DefaultPackageFromYaml(dat) + d, err := PackageFromYaml(dat) if err != nil { return r, errors.Wrapf(err, "failed while parsing YAML '%s'", definitionFile) } @@ -758,7 +727,7 @@ func (p *DefaultPackage) GetRuntimePackage() (*DefaultPackage, error) { return r, nil } -func (pack *DefaultPackage) buildFormula(definitiondb PackageDatabase, db PackageDatabase, visited map[string]interface{}) ([]bf.Formula, error) { +func (pack *Package) buildFormula(definitiondb PackageDatabase, db PackageDatabase, visited map[string]interface{}) ([]bf.Formula, error) { if _, ok := visited[pack.HumanReadableString()]; ok { return nil, nil } @@ -795,45 +764,14 @@ func (pack *DefaultPackage) buildFormula(definitiondb PackageDatabase, db Packag required, err := definitiondb.FindPackage(requiredDef) if err != nil || requiredDef.IsSelector() { if err == nil { - requiredDef = required.(*DefaultPackage) + required = requiredDef } - packages, err := definitiondb.FindPackages(requiredDef) if err != nil || len(packages) == 0 { required = requiredDef } else { - 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...))))) - // formulas = append(formulas, bf.Or(C, bf.Or(priorityConstraints...))) - // } - + var ALO []bf.Formula // AMO/ALO - At most/least one for _, o := range packages { encodedB, err := o.Encode(db) @@ -865,8 +803,7 @@ func (pack *DefaultPackage) buildFormula(definitiondb PackageDatabase, db Packag } B := bf.Var(encodedB) formulas = append(formulas, bf.Or(bf.Not(A), B)) - r := required.(*DefaultPackage) // We know since the implementation is DefaultPackage, that can be only DefaultPackage - f, err := r.buildFormula(definitiondb, db, visited) + f, err := required.buildFormula(definitiondb, db, visited) if err != nil { return nil, err } @@ -878,7 +815,7 @@ func (pack *DefaultPackage) buildFormula(definitiondb PackageDatabase, db Packag required, err := definitiondb.FindPackage(requiredDef) if err != nil || requiredDef.IsSelector() { if err == nil { - requiredDef = required.(*DefaultPackage) + requiredDef = required } packages, err := definitiondb.FindPackages(requiredDef) if err != nil || len(packages) == 0 { @@ -895,8 +832,7 @@ func (pack *DefaultPackage) buildFormula(definitiondb PackageDatabase, db Packag B := bf.Var(encodedB) formulas = append(formulas, bf.Or(bf.Not(A), bf.Not(B))) - r := p.(*DefaultPackage) // We know since the implementation is DefaultPackage, that can be only DefaultPackage - f, err := r.buildFormula(definitiondb, db, visited) + f, err := p.buildFormula(definitiondb, db, visited) if err != nil { return nil, err } @@ -915,8 +851,7 @@ func (pack *DefaultPackage) buildFormula(definitiondb PackageDatabase, db Packag formulas = append(formulas, bf.Or(bf.Not(A), bf.Not(B))) - r := required.(*DefaultPackage) // We know since the implementation is DefaultPackage, that can be only DefaultPackage - f, err := r.buildFormula(definitiondb, db, visited) + f, err := required.buildFormula(definitiondb, db, visited) if err != nil { return nil, err } @@ -927,11 +862,11 @@ func (pack *DefaultPackage) buildFormula(definitiondb PackageDatabase, db Packag return formulas, nil } -func (pack *DefaultPackage) BuildFormula(definitiondb PackageDatabase, db PackageDatabase) ([]bf.Formula, error) { +func (pack *Package) BuildFormula(definitiondb PackageDatabase, db PackageDatabase) ([]bf.Formula, error) { return pack.buildFormula(definitiondb, db, make(map[string]interface{})) } -func (p *DefaultPackage) Explain() { +func (p *Package) Explain() { fmt.Println("====================") fmt.Println("Name: ", p.GetName()) @@ -950,7 +885,7 @@ func (p *DefaultPackage) Explain() { } -func (p *DefaultPackage) BumpBuildVersion() error { +func (p *Package) BumpBuildVersion() error { cat := p.Category if cat == "" { // Use fake category for parse package @@ -1036,7 +971,7 @@ end: return nil } -func (p *DefaultPackage) SelectorMatchVersion(ver string, v version.Versioner) (bool, error) { +func (p *Package) SelectorMatchVersion(ver string, v version.Versioner) (bool, error) { if !p.IsSelector() { return false, errors.New("Package is not a selector") } @@ -1047,7 +982,7 @@ func (p *DefaultPackage) SelectorMatchVersion(ver string, v version.Versioner) ( return v.ValidateSelector(ver, p.GetVersion()), nil } -func (p *DefaultPackage) VersionMatchSelector(selector string, v version.Versioner) (bool, error) { +func (p *Package) VersionMatchSelector(selector string, v version.Versioner) (bool, error) { if v == nil { v = &version.WrappedVersioner{} } diff --git a/pkg/package/package_test.go b/pkg/api/core/types/package_test.go similarity index 61% rename from pkg/package/package_test.go rename to pkg/api/core/types/package_test.go index 9c3aa4cf..b8005bf1 100644 --- a/pkg/package/package_test.go +++ b/pkg/api/core/types/package_test.go @@ -13,12 +13,14 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg_test +package types_test import ( "regexp" - . "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" + + . "github.com/mudler/luet/pkg/database" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -26,12 +28,12 @@ import ( var _ = Describe("Package", func() { Context("Encoding/Decoding", func() { - a := &DefaultPackage{Name: "test", Version: "1", Category: "t"} - a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a := &types.Package{Name: "test", Version: "1", Category: "t"} + a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) It("Encodes and decodes correctly", func() { Expect(a.String()).ToNot(Equal("")) - p := FromString(a.String()) + p := types.PackageFromString(a.String()) Expect(p).To(Equal(a)) }) @@ -42,14 +44,14 @@ var _ = Describe("Package", func() { }) Context("Simple package", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a11 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a01 := NewPackage("A", "0.1", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a11 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a01 := types.NewPackage("A", "0.1", []*types.Package{}, []*types.Package{}) re := regexp.MustCompile("project[0-9][=].*") It("Expands correctly", func() { definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a1, a11, a01} { + for _, p := range []*types.Package{a1, a11, a01} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -68,26 +70,26 @@ var _ = Describe("Package", func() { Context("ImageID", func() { It("Returns a correct ImageID escaping unsupported chars", func() { - p := NewPackage("A", "1.0+p1", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0+p1", []*types.Package{}, []*types.Package{}) Expect(p.ImageID()).To(Equal("A--1.0-p1")) }) It("Returns a correct ImageID", func() { - p := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) Expect(p.ImageID()).To(Equal("A--1.0")) }) }) Context("Find label on packages", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) a.AddLabel("project1", "test1") a.AddLabel("label2", "value1") - b := NewPackage("B", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + b := types.NewPackage("B", "1.0", []*types.Package{}, []*types.Package{}) b.AddLabel("project2", "test2") b.AddLabel("label2", "value1") It("Expands correctly", func() { var err error definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a, b} { + for _, p := range []*types.Package{a, b} { _, err = definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -106,35 +108,40 @@ var _ = Describe("Package", func() { }) Context("Find annotations on packages", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) a.AddAnnotation("project1", "test1") a.AddAnnotation("label2", "value1") - b := NewPackage("B", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + b := types.NewPackage("B", "1.0", []*types.Package{}, []*types.Package{}) b.AddAnnotation("project2", "test2") - b.AddAnnotation("label2", "value1") + b.AddAnnotation("label2", "value2") It("Expands correctly", func() { var err error definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a, b} { + for _, p := range []*types.Package{a, b} { _, err = definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } re := regexp.MustCompile("project[0-9][=].*") Expect(err).ToNot(HaveOccurred()) Expect(re).ToNot(BeNil()) - Expect(a.HasAnnotation("label2")).To(Equal(true)) - Expect(a.HasAnnotation("label3")).To(Equal(false)) - Expect(a.HasAnnotation("project1")).To(Equal(true)) - Expect(b.HasAnnotation("project2")).To(Equal(true)) - Expect(b.HasAnnotation("label2")).To(Equal(true)) + + Expect(a.Annotations).To(Equal(map[types.PackageAnnotation]string{ + types.PackageAnnotation("project1"): "test1", + types.PackageAnnotation("label2"): "value1", + })) + + Expect(b.Annotations).To(Equal(map[types.PackageAnnotation]string{ + types.PackageAnnotation("project2"): "test2", + types.PackageAnnotation("label2"): "value2", + })) + Expect(b.MatchAnnotation(re)).To(Equal(true)) Expect(a.MatchAnnotation(re)).To(Equal(true)) - }) }) Context("Check description", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) a.SetDescription("Description A") It("Set and get correctly a description", func() { @@ -143,7 +150,7 @@ var _ = Describe("Package", func() { }) Context("Check licenses", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) a.SetLicense("MIT") It("Set and get correctly a license", func() { @@ -152,7 +159,7 @@ var _ = Describe("Package", func() { }) Context("Check URI", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) a.AddURI("ftp://ftp.freeradius.org/pub/radius/freearadius-server-3.0.20.tar.gz") It("Set and get correctly an uri", func() { @@ -163,13 +170,13 @@ var _ = Describe("Package", func() { }) Context("revdeps", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - b := NewPackage("B", "1.0", []*DefaultPackage{a}, []*DefaultPackage{}) - c := NewPackage("C", "1.1", []*DefaultPackage{b}, []*DefaultPackage{}) - d := NewPackage("D", "0.1", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + b := types.NewPackage("B", "1.0", []*types.Package{a}, []*types.Package{}) + c := types.NewPackage("C", "1.1", []*types.Package{b}, []*types.Package{}) + d := types.NewPackage("D", "0.1", []*types.Package{}, []*types.Package{}) It("Computes correctly", func() { definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a, b, c, d} { + for _, p := range []*types.Package{a, b, c, d} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -181,15 +188,15 @@ var _ = Describe("Package", func() { }) Context("revdeps", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - b := NewPackage("B", "1.0", []*DefaultPackage{a}, []*DefaultPackage{}) - c := NewPackage("C", "1.1", []*DefaultPackage{b}, []*DefaultPackage{}) - d := NewPackage("D", "0.1", []*DefaultPackage{c}, []*DefaultPackage{}) - e := NewPackage("E", "0.1", []*DefaultPackage{c}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + b := types.NewPackage("B", "1.0", []*types.Package{a}, []*types.Package{}) + c := types.NewPackage("C", "1.1", []*types.Package{b}, []*types.Package{}) + d := types.NewPackage("D", "0.1", []*types.Package{c}, []*types.Package{}) + e := types.NewPackage("E", "0.1", []*types.Package{c}, []*types.Package{}) It("Computes correctly", func() { definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a, b, c, d, e} { + for _, p := range []*types.Package{a, b, c, d, e} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -202,15 +209,15 @@ var _ = Describe("Package", func() { }) Context("revdeps", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - b := NewPackage("B", "1.0", []*DefaultPackage{&DefaultPackage{Name: "A", Version: ">=1.0"}}, []*DefaultPackage{}) - c := NewPackage("C", "1.1", []*DefaultPackage{&DefaultPackage{Name: "B", Version: ">=1.0"}}, []*DefaultPackage{}) - d := NewPackage("D", "0.1", []*DefaultPackage{c}, []*DefaultPackage{}) - e := NewPackage("E", "0.1", []*DefaultPackage{c}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + b := types.NewPackage("B", "1.0", []*types.Package{&types.Package{Name: "A", Version: ">=1.0"}}, []*types.Package{}) + c := types.NewPackage("C", "1.1", []*types.Package{&types.Package{Name: "B", Version: ">=1.0"}}, []*types.Package{}) + d := types.NewPackage("D", "0.1", []*types.Package{c}, []*types.Package{}) + e := types.NewPackage("E", "0.1", []*types.Package{c}, []*types.Package{}) It("doesn't resolve selectors", func() { definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a, b, c, d, e} { + for _, p := range []*types.Package{a, b, c, d, e} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -219,15 +226,15 @@ var _ = Describe("Package", func() { }) }) Context("Expandedrevdeps", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - b := NewPackage("B", "1.0", []*DefaultPackage{&DefaultPackage{Name: "A", Version: ">=1.0"}}, []*DefaultPackage{}) - c := NewPackage("C", "1.1", []*DefaultPackage{&DefaultPackage{Name: "B", Version: ">=1.0"}}, []*DefaultPackage{}) - d := NewPackage("D", "0.1", []*DefaultPackage{c}, []*DefaultPackage{}) - e := NewPackage("E", "0.1", []*DefaultPackage{c}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + b := types.NewPackage("B", "1.0", []*types.Package{{Name: "A", Version: ">=1.0"}}, []*types.Package{}) + c := types.NewPackage("C", "1.1", []*types.Package{{Name: "B", Version: ">=1.0"}}, []*types.Package{}) + d := types.NewPackage("D", "0.1", []*types.Package{c}, []*types.Package{}) + e := types.NewPackage("E", "0.1", []*types.Package{c}, []*types.Package{}) It("Computes correctly", func() { definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a, b, c, d, e} { + for _, p := range []*types.Package{a, b, c, d, e} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -241,15 +248,15 @@ var _ = Describe("Package", func() { }) Context("Expandedrevdeps", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - b := NewPackage("B", "1.0", []*DefaultPackage{&DefaultPackage{Name: "A", Version: ">=1.0"}}, []*DefaultPackage{}) - c := NewPackage("C", "1.1", []*DefaultPackage{&DefaultPackage{Name: "B", Version: ">=1.0"}}, []*DefaultPackage{}) - d := NewPackage("D", "0.1", []*DefaultPackage{&DefaultPackage{Name: "C", Version: ">=1.0"}}, []*DefaultPackage{}) - e := NewPackage("E", "0.1", []*DefaultPackage{&DefaultPackage{Name: "C", Version: ">=1.0"}}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + b := types.NewPackage("B", "1.0", []*types.Package{&types.Package{Name: "A", Version: ">=1.0"}}, []*types.Package{}) + c := types.NewPackage("C", "1.1", []*types.Package{&types.Package{Name: "B", Version: ">=1.0"}}, []*types.Package{}) + d := types.NewPackage("D", "0.1", []*types.Package{&types.Package{Name: "C", Version: ">=1.0"}}, []*types.Package{}) + e := types.NewPackage("E", "0.1", []*types.Package{&types.Package{Name: "C", Version: ">=1.0"}}, []*types.Package{}) It("Computes correctly", func() { definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a, b, c, d, e} { + for _, p := range []*types.Package{a, b, c, d, e} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -265,15 +272,15 @@ var _ = Describe("Package", func() { }) Context("Expandedrevdeps", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - b := NewPackage("B", "1.0", []*DefaultPackage{&DefaultPackage{Name: "A", Version: ">=1.0"}}, []*DefaultPackage{}) - c := NewPackage("C", "1.1", []*DefaultPackage{&DefaultPackage{Name: "B", Version: ">=1.0"}, &DefaultPackage{Name: "A", Version: ">=0"}}, []*DefaultPackage{}) - d := NewPackage("D", "0.1", []*DefaultPackage{&DefaultPackage{Name: "C", Version: ">=1.0"}}, []*DefaultPackage{}) - e := NewPackage("E", "0.1", []*DefaultPackage{&DefaultPackage{Name: "C", Version: ">=1.0"}}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + b := types.NewPackage("B", "1.0", []*types.Package{{Name: "A", Version: ">=1.0"}}, []*types.Package{}) + c := types.NewPackage("C", "1.1", []*types.Package{{Name: "B", Version: ">=1.0"}, &types.Package{Name: "A", Version: ">=0"}}, []*types.Package{}) + d := types.NewPackage("D", "0.1", []*types.Package{{Name: "C", Version: ">=1.0"}}, []*types.Package{}) + e := types.NewPackage("E", "0.1", []*types.Package{{Name: "C", Version: ">=1.0"}}, []*types.Package{}) It("Computes correctly", func() { definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a, b, c, d, e} { + for _, p := range []*types.Package{a, b, c, d, e} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -288,14 +295,14 @@ var _ = Describe("Package", func() { }) Context("RequiresContains", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.0", []*DefaultPackage{a}, []*DefaultPackage{}) - a11 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a01 := NewPackage("A", "0.1", []*DefaultPackage{a1, a11}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.0", []*types.Package{a}, []*types.Package{}) + a11 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a01 := types.NewPackage("A", "0.1", []*types.Package{a1, a11}, []*types.Package{}) It("returns correctly", func() { definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a, a1, a11, a01} { + for _, p := range []*types.Package{a, a1, a11, a01} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -311,15 +318,15 @@ var _ = Describe("Package", func() { Context("Encoding", func() { db := NewInMemoryDatabase(false) - a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a11 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a := NewPackage("A", ">=1.0", []*DefaultPackage{a1}, []*DefaultPackage{a11}) + a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a11 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{a1}, []*types.Package{a11}) It("decodes and encodes correctly", func() { ID, err := a.Encode(db) Expect(err).ToNot(HaveOccurred()) - p, err := DecodePackage(ID, db) + p, err := types.DecodePackage(ID, db) Expect(err).ToNot(HaveOccurred()) Expect(p.GetVersion()).To(Equal(a.GetVersion())) @@ -339,10 +346,10 @@ var _ = Describe("Package", func() { Context("BuildFormula", func() { It("builds empty constraints", func() { db := NewInMemoryDatabase(false) - a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a1} { + for _, p := range []*types.Package{a1} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -354,14 +361,14 @@ var _ = Describe("Package", func() { It("builds constraints correctly", func() { db := NewInMemoryDatabase(false) - a11 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a21 := NewPackage("A", "1.2", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1.Requires([]*DefaultPackage{a11}) - a1.Conflicts([]*DefaultPackage{a21}) + a11 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a21 := types.NewPackage("A", "1.2", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1.Requires([]*types.Package{a11}) + a1.Conflicts([]*types.Package{a21}) definitions := NewInMemoryDatabase(false) - for _, p := range []Package{a1, a21, a11} { + for _, p := range []*types.Package{a1, a21, a11} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -375,9 +382,9 @@ var _ = Describe("Package", func() { }) Context("Clone", func() { - a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a11 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a := NewPackage("A", ">=1.0", []*DefaultPackage{a1}, []*DefaultPackage{a11}) + a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a11 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{a1}, []*types.Package{a11}) It("Clones correctly", func() { a2 := a.Clone() @@ -395,7 +402,7 @@ var _ = Describe("Package", func() { }) Context("Useflags", func() { - a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) It("Adds correctly", func() { a1.AddUse("test") Expect(a1.GetUses()[0]).To(Equal("test")) @@ -411,62 +418,62 @@ var _ = Describe("Package", func() { Context("Check Bump build Version", func() { It("Bump without build version", func() { - a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) err := a1.BumpBuildVersion() Expect(err).ToNot(HaveOccurred()) Expect(a1.GetVersion()).To(Equal("1.0+1")) }) It("Bump 2", func() { - p := NewPackage("A", "1.0+1", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0+1", []*types.Package{}, []*types.Package{}) err := p.BumpBuildVersion() Expect(err).ToNot(HaveOccurred()) Expect(p.GetVersion()).To(Equal("1.0+2")) }) It("Bump 3", func() { - p := NewPackage("A", "1.0+100", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0+100", []*types.Package{}, []*types.Package{}) err := p.BumpBuildVersion() Expect(err).ToNot(HaveOccurred()) Expect(p.GetVersion()).To(Equal("1.0+101")) }) It("Bump 4", func() { - p := NewPackage("A", "1.0+r1", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0+r1", []*types.Package{}, []*types.Package{}) err := p.BumpBuildVersion() Expect(err).ToNot(HaveOccurred()) Expect(p.GetVersion()).To(Equal("1.0+r2")) }) It("Bump 5", func() { - p := NewPackage("A", "1.0+p1", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0+p1", []*types.Package{}, []*types.Package{}) err := p.BumpBuildVersion() Expect(err).ToNot(HaveOccurred()) Expect(p.GetVersion()).To(Equal("1.0+p2")) }) It("Bump 6", func() { - p := NewPackage("A", "1.0+pre20200315", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0+pre20200315", []*types.Package{}, []*types.Package{}) err := p.BumpBuildVersion() Expect(err).ToNot(HaveOccurred()) Expect(p.GetVersion()).To(Equal("1.0+pre20200315.1")) }) It("Bump 7", func() { - p := NewPackage("A", "1.0+pre20200315.1", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0+pre20200315.1", []*types.Package{}, []*types.Package{}) err := p.BumpBuildVersion() Expect(err).ToNot(HaveOccurred()) Expect(p.GetVersion()).To(Equal("1.0+pre20200315.2")) }) It("Bump 8", func() { - p := NewPackage("A", "1.0+d-r1", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0+d-r1", []*types.Package{}, []*types.Package{}) err := p.BumpBuildVersion() Expect(err).ToNot(HaveOccurred()) Expect(p.GetVersion()).To(Equal("1.0+d-r1.1")) }) It("Bump 9", func() { - p := NewPackage("A", "1.0+p20200315.1", []*DefaultPackage{}, []*DefaultPackage{}) + p := types.NewPackage("A", "1.0+p20200315.1", []*types.Package{}, []*types.Package{}) err := p.BumpBuildVersion() Expect(err).ToNot(HaveOccurred()) Expect(p.GetVersion()).To(Equal("1.0+p20200315.2")) diff --git a/pkg/api/core/types/solver.go b/pkg/api/core/types/solver.go new file mode 100644 index 00000000..e0e30db6 --- /dev/null +++ b/pkg/api/core/types/solver.go @@ -0,0 +1,66 @@ +// Copyright © 2022 Ettore Di Giacinto +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . + +package types + +import ( + "github.com/crillab/gophersat/bf" +) + +type SolverType int + +const ( + SolverSingleCoreSimple SolverType = 0 +) + +// PackageSolver is an interface to a generic package solving algorithm +type PackageSolver interface { + SetDefinitionDatabase(PackageDatabase) + Install(p Packages) (PackagesAssertions, error) + RelaxedInstall(p Packages) (PackagesAssertions, error) + + Uninstall(checkconflicts, full bool, candidate ...*Package) (Packages, error) + ConflictsWithInstalled(p *Package) (bool, error) + ConflictsWith(p *Package, ls Packages) (bool, error) + Conflicts(pack *Package, lsp Packages) (bool, error) + + World() Packages + Upgrade(checkconflicts, full bool) (Packages, PackagesAssertions, error) + + UpgradeUniverse(dropremoved bool) (Packages, PackagesAssertions, error) + UninstallUniverse(toremove Packages) (Packages, error) + + SetResolver(PackageResolver) + + Solve() (PackagesAssertions, error) + // BestInstall(c Packages) (PackagesAssertions, error) +} + +type SolverOptions struct { + Type SolverType `yaml:"type,omitempty"` + Concurrency int `yaml:"concurrency,omitempty"` +} + +// PackageResolver assists PackageSolver on unsat cases +type PackageResolver interface { + Solve(bf.Formula, PackageSolver) (PackagesAssertions, error) +} + +type PackagesAssertions []PackageAssert + +type PackageHash struct { + BuildHash string + PackageHash string +} diff --git a/pkg/compiler/backend/simpledocker_test.go b/pkg/compiler/backend/simpledocker_test.go index adb02796..8a5e0852 100644 --- a/pkg/compiler/backend/simpledocker_test.go +++ b/pkg/compiler/backend/simpledocker_test.go @@ -16,6 +16,8 @@ package backend_test import ( + "github.com/mudler/luet/pkg/api/core/types" + "github.com/mudler/luet/pkg/api/core/context" . "github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler/backend" @@ -26,7 +28,7 @@ import ( "os" "path/filepath" - pkg "github.com/mudler/luet/pkg/package" + pkg "github.com/mudler/luet/pkg/database" "github.com/mudler/luet/pkg/tree" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -44,7 +46,7 @@ var _ = Describe("Docker backend", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) cc := NewLuetCompiler(nil, generalRecipe.GetDatabase()) - lspec, err := cc.FromPackage(&pkg.DefaultPackage{Name: "enman", Category: "app-admin", Version: "1.4.0"}) + lspec, err := cc.FromPackage(&types.Package{Name: "enman", Category: "app-admin", Version: "1.4.0"}) Expect(err).ToNot(HaveOccurred()) Expect(lspec.Steps).To(Equal([]string{"echo foo > /test", "echo bar > /test2"})) diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index ff3b8286..47dabd95 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -32,13 +32,14 @@ import ( bus "github.com/mudler/luet/pkg/api/core/bus" "github.com/mudler/luet/pkg/api/core/context" "github.com/mudler/luet/pkg/api/core/image" + "github.com/mudler/luet/pkg/api/core/types" artifact "github.com/mudler/luet/pkg/api/core/types/artifact" "github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/compiler/types/options" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" + pkg "github.com/mudler/luet/pkg/database" "github.com/mudler/luet/pkg/helpers" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" "github.com/mudler/luet/pkg/solver" "github.com/imdario/mergo" @@ -66,7 +67,7 @@ func (i ArtifactIndex) CleanPath() ArtifactIndex { type LuetCompiler struct { //*tree.CompilerRecipe Backend CompilerBackend - Database pkg.PackageDatabase + Database types.PackageDatabase Options options.Compiler } @@ -77,7 +78,7 @@ func NewCompiler(p ...options.Option) *LuetCompiler { return &LuetCompiler{Options: *c} } -func NewLuetCompiler(backend CompilerBackend, db pkg.PackageDatabase, compilerOpts ...options.Option) *LuetCompiler { +func NewLuetCompiler(backend CompilerBackend, db types.PackageDatabase, compilerOpts ...options.Option) *LuetCompiler { // The CompilerRecipe will gives us a tree with only build deps listed. c := NewCompiler(compilerOpts...) @@ -749,7 +750,7 @@ func (cs *LuetCompiler) compileWithImage(image, builderHash string, packageTagHa // FromDatabase returns all the available compilation specs from a database. If the minimum flag is returned // it will be computed a minimal subset that will guarantees that all packages are built ( if not targeting a single package explictly ) -func (cs *LuetCompiler) FromDatabase(db pkg.PackageDatabase, minimum bool, dst string) ([]*compilerspec.LuetCompilationSpec, error) { +func (cs *LuetCompiler) FromDatabase(db types.PackageDatabase, minimum bool, dst string) ([]*compilerspec.LuetCompilationSpec, error) { compilerSpecs := compilerspec.NewLuetCompilationspecs() w := db.World() @@ -773,10 +774,10 @@ func (cs *LuetCompiler) FromDatabase(db pkg.PackageDatabase, minimum bool, dst s } } -func (cs *LuetCompiler) ComputeDepTree(p *compilerspec.LuetCompilationSpec) (solver.PackagesAssertions, error) { - s := solver.NewResolver(cs.Options.SolverOptions.Options, pkg.NewInMemoryDatabase(false), cs.Database, pkg.NewInMemoryDatabase(false), cs.Options.SolverOptions.Resolver()) +func (cs *LuetCompiler) ComputeDepTree(p *compilerspec.LuetCompilationSpec) (types.PackagesAssertions, error) { + s := solver.NewResolver(cs.Options.SolverOptions.SolverOptions, pkg.NewInMemoryDatabase(false), cs.Database, pkg.NewInMemoryDatabase(false), solver.NewSolverFromOptions(cs.Options.SolverOptions)) - solution, err := s.Install(pkg.Packages{p.GetPackage()}) + solution, err := s.Install(types.Packages{p.GetPackage()}) if err != nil { return nil, errors.Wrap(err, "While computing a solution for "+p.GetPackage().HumanReadableString()) } @@ -837,7 +838,7 @@ func (cs *LuetCompiler) BuildTree(compilerSpecs compilerspec.LuetCompilationspec func (cs *LuetCompiler) ComputeMinimumCompilableSet(p ...*compilerspec.LuetCompilationSpec) ([]*compilerspec.LuetCompilationSpec, error) { // Generate a set with all the deps of the provided specs // we will use that set to remove the deps from the list of provided compilation specs - allDependencies := solver.PackagesAssertions{} // Get all packages that will be in deps + allDependencies := types.PackagesAssertions{} // Get all packages that will be in deps result := []*compilerspec.LuetCompilationSpec{} for _, spec := range p { sol, err := cs.ComputeDepTree(spec) @@ -888,7 +889,7 @@ func (cs *LuetCompiler) inheritSpecBuildOptions(p *compilerspec.LuetCompilationS cs.Options.Context.Debug(p.GetPackage().HumanReadableString(), "Build options after inherit", p.BuildOptions) } -func (cs *LuetCompiler) getSpecHash(pkgs pkg.DefaultPackages, salt string) (string, error) { +func (cs *LuetCompiler) getSpecHash(pkgs types.Packages, salt string) (string, error) { ht := NewHashTree(cs.Database) overallFp := "" for _, p := range pkgs { @@ -911,7 +912,7 @@ func (cs *LuetCompiler) getSpecHash(pkgs pkg.DefaultPackages, salt string) (stri func (cs *LuetCompiler) resolveFinalImages(concurrency int, keepPermissions bool, p *compilerspec.LuetCompilationSpec) error { joinTag := ">:loop: final images<" - var fromPackages pkg.DefaultPackages + var fromPackages types.Packages if p.RequiresFinalImages { cs.Options.Context.Info(joinTag, "Generating a parent image from final packages") @@ -1078,7 +1079,7 @@ func CompilerFinalImages(cs *LuetCompiler) (*LuetCompiler, error) { return nil, errors.Wrap(err, "failed getting compile spec for package "+p.HumanReadableString()) } if spec.RequiresFinalImages { - copy.Requires([]*pkg.DefaultPackage{}) + copy.Requires([]*types.Package{}) } memDB.CreatePackage(copy) @@ -1125,7 +1126,7 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateF bus.Manager.Publish(bus.EventPackagePreBuild, struct { CompileSpec *compilerspec.LuetCompilationSpec - Assert solver.PackageAssert + Assert types.PackageAssert PackageHashTree *PackageImageHashTree }{ CompileSpec: p, @@ -1195,7 +1196,7 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateF bus.Manager.Publish(bus.EventPackagePreBuild, struct { CompileSpec *compilerspec.LuetCompilationSpec - Assert solver.PackageAssert + Assert types.PackageAssert }{ CompileSpec: compileSpec, Assert: assertion, @@ -1291,7 +1292,7 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, generateF type templatedata map[string]interface{} -func (cs *LuetCompiler) templatePackage(vals []map[string]interface{}, pack pkg.Package, dst templatedata) ([]byte, error) { +func (cs *LuetCompiler) templatePackage(vals []map[string]interface{}, pack *types.Package, dst templatedata) ([]byte, error) { // Grab shared templates first var chartFiles []*chart.File if len(cs.Options.TemplatesFolder) != 0 { @@ -1317,7 +1318,7 @@ func (cs *LuetCompiler) templatePackage(vals []map[string]interface{}, pack pkg. return nil, errors.Wrap(err, "rendering file "+val) } - packsRaw, err := pkg.GetRawPackages(data) + packsRaw, err := types.GetRawPackages(data) if err != nil { return nil, errors.Wrap(err, "getting raw packages") } @@ -1380,7 +1381,7 @@ func (cs *LuetCompiler) templatePackage(vals []map[string]interface{}, pack pkg. } // FromPackage returns a compilation spec from a package definition -func (cs *LuetCompiler) FromPackage(p pkg.Package) (*compilerspec.LuetCompilationSpec, error) { +func (cs *LuetCompiler) FromPackage(p *types.Package) (*compilerspec.LuetCompilationSpec, error) { pack, err := cs.Database.FindPackageCandidate(p) if err != nil { diff --git a/pkg/compiler/compiler_test.go b/pkg/compiler/compiler_test.go index 826adbb4..9d605896 100644 --- a/pkg/compiler/compiler_test.go +++ b/pkg/compiler/compiler_test.go @@ -22,6 +22,8 @@ import ( "path/filepath" "strings" + "github.com/mudler/luet/pkg/api/core/types" + helpers "github.com/mudler/luet/tests/helpers" "github.com/mudler/luet/pkg/api/core/context" @@ -32,8 +34,8 @@ import ( "github.com/mudler/luet/pkg/compiler/types/compression" "github.com/mudler/luet/pkg/compiler/types/options" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" + pkg "github.com/mudler/luet/pkg/database" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" "github.com/mudler/luet/pkg/tree" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -53,7 +55,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -96,7 +98,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.2"}) + spec, err := compiler.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.2"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -126,7 +128,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.2"}) + spec, err := compiler.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.2"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -158,9 +160,9 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(1), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.0"}) + spec2, err := compiler.FromPackage(&types.Package{Name: "a", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -193,7 +195,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext())) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) - pkg, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + pkg, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) spec, err := compiler.FromPackage(pkg) @@ -216,11 +218,11 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.0"}) + spec2, err := compiler.FromPackage(&types.Package{Name: "a", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec3, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) + spec3, err := compiler.FromPackage(&types.Package{Name: "d", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -272,9 +274,9 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(1), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "extra", Category: "layer", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "base", Category: "layer", Version: "0.2"}) + spec2, err := compiler.FromPackage(&types.Package{Name: "base", Category: "layer", Version: "0.2"}) Expect(err).ToNot(HaveOccurred()) spec.SetOutputPath(tmpdir) spec2.SetOutputPath(tmpdir) @@ -313,7 +315,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -346,7 +348,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -381,7 +383,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -416,7 +418,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -449,7 +451,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -482,7 +484,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -519,7 +521,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "pkgs-checker", Category: "package", Version: "9999"}) + spec, err := compiler.FromPackage(&types.Package{Name: "pkgs-checker", Category: "package", Version: "9999"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -559,7 +561,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "d", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -602,7 +604,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "d", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -643,7 +645,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "0.1"}) + spec, err := compiler.FromPackage(&types.Package{Name: "extra", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -677,7 +679,7 @@ var _ = Describe("Compiler", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(10)) compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "vhba", Category: "sys-fs-5.4.2", Version: "20190410"}) + spec, err := compiler.FromPackage(&types.Package{Name: "vhba", Category: "sys-fs-5.4.2", Version: "20190410"}) Expect(err).ToNot(HaveOccurred()) bt, err := compiler.BuildTree(compilerspec.LuetCompilationspecs{*spec}) @@ -705,7 +707,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "vhba", Category: "sys-fs-5.4.2", Version: "20190410"}) + spec, err := compiler.FromPackage(&types.Package{Name: "vhba", Category: "sys-fs-5.4.2", Version: "20190410"}) Expect(err).ToNot(HaveOccurred()) // err = generalRecipe.Tree().ResolveDeps(3) @@ -744,7 +746,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) spec.SetOutputPath(tmpdir) @@ -796,7 +798,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -838,7 +840,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) + spec, err := compiler.FromPackage(&types.Package{Name: "runtime", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -874,9 +876,9 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(b, generalRecipe.GetDatabase(), options.EnablePushFinalImages, options.ForcePushFinalImages, options.WithFinalRepository(imageName)) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) + spec, err := compiler.FromPackage(&types.Package{Name: "runtime", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "build", Category: "layer", Version: "0.1"}) + spec2, err := compiler.FromPackage(&types.Package{Name: "build", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -932,14 +934,14 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{ + spec, err := compiler.FromPackage(&types.Package{ Name: "dironly", Category: "test", Version: "1.0", }) Expect(err).ToNot(HaveOccurred()) - spec2, err := compiler.FromPackage(&pkg.DefaultPackage{ + spec2, err := compiler.FromPackage(&types.Package{ Name: "dironly_filter", Category: "test", Version: "1.0", @@ -985,7 +987,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) + spec, err := compiler.FromPackage(&types.Package{Name: "runtime", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) compiler.Options.CompressionType = compression.GZip Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -1039,7 +1041,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) + spec, err := compiler.FromPackage(&types.Package{Name: "runtime", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) compiler.Options.CompressionType = compression.GZip Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -1075,7 +1077,7 @@ var _ = Describe("Compiler", func() { compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "runtime", Category: "layer", Version: "0.1"}) + spec, err := compiler.FromPackage(&types.Package{Name: "runtime", Category: "layer", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) compiler.Options.CompressionType = compression.GZip Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) diff --git a/pkg/compiler/imagehashtree.go b/pkg/compiler/imagehashtree.go index 8b4dffc2..d32035dc 100644 --- a/pkg/compiler/imagehashtree.go +++ b/pkg/compiler/imagehashtree.go @@ -20,8 +20,6 @@ import ( "github.com/mudler/luet/pkg/api/core/types" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" - pkg "github.com/mudler/luet/pkg/package" - "github.com/mudler/luet/pkg/solver" "github.com/pkg/errors" ) @@ -31,7 +29,7 @@ import ( // It is responsible of returning a concrete result // which identifies a Package in a HashTree type ImageHashTree struct { - Database pkg.PackageDatabase + Database types.PackageDatabase SolverOptions types.LuetSolverOptions } @@ -42,21 +40,21 @@ type ImageHashTree struct { // and the specfile signatures. This guarantees that each image of the build stage // is unique and can be identified later on. type PackageImageHashTree struct { - Target *solver.PackageAssert - Dependencies solver.PackagesAssertions - Solution solver.PackagesAssertions + Target *types.PackageAssert + Dependencies types.PackagesAssertions + Solution types.PackagesAssertions dependencyBuilderImageHashes map[string]string SourceHash string BuilderImageHash string } -func NewHashTree(db pkg.PackageDatabase) *ImageHashTree { +func NewHashTree(db types.PackageDatabase) *ImageHashTree { return &ImageHashTree{ Database: db, } } -func (ht *PackageImageHashTree) DependencyBuildImage(p pkg.Package) (string, error) { +func (ht *PackageImageHashTree) DependencyBuildImage(p *types.Package) (string, error) { found, ok := ht.dependencyBuilderImageHashes[p.GetFingerPrint()] if !ok { return "", errors.New("package hash not found") @@ -122,7 +120,7 @@ func (ht *ImageHashTree) genBuilderImageTag(p *compilerspec.LuetCompilationSpec, // resolve computes the dependency tree of a compilation spec and returns solver assertions // in order to be able to compile the spec. -func (ht *ImageHashTree) resolve(cs *LuetCompiler, p *compilerspec.LuetCompilationSpec) (solver.PackagesAssertions, error) { +func (ht *ImageHashTree) resolve(cs *LuetCompiler, p *compilerspec.LuetCompilationSpec) (types.PackagesAssertions, error) { dependencies, err := cs.ComputeDepTree(p) if err != nil { return nil, errors.Wrap(err, "While computing a solution for "+p.GetPackage().HumanReadableString()) @@ -144,11 +142,11 @@ func (ht *ImageHashTree) resolve(cs *LuetCompiler, p *compilerspec.LuetCompilati } } - assertions := solver.PackagesAssertions{} + assertions := types.PackagesAssertions{} for _, assertion := range dependencies { //highly dependent on the order if assertion.Value { nthsolution := dependencies.Cut(assertion.Package) - assertion.Hash = solver.PackageHash{ + assertion.Hash = types.PackageHash{ BuildHash: nthsolution.SaltedHashFrom(assertion.Package, salts), PackageHash: nthsolution.SaltedAssertionHash(salts), } diff --git a/pkg/compiler/imagehashtree_test.go b/pkg/compiler/imagehashtree_test.go index 56b7f7b4..c8231181 100644 --- a/pkg/compiler/imagehashtree_test.go +++ b/pkg/compiler/imagehashtree_test.go @@ -16,11 +16,13 @@ package compiler_test import ( + "github.com/mudler/luet/pkg/api/core/types" + "github.com/mudler/luet/pkg/api/core/context" . "github.com/mudler/luet/pkg/compiler" sd "github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/compiler/types/options" - pkg "github.com/mudler/luet/pkg/package" + pkg "github.com/mudler/luet/pkg/database" "github.com/mudler/luet/pkg/tree" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -43,7 +45,7 @@ var _ = Describe("ImageHashTree", func() { It("Calculates the hash correctly", func() { - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) packageHash, err := hashtree.Query(compiler, spec) @@ -54,7 +56,7 @@ var _ = Describe("ImageHashTree", func() { }) }) - expectedPackageHash := "f3f42a7435293225e92a51da8416f90b7c0ccd5958cd5c72276c39ece408c01f" + expectedPackageHash := "4154ad4e5dfa2aea41292b3c49eeb04ef327456ecb6312f12d7b94d18ac8cb64" Context("complex package definition", func() { BeforeEach(func() { @@ -67,30 +69,32 @@ var _ = Describe("ImageHashTree", func() { }) It("Calculates the hash correctly", func() { - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) packageHash, err := hashtree.Query(compiler, spec) Expect(err).ToNot(HaveOccurred()) + expectedHash := "b4b61939260263582da1dfa5289182a0a7570ef8658f3b01b1997fe5d8a95e49" + Expect(packageHash.Dependencies[len(packageHash.Dependencies)-1].Hash.PackageHash).To(Equal(expectedPackageHash)) Expect(packageHash.SourceHash).To(Equal(expectedPackageHash)) - Expect(packageHash.BuilderImageHash).To(Equal("builder-977129605c0d7e974cc8a431a563cec1")) + Expect(packageHash.BuilderImageHash).To(Equal("builder-381bd2ad9abe1ac6c3c26cba8f8cca0b")) //Expect(packageHash.Target.Hash.BuildHash).To(Equal("79d7107d13d578b362e6a7bf10ec850efce26316405b8d732ce8f9e004d64281")) - Expect(packageHash.Target.Hash.PackageHash).To(Equal("9112e2c97bf8ca998c1df303a9ebc4957b685930c882e9aa556eab4507220079")) - a := &pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.1"} + Expect(packageHash.Target.Hash.PackageHash).To(Equal("3a372fcee17b2c7912eabb04b50f7d5a83e75402da0c96c102f7c2e836ebaa10")) + a := &types.Package{Name: "a", Category: "test", Version: "1.1"} hash, err := packageHash.DependencyBuildImage(a) Expect(err).ToNot(HaveOccurred()) - Expect(hash).To(Equal("b4b61939260263582da1dfa5289182a0a7570ef8658f3b01b1997fe5d8a95e49")) + Expect(hash).To(Equal(expectedHash)) assertionA := packageHash.Dependencies.Search(a.GetFingerPrint()) Expect(assertionA.Hash.PackageHash).To(Equal(expectedPackageHash)) - b := &pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"} + b := &types.Package{Name: "b", Category: "test", Version: "1.0"} assertionB := packageHash.Dependencies.Search(b.GetFingerPrint()) - Expect(assertionB.Hash.PackageHash).To(Equal("b4b61939260263582da1dfa5289182a0a7570ef8658f3b01b1997fe5d8a95e49")) + Expect(assertionB.Hash.PackageHash).To(Equal(expectedHash)) hashB, err := packageHash.DependencyBuildImage(b) Expect(err).ToNot(HaveOccurred()) @@ -110,23 +114,23 @@ var _ = Describe("ImageHashTree", func() { }) It("Calculates the hash correctly", func() { - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) packageHash, err := hashtree.Query(compiler, spec) Expect(err).ToNot(HaveOccurred()) Expect(packageHash.Dependencies[len(packageHash.Dependencies)-1].Hash.PackageHash).ToNot(Equal(expectedPackageHash)) - sourceHash := "f0d96e79a0021b065674c58203158a02ed702ff29cc2ee6605e1f16f1fae9b89" + sourceHash := "5534399abed19a3c93b0e638811a5ba6d07e68f6782e2b40aaf2b09c408a3154" Expect(packageHash.Dependencies[len(packageHash.Dependencies)-1].Hash.PackageHash).To(Equal(sourceHash)) Expect(packageHash.SourceHash).To(Equal(sourceHash)) Expect(packageHash.SourceHash).ToNot(Equal(expectedPackageHash)) - Expect(packageHash.BuilderImageHash).To(Equal("builder-05506adb3777ed74825254e8b46da5e9")) + Expect(packageHash.BuilderImageHash).To(Equal("builder-2a3905cf55bdcd1e4cea6b128cbf5b3a")) //Expect(packageHash.Target.Hash.BuildHash).To(Equal("79d7107d13d578b362e6a7bf10ec850efce26316405b8d732ce8f9e004d64281")) - Expect(packageHash.Target.Hash.PackageHash).To(Equal("489ece9825e18eba2de91e93293d5c61578d492d42bbfe9b6ae2e2c3c11bc842")) - a := &pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.1"} + Expect(packageHash.Target.Hash.PackageHash).To(Equal("4a13154de2e802fbd250236294562fad8c9f2c51ab8a3fc359323dd1ed064907")) + a := &types.Package{Name: "a", Category: "test", Version: "1.1"} hash, err := packageHash.DependencyBuildImage(a) Expect(err).ToNot(HaveOccurred()) @@ -134,10 +138,10 @@ var _ = Describe("ImageHashTree", func() { assertionA := packageHash.Dependencies.Search(a.GetFingerPrint()) - Expect(assertionA.Hash.PackageHash).To(Equal("f0d96e79a0021b065674c58203158a02ed702ff29cc2ee6605e1f16f1fae9b89")) + Expect(assertionA.Hash.PackageHash).To(Equal("5534399abed19a3c93b0e638811a5ba6d07e68f6782e2b40aaf2b09c408a3154")) Expect(assertionA.Hash.PackageHash).ToNot(Equal(expectedPackageHash)) - b := &pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"} + b := &types.Package{Name: "b", Category: "test", Version: "1.0"} assertionB := packageHash.Dependencies.Search(b.GetFingerPrint()) Expect(assertionB.Hash.PackageHash).To(Equal("b4b61939260263582da1dfa5289182a0a7570ef8658f3b01b1997fe5d8a95e49")) diff --git a/pkg/compiler/types/options/compiler_options.go b/pkg/compiler/types/options/compiler_options.go index 9e5afdc8..a1f882c8 100644 --- a/pkg/compiler/types/options/compiler_options.go +++ b/pkg/compiler/types/options/compiler_options.go @@ -20,7 +20,6 @@ import ( "github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/compiler/types/compression" - "github.com/mudler/luet/pkg/solver" ) type Compiler struct { @@ -66,7 +65,7 @@ func NewDefaultCompiler() *Compiler { Concurrency: runtime.NumCPU(), OnlyDeps: false, NoDeps: false, - SolverOptions: types.LuetSolverOptions{Options: solver.Options{Concurrency: 1, Type: solver.SingleCoreSimple}}, + SolverOptions: types.LuetSolverOptions{SolverOptions: types.SolverOptions{Concurrency: 1, Type: types.SolverSingleCoreSimple}}, } } diff --git a/pkg/compiler/types/spec/spec.go b/pkg/compiler/types/spec/spec.go index 45d11c6f..3c43546b 100644 --- a/pkg/compiler/types/spec/spec.go +++ b/pkg/compiler/types/spec/spec.go @@ -21,11 +21,10 @@ import ( "path/filepath" "github.com/mitchellh/hashstructure/v2" + "github.com/mudler/luet/pkg/api/core/types" options "github.com/mudler/luet/pkg/compiler/types/options" "github.com/ghodss/yaml" - pkg "github.com/mudler/luet/pkg/package" - "github.com/mudler/luet/pkg/solver" "github.com/otiai10/copy" dirhash "golang.org/x/mod/sumdb/dirhash" ) @@ -65,7 +64,7 @@ func (specs *LuetCompilationspecs) Add(s *LuetCompilationSpec) { func (specs *LuetCompilationspecs) All() []*LuetCompilationSpec { var cspecs []*LuetCompilationSpec - for i, _ := range *specs { + for i := range *specs { f := (*specs)[i] cspecs = append(cspecs, &f) } @@ -77,7 +76,7 @@ func (specs *LuetCompilationspecs) Unique() *LuetCompilationspecs { newSpecs := LuetCompilationspecs{} seen := map[string]bool{} - for i, _ := range *specs { + for i := range *specs { j := (*specs)[i] _, ok := seen[j.GetPackage().GetFingerPrint()] if !ok { @@ -89,21 +88,21 @@ func (specs *LuetCompilationspecs) Unique() *LuetCompilationspecs { } type CopyField struct { - Package *pkg.DefaultPackage `json:"package"` - Image string `json:"image"` - Source string `json:"source"` - Destination string `json:"destination"` + Package *types.Package `json:"package"` + Image string `json:"image"` + Source string `json:"source"` + Destination string `json:"destination"` } type LuetCompilationSpec struct { - Steps []string `json:"steps"` // Are run inside a container and the result layer diff is saved - Env []string `json:"env"` - Prelude []string `json:"prelude"` // Are run inside the image which will be our builder - Image string `json:"image"` - Seed string `json:"seed"` - Package *pkg.DefaultPackage `json:"package"` - SourceAssertion solver.PackagesAssertions `json:"-"` - PackageDir string `json:"package_dir" yaml:"package_dir"` + Steps []string `json:"steps"` // Are run inside a container and the result layer diff is saved + Env []string `json:"env"` + Prelude []string `json:"prelude"` // Are run inside the image which will be our builder + Image string `json:"image"` + Seed string `json:"seed"` + Package *types.Package `json:"package"` + SourceAssertion types.PackagesAssertions `json:"-"` + PackageDir string `json:"package_dir" yaml:"package_dir"` Retrieve []string `json:"retrieve"` @@ -132,7 +131,7 @@ type Signature struct { Includes []string Excludes []string Copy []CopyField - Requires pkg.DefaultPackages + Requires types.Packages RequiresFinalImages bool } @@ -154,9 +153,9 @@ func (cs *LuetCompilationSpec) signature() Signature { } } -func NewLuetCompilationSpec(b []byte, p pkg.Package) (*LuetCompilationSpec, error) { +func NewLuetCompilationSpec(b []byte, p *types.Package) (*LuetCompilationSpec, error) { var spec LuetCompilationSpec - var packageDefinition pkg.DefaultPackage + var packageDefinition types.Package err := yaml.Unmarshal(b, &spec) if err != nil { return &spec, err @@ -170,7 +169,7 @@ func NewLuetCompilationSpec(b []byte, p pkg.Package) (*LuetCompilationSpec, erro // When we have been passed a bytes slice, parse it as a package // and updates requires/conflicts/provides. // This is required in order to allow manipulation of such fields with templating - copy := *p.(*pkg.DefaultPackage) + copy := *p spec.Package = © if len(packageDefinition.GetRequires()) != 0 { spec.Package.Requires(packageDefinition.GetRequires()) @@ -183,7 +182,7 @@ func NewLuetCompilationSpec(b []byte, p pkg.Package) (*LuetCompilationSpec, erro } return &spec, nil } -func (cs *LuetCompilationSpec) GetSourceAssertion() solver.PackagesAssertions { +func (cs *LuetCompilationSpec) GetSourceAssertion() types.PackagesAssertions { return cs.SourceAssertion } @@ -191,10 +190,10 @@ func (cs *LuetCompilationSpec) SetBuildOptions(b options.Compiler) { cs.BuildOptions = &b } -func (cs *LuetCompilationSpec) SetSourceAssertion(as solver.PackagesAssertions) { +func (cs *LuetCompilationSpec) SetSourceAssertion(as types.PackagesAssertions) { cs.SourceAssertion = as } -func (cs *LuetCompilationSpec) GetPackage() pkg.Package { +func (cs *LuetCompilationSpec) GetPackage() *types.Package { return cs.Package } diff --git a/pkg/compiler/types/spec/spec_test.go b/pkg/compiler/types/spec/spec_test.go index 5329c687..63041af9 100644 --- a/pkg/compiler/types/spec/spec_test.go +++ b/pkg/compiler/types/spec/spec_test.go @@ -20,12 +20,14 @@ import ( "os" "path/filepath" + "github.com/mudler/luet/pkg/api/core/types" + options "github.com/mudler/luet/pkg/compiler/types/options" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" fileHelper "github.com/mudler/luet/pkg/helpers/file" . "github.com/mudler/luet/pkg/compiler" - pkg "github.com/mudler/luet/pkg/package" + pkg "github.com/mudler/luet/pkg/database" "github.com/mudler/luet/pkg/tree" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -34,10 +36,10 @@ import ( var _ = Describe("Spec", func() { Context("Luet specs", func() { It("Allows normal operations", func() { - testSpec := &compilerspec.LuetCompilationSpec{Package: &pkg.DefaultPackage{Name: "foo", Category: "a", Version: "0"}} - testSpec2 := &compilerspec.LuetCompilationSpec{Package: &pkg.DefaultPackage{Name: "bar", Category: "a", Version: "0"}} - testSpec3 := &compilerspec.LuetCompilationSpec{Package: &pkg.DefaultPackage{Name: "baz", Category: "a", Version: "0"}} - testSpec4 := &compilerspec.LuetCompilationSpec{Package: &pkg.DefaultPackage{Name: "foo", Category: "a", Version: "0"}} + testSpec := &compilerspec.LuetCompilationSpec{Package: &types.Package{Name: "foo", Category: "a", Version: "0"}} + testSpec2 := &compilerspec.LuetCompilationSpec{Package: &types.Package{Name: "bar", Category: "a", Version: "0"}} + testSpec3 := &compilerspec.LuetCompilationSpec{Package: &types.Package{Name: "baz", Category: "a", Version: "0"}} + testSpec4 := &compilerspec.LuetCompilationSpec{Package: &types.Package{Name: "foo", Category: "a", Version: "0"}} specs := compilerspec.NewLuetCompilationspecs(testSpec, testSpec2) Expect(specs.Len()).To(Equal(2)) @@ -81,7 +83,7 @@ var _ = Describe("Spec", func() { Image: "foo", BuildOptions: &options.Compiler{BuildValues: []map[string]interface{}{{"foo": "bar", "baz": true}}}, - Package: &pkg.DefaultPackage{ + Package: &types.Package{ Name: "foo", Category: "Bar", Labels: map[string]string{ @@ -93,7 +95,7 @@ var _ = Describe("Spec", func() { spec2 := &compilerspec.LuetCompilationSpec{ Image: "foo", BuildOptions: &options.Compiler{BuildValues: []map[string]interface{}{{"foo": "bar", "baz": true}}}, - Package: &pkg.DefaultPackage{ + Package: &types.Package{ Name: "foo", Category: "Bar", Labels: map[string]string{ @@ -105,7 +107,7 @@ var _ = Describe("Spec", func() { spec3 := &compilerspec.LuetCompilationSpec{ Image: "foo", Steps: []string{"foo"}, - Package: &pkg.DefaultPackage{ + Package: &types.Package{ Name: "foo", Category: "Bar", Labels: map[string]string{ @@ -141,7 +143,7 @@ var _ = Describe("Spec", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase()) - lspec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "enman", Category: "app-admin", Version: "1.4.0"}) + lspec, err := compiler.FromPackage(&types.Package{Name: "enman", Category: "app-admin", Version: "1.4.0"}) Expect(err).ToNot(HaveOccurred()) Expect(lspec.Steps).To(Equal([]string{"echo foo > /test", "echo bar > /test2"})) @@ -193,7 +195,7 @@ RUN echo bar > /test2`)) Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(1)) compiler := NewLuetCompiler(nil, generalRecipe.GetDatabase()) - lspec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.0"}) + lspec, err := compiler.FromPackage(&types.Package{Name: "a", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(lspec.Steps).To(Equal([]string{"echo foo > /test", "echo bar > /test2"})) diff --git a/pkg/package/database_bench_test.go b/pkg/database/database_bench_test.go similarity index 82% rename from pkg/package/database_bench_test.go rename to pkg/database/database_bench_test.go index fbd337b0..75a7074a 100644 --- a/pkg/package/database_bench_test.go +++ b/pkg/database/database_bench_test.go @@ -13,14 +13,15 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg_test +package database_test import ( "io/ioutil" "os" "strconv" - . "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" + . "github.com/mudler/luet/pkg/database" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -29,11 +30,11 @@ var _ = Describe("Database benchmark", func() { Context("BoltDB", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) tmpfile, _ := ioutil.TempFile(os.TempDir(), "tests") defer os.Remove(tmpfile.Name()) // clean up - var db PackageSet + var db types.PackageSet BeforeEach(func() { @@ -47,7 +48,7 @@ var _ = Describe("Database benchmark", func() { Measure("it should be fast in computing world from a 50000 dataset", func(b Benchmarker) { for i := 0; i < 50000; i++ { - a = NewPackage("A"+strconv.Itoa(i), ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a = types.NewPackage("A"+strconv.Itoa(i), ">=1.0", []*types.Package{}, []*types.Package{}) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -63,7 +64,7 @@ var _ = Describe("Database benchmark", func() { Measure("it should be fast in computing world from a 100000 dataset", func(b Benchmarker) { for i := 0; i < 100000; i++ { - a = NewPackage("A"+strconv.Itoa(i), ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a = types.NewPackage("A"+strconv.Itoa(i), ">=1.0", []*types.Package{}, []*types.Package{}) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -80,11 +81,11 @@ var _ = Describe("Database benchmark", func() { Context("InMemory", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) tmpfile, _ := ioutil.TempFile(os.TempDir(), "tests") defer os.Remove(tmpfile.Name()) // clean up - var db PackageSet + var db types.PackageSet BeforeEach(func() { @@ -100,7 +101,7 @@ var _ = Describe("Database benchmark", func() { runtime := b.Time("runtime", func() { for i := 0; i < 100000; i++ { - a = NewPackage("A"+strconv.Itoa(i), ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a = types.NewPackage("A"+strconv.Itoa(i), ">=1.0", []*types.Package{}, []*types.Package{}) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/package/database_boltdb.go b/pkg/database/database_boltdb.go similarity index 74% rename from pkg/package/database_boltdb.go rename to pkg/database/database_boltdb.go index a5ed5d4c..298ea63e 100644 --- a/pkg/package/database_boltdb.go +++ b/pkg/database/database_boltdb.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg +package database import ( "encoding/base64" @@ -24,6 +24,7 @@ import ( "sync" "time" + "github.com/mudler/luet/pkg/api/core/types" "github.com/pkg/errors" storm "github.com/asdine/storm" @@ -31,32 +32,45 @@ import ( "go.etcd.io/bbolt" ) -//var BoltInstance PackageDatabase +//var BoltInstance types.PackageDatabase type BoltDatabase struct { sync.Mutex + timeout time.Duration Path string - ProvidesDatabase map[string]map[string]Package + ProvidesDatabase map[string]map[string]*types.Package } -func NewBoltDatabase(path string) PackageDatabase { - // if BoltInstance == nil { - // BoltInstance = &BoltDatabase{Path: path} - // } - //return BoltInstance, nil - return &BoltDatabase{Path: path, ProvidesDatabase: map[string]map[string]Package{}} +func checkMigrationSchema(path string) { + b, err := storm.Open(path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 10 * time.Second})) + if err != nil { + return + } + defer b.Close() + + for _, m := range migrations { + b.Bolt.Update(m) + } } -func (db *BoltDatabase) Clone(to PackageDatabase) error { +func NewBoltDatabase(path string) types.PackageDatabase { + checkMigrationSchema(path) + + return &BoltDatabase{ + timeout: 30 * time.Second, + Path: path, ProvidesDatabase: map[string]map[string]*types.Package{}} +} + +func (db *BoltDatabase) Clone(to types.PackageDatabase) error { return clone(db, to) } -func (db *BoltDatabase) Copy() (PackageDatabase, error) { +func (db *BoltDatabase) Copy() (types.PackageDatabase, error) { return copy(db) } func (db *BoltDatabase) Get(s string) (string, error) { - bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) + bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: db.timeout})) if err != nil { return "", err } @@ -68,13 +82,14 @@ func (db *BoltDatabase) Get(s string) (string, error) { } func (db *BoltDatabase) Set(k, v string) error { - bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) + bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: db.timeout})) if err != nil { return err } defer bolt.Close() return bolt.Set("solver", k, v) } + func (db *BoltDatabase) Create(id string, v []byte) (string, error) { enc := base64.StdEncoding.EncodeToString(v) @@ -97,7 +112,7 @@ func (db *BoltDatabase) Retrieve(ID string) ([]byte, error) { // GetRevdeps uses a new inmemory db to calcuate revdeps // TODO: Have a memory instance for boltdb, so we don't compute each time we get called // as this is REALLY expensive. But we don't perform usually those operations in a file db. -func (db *BoltDatabase) GetRevdeps(p Package) (Packages, error) { +func (db *BoltDatabase) GetRevdeps(p *types.Package) (types.Packages, error) { memory, err := db.Copy() if err != nil { return nil, errors.New("Failed copying bolt db to memory") @@ -105,13 +120,13 @@ func (db *BoltDatabase) GetRevdeps(p Package) (Packages, error) { return memory.GetRevdeps(p) } -func (db *BoltDatabase) FindPackage(tofind Package) (Package, error) { +func (db *BoltDatabase) FindPackage(tofind *types.Package) (*types.Package, error) { // Provides: Return the replaced package here if provided, err := db.getProvide(tofind); err == nil { return provided, nil } - p := &DefaultPackage{} + p := &types.Package{} bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { return nil, err @@ -125,7 +140,7 @@ func (db *BoltDatabase) FindPackage(tofind Package) (Package, error) { return p, nil } -func (db *BoltDatabase) UpdatePackage(p Package) error { +func (db *BoltDatabase) UpdatePackage(p *types.Package) error { // TODO: Change, but by query we cannot update by ID err := db.RemovePackage(p) if err != nil { @@ -140,8 +155,8 @@ func (db *BoltDatabase) UpdatePackage(p Package) error { return nil } -func (db *BoltDatabase) GetPackage(ID string) (Package, error) { - p := &DefaultPackage{} +func (db *BoltDatabase) GetPackage(ID string) (*types.Package, error) { + p := &types.Package{} bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { return nil, err @@ -167,21 +182,21 @@ func (db *BoltDatabase) GetPackages() []string { // Fetching records one by one (useful when the bucket contains a lot of records) query := bolt.Select() - query.Each(new(DefaultPackage), func(record interface{}) error { - u := record.(*DefaultPackage) + query.Each(new(types.Package), func(record interface{}) error { + u := record.(*types.Package) ids = append(ids, strconv.Itoa(u.ID)) return nil }) return ids } -func (db *BoltDatabase) GetAllPackages(packages chan Package) error { +func (db *BoltDatabase) GetAllPackages(packages chan *types.Package) error { bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { return err } defer bolt.Close() - var packs []DefaultPackage + var packs []types.Package err = bolt.All(&packs) if err != nil { return err @@ -196,19 +211,14 @@ func (db *BoltDatabase) GetAllPackages(packages chan Package) error { // Encode encodes the package to string. // It returns an ID which can be used to retrieve the package later on. -func (db *BoltDatabase) CreatePackage(p Package) (string, error) { +func (db *BoltDatabase) CreatePackage(p *types.Package) (string, error) { bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { return "", errors.Wrap(err, "Error opening boltdb "+db.Path) } defer bolt.Close() - dp, ok := p.(*DefaultPackage) - if !ok { - return "", errors.New("Bolt DB support only DefaultPackage type for now") - } - - err = bolt.Save(dp) + err = bolt.Save(p) if err != nil { return "", errors.Wrap(err, "Error saving package to "+db.Path) } @@ -218,20 +228,20 @@ func (db *BoltDatabase) CreatePackage(p Package) (string, error) { defer db.Unlock() // TODO: Replace with a bolt implementation (and not in memory) // Provides: Store package provides, we will reuse this when walking deps - for _, provide := range dp.Provides { + for _, provide := range p.Provides { if _, ok := db.ProvidesDatabase[provide.GetPackageName()]; !ok { - db.ProvidesDatabase[provide.GetPackageName()] = make(map[string]Package) + db.ProvidesDatabase[provide.GetPackageName()] = make(map[string]*types.Package) } db.ProvidesDatabase[provide.GetPackageName()][provide.GetVersion()] = p } - return strconv.Itoa(dp.ID), err + return strconv.Itoa(p.ID), err } // Dup from memory implementation -func (db *BoltDatabase) getProvide(p Package) (Package, error) { +func (db *BoltDatabase) getProvide(p *types.Package) (*types.Package, error) { db.Lock() pa, ok := db.ProvidesDatabase[p.GetPackageName()][p.GetVersion()] if !ok { @@ -270,7 +280,7 @@ func (db *BoltDatabase) Clean() error { return os.RemoveAll(db.Path) } -func (db *BoltDatabase) GetPackageFiles(p Package) ([]string, error) { +func (db *BoltDatabase) GetPackageFiles(p *types.Package) ([]string, error) { bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { return []string{}, errors.Wrap(err, "Error opening boltdb "+db.Path) @@ -278,14 +288,14 @@ func (db *BoltDatabase) GetPackageFiles(p Package) ([]string, error) { defer bolt.Close() files := bolt.From("files") - var pf PackageFile + var pf types.PackageFile err = files.One("PackageFingerprint", p.GetFingerPrint(), &pf) if err != nil { return []string{}, errors.Wrap(err, "While finding files") } return pf.Files, nil } -func (db *BoltDatabase) SetPackageFiles(p *PackageFile) error { +func (db *BoltDatabase) SetPackageFiles(p *types.PackageFile) error { bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { return errors.Wrap(err, "Error opening boltdb "+db.Path) @@ -295,7 +305,7 @@ func (db *BoltDatabase) SetPackageFiles(p *PackageFile) error { files := bolt.From("files") return files.Save(p) } -func (db *BoltDatabase) RemovePackageFiles(p Package) error { +func (db *BoltDatabase) RemovePackageFiles(p *types.Package) error { bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { return errors.Wrap(err, "Error opening boltdb "+db.Path) @@ -303,7 +313,7 @@ func (db *BoltDatabase) RemovePackageFiles(p Package) error { defer bolt.Close() files := bolt.From("files") - var pf PackageFile + var pf types.PackageFile err = files.One("PackageFingerprint", p.GetFingerPrint(), &pf) if err != nil { return errors.Wrap(err, "While finding files") @@ -311,13 +321,13 @@ func (db *BoltDatabase) RemovePackageFiles(p Package) error { return files.DeleteStruct(&pf) } -func (db *BoltDatabase) RemovePackage(p Package) error { +func (db *BoltDatabase) RemovePackage(p *types.Package) error { bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { return errors.Wrap(err, "Error opening boltdb "+db.Path) } defer bolt.Close() - var found DefaultPackage + var found types.Package err = bolt.Select(q.Eq("Name", p.GetName()), q.Eq("Category", p.GetCategory()), q.Eq("Version", p.GetVersion())).Limit(1).Delete(&found) if err != nil { return errors.New(fmt.Sprintf("Package not found: %s", p.HumanReadableString())) @@ -325,27 +335,27 @@ func (db *BoltDatabase) RemovePackage(p Package) error { return nil } -func (db *BoltDatabase) World() Packages { - var packs []DefaultPackage +func (db *BoltDatabase) World() types.Packages { + var packs []types.Package bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) if err != nil { - return Packages([]Package{}) + return types.Packages([]*types.Package{}) } defer bolt.Close() err = bolt.All(&packs) if err != nil { - return Packages([]Package{}) + return types.Packages([]*types.Package{}) } - models := make([]Package, len(packs)) + models := make([]*types.Package, len(packs)) for i, _ := range packs { models[i] = &packs[i] } - return Packages(models) + return types.Packages(models) } -func (db *BoltDatabase) FindPackageCandidate(p Package) (Package, error) { +func (db *BoltDatabase) FindPackageCandidate(p *types.Package) (*types.Package, error) { required, err := db.FindPackage(p) if err != nil { @@ -361,7 +371,7 @@ func (db *BoltDatabase) FindPackageCandidate(p Package) (Package, error) { } return required, err - //required = &DefaultPackage{Name: "test"} + //required = &*types.Package{Name: "test"} } return required, err @@ -370,24 +380,24 @@ func (db *BoltDatabase) FindPackageCandidate(p Package) (Package, error) { // FindPackages return the list of the packages beloging to cat/name (any versions in requested range) // FIXME: Optimize, see inmemorydb -func (db *BoltDatabase) FindPackages(p Package) (Packages, error) { +func (db *BoltDatabase) FindPackages(p *types.Package) (types.Packages, error) { if !p.IsSelector() { pack, err := db.FindPackage(p) if err != nil { - return []Package{}, err + return []*types.Package{}, err } - return []Package{pack}, nil + return []*types.Package{pack}, nil } // Provides: Treat as the replaced package here if provided, err := db.getProvide(p); err == nil { p = provided if !provided.IsSelector() { - return Packages{provided}, nil + return types.Packages{provided}, nil } } - var versionsInWorld []Package + var versionsInWorld []*types.Package for _, w := range db.World() { if w.GetName() != p.GetName() || w.GetCategory() != p.GetCategory() { continue @@ -401,17 +411,17 @@ func (db *BoltDatabase) FindPackages(p Package) (Packages, error) { versionsInWorld = append(versionsInWorld, w) } } - return Packages(versionsInWorld), nil + return types.Packages(versionsInWorld), nil } // FindPackageVersions return the list of the packages beloging to cat/name -func (db *BoltDatabase) FindPackageVersions(p Package) (Packages, error) { +func (db *BoltDatabase) FindPackageVersions(p *types.Package) (types.Packages, error) { // Provides: Treat as the replaced package here if provided, err := db.getProvide(p); err == nil { p = provided } - var versionsInWorld []Package + var versionsInWorld []*types.Package for _, w := range db.World() { if w.GetName() != p.GetName() || w.GetCategory() != p.GetCategory() { continue @@ -419,22 +429,22 @@ func (db *BoltDatabase) FindPackageVersions(p Package) (Packages, error) { versionsInWorld = append(versionsInWorld, w) } - return Packages(versionsInWorld), nil + return types.Packages(versionsInWorld), nil } -func (db *BoltDatabase) FindPackageLabel(labelKey string) (Packages, error) { - var ans []Package +func (db *BoltDatabase) FindPackageLabel(labelKey string) (types.Packages, error) { + var ans []*types.Package for _, pack := range db.World() { if pack.HasLabel(labelKey) { ans = append(ans, pack) } } - return Packages(ans), nil + return types.Packages(ans), nil } -func (db *BoltDatabase) FindPackageLabelMatch(pattern string) (Packages, error) { - var ans []Package +func (db *BoltDatabase) FindPackageLabelMatch(pattern string) (types.Packages, error) { + var ans []*types.Package re, err := regexp.Compile(pattern) if err != nil { @@ -447,14 +457,14 @@ func (db *BoltDatabase) FindPackageLabelMatch(pattern string) (Packages, error) } } - return Packages(ans), nil + return types.Packages(ans), nil } -func (db *BoltDatabase) FindPackageByFile(pattern string) (Packages, error) { +func (db *BoltDatabase) FindPackageByFile(pattern string) (types.Packages, error) { return findPackageByFile(db, pattern) } -func (db *BoltDatabase) FindPackageMatch(pattern string) (Packages, error) { - var ans []Package +func (db *BoltDatabase) FindPackageMatch(pattern string) (types.Packages, error) { + var ans []*types.Package re, err := regexp.Compile(pattern) if err != nil { @@ -467,5 +477,5 @@ func (db *BoltDatabase) FindPackageMatch(pattern string) (Packages, error) { } } - return Packages(ans), nil + return types.Packages(ans), nil } diff --git a/pkg/package/database_boltdb_test.go b/pkg/database/database_boltdb_test.go similarity index 55% rename from pkg/package/database_boltdb_test.go rename to pkg/database/database_boltdb_test.go index 04502c87..ed6e9a4b 100644 --- a/pkg/package/database_boltdb_test.go +++ b/pkg/database/database_boltdb_test.go @@ -13,14 +13,15 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg_test +package database_test import ( "io/ioutil" "os" "regexp" - . "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" + . "github.com/mudler/luet/pkg/database" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -29,7 +30,7 @@ var _ = Describe("BoltDB Database", func() { tmpfile, _ := ioutil.TempFile(os.TempDir(), "tests") defer os.Remove(tmpfile.Name()) // clean up - var db PackageDatabase + var db types.PackageDatabase BeforeEach(func() { tmpfile, _ = ioutil.TempFile(os.TempDir(), "tests") @@ -37,7 +38,7 @@ var _ = Describe("BoltDB Database", func() { db = NewBoltDatabase(tmpfile.Name()) }) Context("Simple package", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) It("Find packages", func() { ID, err := db.CreatePackage(a) @@ -58,9 +59,9 @@ var _ = Describe("BoltDB Database", func() { }) It("Find package files", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -70,10 +71,10 @@ var _ = Describe("BoltDB Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - err = db.SetPackageFiles(&PackageFile{PackageFingerprint: a.GetFingerPrint(), Files: []string{"foo"}}) + err = db.SetPackageFiles(&types.PackageFile{PackageFingerprint: a.GetFingerPrint(), Files: []string{"foo"}}) Expect(err).ToNot(HaveOccurred()) - err = db.SetPackageFiles(&PackageFile{PackageFingerprint: a1.GetFingerPrint(), Files: []string{"bar"}}) + err = db.SetPackageFiles(&types.PackageFile{PackageFingerprint: a1.GetFingerPrint(), Files: []string{"bar"}}) Expect(err).ToNot(HaveOccurred()) pack, err := db.FindPackageByFile("fo") @@ -84,12 +85,12 @@ var _ = Describe("BoltDB Database", func() { It("Expands correctly", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a11 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a01 := NewPackage("A", "0.1", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a11 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a01 := types.NewPackage("A", "0.1", []*types.Package{}, []*types.Package{}) re := regexp.MustCompile("project[0-9][=].*") - for _, p := range []Package{a1, a11, a01} { + for _, p := range []*types.Package{a1, a11, a01} { _, err := db.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -106,9 +107,9 @@ var _ = Describe("BoltDB Database", func() { }) It("Find best package candidate", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -117,7 +118,7 @@ var _ = Describe("BoltDB Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) pack, err := db.FindPackageCandidate(s) Expect(err).ToNot(HaveOccurred()) @@ -126,9 +127,9 @@ var _ = Describe("BoltDB Database", func() { }) It("Find specific package candidate", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -137,7 +138,7 @@ var _ = Describe("BoltDB Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "=1.0", []*types.Package{}, []*types.Package{}) pack, err := db.FindPackageCandidate(s) Expect(err).ToNot(HaveOccurred()) @@ -146,12 +147,12 @@ var _ = Describe("BoltDB Database", func() { }) It("Provides replaces definitions", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) - a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}) - Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})) + a3.SetProvides([]*types.Package{{Name: "A", Category: "", Version: "1.0"}}) + Expect(a3.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: "1.0"}})) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -162,7 +163,7 @@ var _ = Describe("BoltDB Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) pack, err := db.FindPackage(s) Expect(err).ToNot(HaveOccurred()) @@ -172,12 +173,12 @@ var _ = Describe("BoltDB Database", func() { Context("Provides", func() { It("replaces definitions", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) - a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}) - Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})) + a3.SetProvides([]*types.Package{{Name: "A", Category: "", Version: "1.0"}}) + Expect(a3.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: "1.0"}})) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -188,7 +189,7 @@ var _ = Describe("BoltDB Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) pack, err := db.FindPackage(s) Expect(err).ToNot(HaveOccurred()) @@ -196,12 +197,12 @@ var _ = Describe("BoltDB Database", func() { }) It("replaces definitions", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) - a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}) - Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})) + a3.SetProvides([]*types.Package{{Name: "A", Category: "", Version: "1.0"}}) + Expect(a3.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: "1.0"}})) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -212,7 +213,7 @@ var _ = Describe("BoltDB Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) @@ -220,12 +221,12 @@ var _ = Describe("BoltDB Database", func() { }) It("replaces definitions", func() { - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + z := types.NewPackage("Z", "1.3", []*types.Package{}, []*types.Package{}) - z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}) - Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})) + z.SetProvides([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}}) + Expect(z.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}})) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -236,7 +237,7 @@ var _ = Describe("BoltDB Database", func() { _, err = db.CreatePackage(z) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) @@ -244,11 +245,11 @@ var _ = Describe("BoltDB Database", func() { }) It("replaces definitions of unexisting packages", func() { - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + z := types.NewPackage("Z", "1.3", []*types.Package{}, []*types.Package{}) - z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}) - Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})) + z.SetProvides([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}}) + Expect(z.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}})) _, err := db.CreatePackage(a1) Expect(err).ToNot(HaveOccurred()) @@ -256,7 +257,7 @@ var _ = Describe("BoltDB Database", func() { _, err = db.CreatePackage(z) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) @@ -265,18 +266,18 @@ var _ = Describe("BoltDB Database", func() { It("replaces definitions of a required package", func() { - c := NewPackage("C", "1.1", []*DefaultPackage{{Name: "A", Category: "", Version: ">=0"}}, []*DefaultPackage{}) - z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + c := types.NewPackage("C", "1.1", []*types.Package{{Name: "A", Category: "", Version: ">=0"}}, []*types.Package{}) + z := types.NewPackage("Z", "1.3", []*types.Package{}, []*types.Package{}) - z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}) - Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})) + z.SetProvides([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}}) + Expect(z.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}})) _, err := db.CreatePackage(z) Expect(err).ToNot(HaveOccurred()) _, err = db.CreatePackage(c) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) @@ -286,18 +287,18 @@ var _ = Describe("BoltDB Database", func() { When("Searching with selectors", func() { It("replaces definitions of a required package", func() { - c := NewPackage("C", "1.1", []*DefaultPackage{{Name: "A", Category: "", Version: ">=0"}}, []*DefaultPackage{}) - z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + c := types.NewPackage("C", "1.1", []*types.Package{{Name: "A", Category: "", Version: ">=0"}}, []*types.Package{}) + z := types.NewPackage("Z", "1.3", []*types.Package{}, []*types.Package{}) - z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}) - Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})) + z.SetProvides([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}}) + Expect(z.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}})) _, err := db.CreatePackage(z) Expect(err).ToNot(HaveOccurred()) _, err = db.CreatePackage(c) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/package/database_common.go b/pkg/database/database_common.go similarity index 81% rename from pkg/package/database_common.go rename to pkg/database/database_common.go index 33dde553..5f9a1a2d 100644 --- a/pkg/package/database_common.go +++ b/pkg/database/database_common.go @@ -13,15 +13,16 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg +package database import ( "regexp" + "github.com/mudler/luet/pkg/api/core/types" "github.com/pkg/errors" ) -func clone(src, dst PackageDatabase) error { +func clone(src, dst types.PackageDatabase) error { for _, i := range src.World() { _, err := dst.CreatePackage(i) if err != nil { @@ -31,7 +32,7 @@ func clone(src, dst PackageDatabase) error { return nil } -func copy(src PackageDatabase) (PackageDatabase, error) { +func copy(src types.PackageDatabase) (types.PackageDatabase, error) { dst := NewInMemoryDatabase(false) if err := clone(src, dst); err != nil { @@ -41,9 +42,9 @@ func copy(src PackageDatabase) (PackageDatabase, error) { return dst, nil } -func findPackageByFile(db PackageDatabase, pattern string) (Packages, error) { +func findPackageByFile(db types.PackageDatabase, pattern string) (types.Packages, error) { - var ans []Package + var ans []*types.Package re, err := regexp.Compile(pattern) if err != nil { @@ -63,6 +64,6 @@ PACKAGE: } } - return Packages(ans), nil + return types.Packages(ans), nil } diff --git a/pkg/package/database_mem.go b/pkg/database/database_mem.go similarity index 70% rename from pkg/package/database_mem.go rename to pkg/database/database_mem.go index 6f95e164..aee0601a 100644 --- a/pkg/package/database_mem.go +++ b/pkg/database/database_mem.go @@ -1,4 +1,4 @@ -// Copyright © 2019 Ettore Di Giacinto +// Copyright © 2019-2022 Ettore Di Giacinto // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg +package database import ( "encoding/base64" @@ -22,6 +22,7 @@ import ( "regexp" "sync" + "github.com/mudler/luet/pkg/api/core/types" "github.com/pkg/errors" ) @@ -30,8 +31,8 @@ var DBInMemoryInstance = &InMemoryDatabase{ FileDatabase: map[string][]string{}, Database: map[string]string{}, CacheNoVersion: map[string]map[string]interface{}{}, - ProvidesDatabase: map[string]map[string]Package{}, - RevDepsDatabase: map[string]map[string]Package{}, + ProvidesDatabase: map[string]map[string]*types.Package{}, + RevDepsDatabase: map[string]map[string]*types.Package{}, cached: map[string]interface{}{}, } @@ -40,12 +41,12 @@ type InMemoryDatabase struct { Database map[string]string FileDatabase map[string][]string CacheNoVersion map[string]map[string]interface{} - ProvidesDatabase map[string]map[string]Package - RevDepsDatabase map[string]map[string]Package + ProvidesDatabase map[string]map[string]*types.Package + RevDepsDatabase map[string]map[string]*types.Package cached map[string]interface{} } -func NewInMemoryDatabase(singleton bool) PackageDatabase { +func NewInMemoryDatabase(singleton bool) types.PackageDatabase { // In memoryDB is a singleton if !singleton { return &InMemoryDatabase{ @@ -53,8 +54,8 @@ func NewInMemoryDatabase(singleton bool) PackageDatabase { FileDatabase: map[string][]string{}, Database: map[string]string{}, CacheNoVersion: map[string]map[string]interface{}{}, - ProvidesDatabase: map[string]map[string]Package{}, - RevDepsDatabase: map[string]map[string]Package{}, + ProvidesDatabase: map[string]map[string]*types.Package{}, + RevDepsDatabase: map[string]map[string]*types.Package{}, cached: map[string]interface{}{}, } } @@ -98,19 +99,19 @@ func (db *InMemoryDatabase) Retrieve(ID string) ([]byte, error) { return enc, nil } -func (db *InMemoryDatabase) GetPackage(ID string) (Package, error) { +func (db *InMemoryDatabase) GetPackage(ID string) (*types.Package, error) { enc, err := db.Retrieve(ID) if err != nil { return nil, err } - p := &DefaultPackage{} + p := &types.Package{} rawIn := json.RawMessage(enc) bytes, err := rawIn.MarshalJSON() if err != nil { - return &DefaultPackage{}, err + return p, err } if err := json.Unmarshal(bytes, &p); err != nil { @@ -119,7 +120,7 @@ func (db *InMemoryDatabase) GetPackage(ID string) (Package, error) { return p, nil } -func (db *InMemoryDatabase) GetAllPackages(packages chan Package) error { +func (db *InMemoryDatabase) GetAllPackages(packages chan *types.Package) error { packs := db.GetPackages() for _, p := range packs { pack, err := db.GetPackage(p) @@ -131,14 +132,14 @@ func (db *InMemoryDatabase) GetAllPackages(packages chan Package) error { return nil } -func (db *InMemoryDatabase) getRevdeps(p Package, visited map[string]interface{}) (Packages, error) { - var versionsInWorld Packages +func (db *InMemoryDatabase) getRevdeps(p *types.Package, visited map[string]interface{}) (types.Packages, error) { + var versionsInWorld types.Packages if _, ok := visited[p.HumanReadableString()]; ok { return versionsInWorld, nil } visited[p.HumanReadableString()] = true - var res Packages + var res types.Packages packs, err := db.FindPackages(p) if err != nil { return res, err @@ -169,43 +170,38 @@ func (db *InMemoryDatabase) getRevdeps(p Package, visited map[string]interface{} // GetRevdeps returns the package reverse dependencies, // matching also selectors in versions (>, <, >=, <=) // TODO: Code should use db explictly -func (db *InMemoryDatabase) GetRevdeps(p Package) (Packages, error) { +func (db *InMemoryDatabase) GetRevdeps(p *types.Package) (types.Packages, error) { return db.getRevdeps(p, make(map[string]interface{})) } // Encode encodes the package to string. // It returns an ID which can be used to retrieve the package later on. -func (db *InMemoryDatabase) CreatePackage(p Package) (string, error) { - pd, ok := p.(*DefaultPackage) - if !ok { - return "", errors.New("InMemoryDatabase suports only DefaultPackage") - } +func (db *InMemoryDatabase) CreatePackage(p *types.Package) (string, error) { - res, err := pd.JSON() + res, err := p.JSON() if err != nil { return "", err } - ID, err := db.Create(pd.GetFingerPrint(), res) + ID, err := db.Create(p.GetFingerPrint(), res) if err != nil { return "", err } - db.populateCaches(pd) + db.populateCaches(p) return ID, nil } -func (db *InMemoryDatabase) updateRevDep(k, v string, b Package) { +func (db *InMemoryDatabase) updateRevDep(k, v string, b *types.Package) { _, ok := db.RevDepsDatabase[k] if !ok { - db.RevDepsDatabase[k] = make(map[string]Package) + db.RevDepsDatabase[k] = make(map[string]*types.Package) } db.RevDepsDatabase[k][v] = b.Clone() } -func (db *InMemoryDatabase) populateCaches(p Package) { - pd, _ := p.(*DefaultPackage) +func (db *InMemoryDatabase) populateCaches(pd *types.Package) { // Create extra cache between package -> []versions db.Lock() @@ -213,27 +209,27 @@ func (db *InMemoryDatabase) populateCaches(p Package) { db.cached = map[string]interface{}{} } - if _, ok := db.cached[p.GetFingerPrint()]; ok { + if _, ok := db.cached[pd.GetFingerPrint()]; ok { db.Unlock() return } - db.cached[p.GetFingerPrint()] = nil + db.cached[pd.GetFingerPrint()] = nil // Provides: Store package provides, we will reuse this when walking deps for _, provide := range pd.Provides { if _, ok := db.ProvidesDatabase[provide.GetPackageName()]; !ok { - db.ProvidesDatabase[provide.GetPackageName()] = make(map[string]Package) + db.ProvidesDatabase[provide.GetPackageName()] = make(map[string]*types.Package) } - db.ProvidesDatabase[provide.GetPackageName()][provide.GetVersion()] = p + db.ProvidesDatabase[provide.GetPackageName()][provide.GetVersion()] = pd } - _, ok := db.CacheNoVersion[p.GetPackageName()] + _, ok := db.CacheNoVersion[pd.GetPackageName()] if !ok { - db.CacheNoVersion[p.GetPackageName()] = make(map[string]interface{}) + db.CacheNoVersion[pd.GetPackageName()] = make(map[string]interface{}) } - db.CacheNoVersion[p.GetPackageName()][p.GetVersion()] = nil + db.CacheNoVersion[pd.GetPackageName()][pd.GetVersion()] = nil db.Unlock() @@ -267,7 +263,7 @@ func (db *InMemoryDatabase) populateCaches(p Package) { } } -func (db *InMemoryDatabase) getProvide(p Package) (Package, error) { +func (db *InMemoryDatabase) getProvide(p *types.Package) (*types.Package, error) { db.Lock() @@ -302,30 +298,25 @@ func (db *InMemoryDatabase) getProvide(p Package) (Package, error) { return db.FindPackage(pa) } -func (db *InMemoryDatabase) Clone(to PackageDatabase) error { +func (db *InMemoryDatabase) Clone(to types.PackageDatabase) error { return clone(db, to) } -func (db *InMemoryDatabase) Copy() (PackageDatabase, error) { +func (db *InMemoryDatabase) Copy() (types.PackageDatabase, error) { return copy(db) } -func (db *InMemoryDatabase) encodePackage(p Package) (string, string, error) { - pd, ok := p.(*DefaultPackage) - if !ok { - return "", "", errors.New("InMemoryDatabase suports only DefaultPackage") - } - +func (db *InMemoryDatabase) encodePackage(pd *types.Package) (string, string, error) { res, err := pd.JSON() if err != nil { return "", "", err } enc := base64.StdEncoding.EncodeToString(res) - return p.GetFingerPrint(), enc, nil + return pd.GetFingerPrint(), enc, nil } -func (db *InMemoryDatabase) FindPackage(p Package) (Package, error) { +func (db *InMemoryDatabase) FindPackage(p *types.Package) (*types.Package, error) { // Provides: Return the replaced package here if provided, err := db.getProvide(p); err == nil { @@ -336,7 +327,7 @@ func (db *InMemoryDatabase) FindPackage(p Package) (Package, error) { } // FindPackages return the list of the packages beloging to cat/name -func (db *InMemoryDatabase) FindPackageVersions(p Package) (Packages, error) { +func (db *InMemoryDatabase) FindPackageVersions(p *types.Package) (types.Packages, error) { // Provides: Treat as the replaced package here if provided, err := db.getProvide(p); err == nil { p = provided @@ -347,48 +338,48 @@ func (db *InMemoryDatabase) FindPackageVersions(p Package) (Packages, error) { if !ok { return nil, errors.New("No versions found for package") } - var versionsInWorld []Package + var versionsInWorld []*types.Package for ve, _ := range versions { - w, err := db.FindPackage(&DefaultPackage{Name: p.GetName(), Category: p.GetCategory(), Version: ve}) + w, err := db.FindPackage(&types.Package{Name: p.GetName(), Category: p.GetCategory(), Version: ve}) if err != nil { return nil, errors.Wrap(err, "Cache mismatch - this shouldn't happen") } versionsInWorld = append(versionsInWorld, w) } - return Packages(versionsInWorld), nil + return types.Packages(versionsInWorld), nil } // FindPackages return the list of the packages beloging to cat/name (any versions in requested range) -func (db *InMemoryDatabase) FindPackages(p Package) (Packages, error) { +func (db *InMemoryDatabase) FindPackages(p *types.Package) (types.Packages, error) { if !p.IsSelector() { pack, err := db.FindPackage(p) if err != nil { - return []Package{}, err + return []*types.Package{}, err } - return []Package{pack}, nil + return []*types.Package{pack}, nil } // Provides: Treat as the replaced package here if provided, err := db.getProvide(p); err == nil { p = provided if !provided.IsSelector() { - return Packages{provided}, nil + return types.Packages{provided}, nil } } db.Lock() - var matches []*DefaultPackage + var matches []*types.Package versions, ok := db.CacheNoVersion[p.GetPackageName()] for ve := range versions { match, _ := p.SelectorMatchVersion(ve, nil) if match { - matches = append(matches, &DefaultPackage{Name: p.GetName(), Category: p.GetCategory(), Version: ve}) + matches = append(matches, &types.Package{Name: p.GetName(), Category: p.GetCategory(), Version: ve}) } } db.Unlock() if !ok { - return nil, errors.New(fmt.Sprintf("No versions found for: %s", p.HumanReadableString())) + return nil, fmt.Errorf("No versions found for: %s", p.HumanReadableString()) } - var versionsInWorld []Package + var versionsInWorld []*types.Package for _, p := range matches { w, err := db.FindPackage(p) if err != nil { @@ -396,10 +387,10 @@ func (db *InMemoryDatabase) FindPackages(p Package) (Packages, error) { } versionsInWorld = append(versionsInWorld, w) } - return Packages(versionsInWorld), nil + return types.Packages(versionsInWorld), nil } -func (db *InMemoryDatabase) UpdatePackage(p Package) error { +func (db *InMemoryDatabase) UpdatePackage(p *types.Package) error { _, enc, err := db.encodePackage(p) if err != nil { @@ -407,15 +398,13 @@ func (db *InMemoryDatabase) UpdatePackage(p Package) error { } return db.Set(p.GetFingerPrint(), enc) - - return errors.New(fmt.Sprintf("Package not found: %s", p.HumanReadableString())) } func (db *InMemoryDatabase) GetPackages() []string { keys := []string{} db.Lock() defer db.Unlock() - for k, _ := range db.Database { + for k := range db.Database { keys = append(keys, k) } return keys @@ -426,40 +415,40 @@ func (db *InMemoryDatabase) Clean() error { return nil } -func (db *InMemoryDatabase) GetPackageFiles(p Package) ([]string, error) { +func (db *InMemoryDatabase) GetPackageFiles(p *types.Package) ([]string, error) { db.Lock() defer db.Unlock() pa, ok := db.FileDatabase[p.GetFingerPrint()] if !ok { - return pa, errors.New(fmt.Sprintf("No key found for: %s", p.HumanReadableString())) + return pa, fmt.Errorf("No key found for: %s", p.HumanReadableString()) } return pa, nil } -func (db *InMemoryDatabase) SetPackageFiles(p *PackageFile) error { +func (db *InMemoryDatabase) SetPackageFiles(p *types.PackageFile) error { db.Lock() defer db.Unlock() db.FileDatabase[p.PackageFingerprint] = p.Files return nil } -func (db *InMemoryDatabase) RemovePackageFiles(p Package) error { +func (db *InMemoryDatabase) RemovePackageFiles(p *types.Package) error { db.Lock() defer db.Unlock() delete(db.FileDatabase, p.GetFingerPrint()) return nil } -func (db *InMemoryDatabase) RemovePackage(p Package) error { +func (db *InMemoryDatabase) RemovePackage(p *types.Package) error { db.Lock() defer db.Unlock() delete(db.Database, p.GetFingerPrint()) return nil } -func (db *InMemoryDatabase) World() Packages { - var all []Package +func (db *InMemoryDatabase) World() types.Packages { + var all []*types.Package // FIXME: This should all be locked in the db - for now forbid the solver to be run in threads. for _, k := range db.GetPackages() { pack, err := db.GetPackage(k) @@ -467,10 +456,10 @@ func (db *InMemoryDatabase) World() Packages { all = append(all, pack) } } - return Packages(all) + return types.Packages(all) } -func (db *InMemoryDatabase) FindPackageCandidate(p Package) (Package, error) { +func (db *InMemoryDatabase) FindPackageCandidate(p *types.Package) (*types.Package, error) { required, err := db.FindPackage(p) if err != nil { @@ -485,15 +474,15 @@ func (db *InMemoryDatabase) FindPackageCandidate(p Package) (Package, error) { required = packages.Best(nil) } return required, err - //required = &DefaultPackage{Name: "test"} + //required = &types.Package{Name: "test"} } return required, err } -func (db *InMemoryDatabase) FindPackageLabel(labelKey string) (Packages, error) { - var ans []Package +func (db *InMemoryDatabase) FindPackageLabel(labelKey string) (types.Packages, error) { + var ans []*types.Package for _, k := range db.GetPackages() { pack, err := db.GetPackage(k) @@ -505,11 +494,11 @@ func (db *InMemoryDatabase) FindPackageLabel(labelKey string) (Packages, error) } } - return Packages(ans), nil + return types.Packages(ans), nil } -func (db *InMemoryDatabase) FindPackageLabelMatch(pattern string) (Packages, error) { - var ans []Package +func (db *InMemoryDatabase) FindPackageLabelMatch(pattern string) (types.Packages, error) { + var ans []*types.Package re := regexp.MustCompile(pattern) if re == nil { @@ -526,11 +515,11 @@ func (db *InMemoryDatabase) FindPackageLabelMatch(pattern string) (Packages, err } } - return Packages(ans), nil + return types.Packages(ans), nil } -func (db *InMemoryDatabase) FindPackageMatch(pattern string) (Packages, error) { - var ans []Package +func (db *InMemoryDatabase) FindPackageMatch(pattern string) (types.Packages, error) { + var ans []*types.Package re := regexp.MustCompile(pattern) if re == nil { @@ -548,9 +537,9 @@ func (db *InMemoryDatabase) FindPackageMatch(pattern string) (Packages, error) { } } - return Packages(ans), nil + return types.Packages(ans), nil } -func (db *InMemoryDatabase) FindPackageByFile(pattern string) (Packages, error) { +func (db *InMemoryDatabase) FindPackageByFile(pattern string) (types.Packages, error) { return findPackageByFile(db, pattern) } diff --git a/pkg/package/database_mem_test.go b/pkg/database/database_mem_test.go similarity index 54% rename from pkg/package/database_mem_test.go rename to pkg/database/database_mem_test.go index 5d991c3e..ebe950b6 100644 --- a/pkg/package/database_mem_test.go +++ b/pkg/database/database_mem_test.go @@ -13,10 +13,12 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg_test +package database_test import ( - . "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" + + . "github.com/mudler/luet/pkg/database" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -25,10 +27,10 @@ var _ = Describe("Database", func() { db := NewInMemoryDatabase(false) Context("Simple package", func() { - a := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) - // a1 := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - // a11 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - // a01 := NewPackage("A", "0.1", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) + // a1 := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + // a11 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + // a01 := types.NewPackage("A", "0.1", []*types.Package{}, []*types.Package{}) It("Saves and get data back correctly", func() { ID, err := db.CreatePackage(a) @@ -58,9 +60,9 @@ var _ = Describe("Database", func() { It("Find best package candidate", func() { db := NewInMemoryDatabase(false) - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -69,7 +71,7 @@ var _ = Describe("Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) pack, err := db.FindPackageCandidate(s) Expect(err).ToNot(HaveOccurred()) @@ -79,9 +81,9 @@ var _ = Describe("Database", func() { It("Find package files", func() { db := NewInMemoryDatabase(false) - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -91,10 +93,10 @@ var _ = Describe("Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - err = db.SetPackageFiles(&PackageFile{PackageFingerprint: a.GetFingerPrint(), Files: []string{"foo"}}) + err = db.SetPackageFiles(&types.PackageFile{PackageFingerprint: a.GetFingerPrint(), Files: []string{"foo"}}) Expect(err).ToNot(HaveOccurred()) - err = db.SetPackageFiles(&PackageFile{PackageFingerprint: a1.GetFingerPrint(), Files: []string{"bar"}}) + err = db.SetPackageFiles(&types.PackageFile{PackageFingerprint: a1.GetFingerPrint(), Files: []string{"bar"}}) Expect(err).ToNot(HaveOccurred()) pack, err := db.FindPackageByFile("fo") @@ -105,9 +107,9 @@ var _ = Describe("Database", func() { It("Find specific package candidate", func() { db := NewInMemoryDatabase(false) - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -116,7 +118,7 @@ var _ = Describe("Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "=1.0", []*types.Package{}, []*types.Package{}) pack, err := db.FindPackageCandidate(s) Expect(err).ToNot(HaveOccurred()) @@ -128,12 +130,12 @@ var _ = Describe("Database", func() { It("replaces definitions", func() { db := NewInMemoryDatabase(false) - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) - a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}) - Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})) + a3.SetProvides([]*types.Package{{Name: "A", Category: "", Version: "1.0"}}) + Expect(a3.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: "1.0"}})) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -144,7 +146,7 @@ var _ = Describe("Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) pack, err := db.FindPackage(s) Expect(err).ToNot(HaveOccurred()) @@ -153,12 +155,12 @@ var _ = Describe("Database", func() { It("replaces definitions", func() { db := NewInMemoryDatabase(false) - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - a3 := NewPackage("A", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + a3 := types.NewPackage("A", "1.3", []*types.Package{}, []*types.Package{}) - a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}) - Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})) + a3.SetProvides([]*types.Package{{Name: "A", Category: "", Version: "1.0"}}) + Expect(a3.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: "1.0"}})) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -169,7 +171,7 @@ var _ = Describe("Database", func() { _, err = db.CreatePackage(a3) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) @@ -178,12 +180,12 @@ var _ = Describe("Database", func() { It("replaces definitions", func() { db := NewInMemoryDatabase(false) - a := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + z := types.NewPackage("Z", "1.3", []*types.Package{}, []*types.Package{}) - z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}) - Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})) + z.SetProvides([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}}) + Expect(z.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}})) _, err := db.CreatePackage(a) Expect(err).ToNot(HaveOccurred()) @@ -194,7 +196,7 @@ var _ = Describe("Database", func() { _, err = db.CreatePackage(z) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) @@ -203,11 +205,11 @@ var _ = Describe("Database", func() { It("replaces definitions of unexisting packages", func() { db := NewInMemoryDatabase(false) - a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{}) - z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + a1 := types.NewPackage("A", "1.1", []*types.Package{}, []*types.Package{}) + z := types.NewPackage("Z", "1.3", []*types.Package{}, []*types.Package{}) - z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}) - Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})) + z.SetProvides([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}}) + Expect(z.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}})) _, err := db.CreatePackage(a1) Expect(err).ToNot(HaveOccurred()) @@ -215,7 +217,7 @@ var _ = Describe("Database", func() { _, err = db.CreatePackage(z) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) @@ -225,18 +227,18 @@ var _ = Describe("Database", func() { It("replaces definitions of a required package", func() { db := NewInMemoryDatabase(false) - c := NewPackage("C", "1.1", []*DefaultPackage{{Name: "A", Category: "", Version: ">=0"}}, []*DefaultPackage{}) - z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + c := types.NewPackage("C", "1.1", []*types.Package{{Name: "A", Category: "", Version: ">=0"}}, []*types.Package{}) + z := types.NewPackage("Z", "1.3", []*types.Package{}, []*types.Package{}) - z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}) - Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})) + z.SetProvides([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}}) + Expect(z.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}})) _, err := db.CreatePackage(z) Expect(err).ToNot(HaveOccurred()) _, err = db.CreatePackage(c) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", "1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) @@ -247,18 +249,18 @@ var _ = Describe("Database", func() { It("replaces definitions of a required package", func() { db := NewInMemoryDatabase(false) - c := NewPackage("C", "1.1", []*DefaultPackage{{Name: "A", Category: "", Version: ">=0"}}, []*DefaultPackage{}) - z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{}) + c := types.NewPackage("C", "1.1", []*types.Package{{Name: "A", Category: "", Version: ">=0"}}, []*types.Package{}) + z := types.NewPackage("Z", "1.3", []*types.Package{}, []*types.Package{}) - z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}) - Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})) + z.SetProvides([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}}) + Expect(z.GetProvides()).To(Equal([]*types.Package{{Name: "A", Category: "", Version: ">=1.0"}})) _, err := db.CreatePackage(z) Expect(err).ToNot(HaveOccurred()) _, err = db.CreatePackage(c) Expect(err).ToNot(HaveOccurred()) - s := NewPackage("A", ">=1.0", []*DefaultPackage{}, []*DefaultPackage{}) + s := types.NewPackage("A", ">=1.0", []*types.Package{}, []*types.Package{}) packs, err := db.FindPackages(s) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/database/migrations.go b/pkg/database/migrations.go new file mode 100644 index 00000000..1289392b --- /dev/null +++ b/pkg/database/migrations.go @@ -0,0 +1,40 @@ +// Copyright © 2022 Ettore Di Giacinto +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . + +package database + +import "go.etcd.io/bbolt" + +type schemaMigration func(tx *bbolt.Tx) error + +var migrations = []schemaMigration{migrateDefaultPackage} + +var migrateDefaultPackage schemaMigration = func(tx *bbolt.Tx) error { + // previously we had pkg.DefaultPackage + // IF it's there, rename it to the proper bucket + b := tx.Bucket([]byte("DefaultPackage")) + if b != nil { + newB, err := tx.CreateBucket([]byte("Package")) + if err != nil { + return nil + } + b.ForEach(func(k, v []byte) error { + return newB.Put(k, v) + }) + + tx.DeleteBucket([]byte("DefaultPackage")) + } + return nil +} diff --git a/pkg/package/package_suite_test.go b/pkg/database/package_suite_test.go similarity index 97% rename from pkg/package/package_suite_test.go rename to pkg/database/package_suite_test.go index 1f264e59..50851a5b 100644 --- a/pkg/package/package_suite_test.go +++ b/pkg/database/package_suite_test.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with this program; if not, see . -package pkg_test +package database_test import ( "testing" diff --git a/pkg/helpers/match/match.go b/pkg/helpers/match/match.go deleted file mode 100644 index bb932b82..00000000 --- a/pkg/helpers/match/match.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright © 2019-2020 Ettore Di Giacinto -// Daniele Rondina -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, see . - -package match - -import ( - "reflect" - "regexp" -) - -func ReverseAny(s interface{}) { - n := reflect.ValueOf(s).Len() - swap := reflect.Swapper(s) - for i, j := 0, n-1; i < j; i, j = i+1, j-1 { - swap(i, j) - } -} - -func MapMatchRegex(m *map[string]string, r *regexp.Regexp) bool { - ans := false - - if m != nil { - for k, v := range *m { - if r.MatchString(k + "=" + v) { - ans = true - break - } - } - } - - return ans -} - -func MapHasKey(m *map[string]string, label string) bool { - ans := false - if m != nil { - for k, _ := range *m { - if k == label { - ans = true - break - } - } - } - return ans -} diff --git a/pkg/helpers/references.go b/pkg/helpers/references.go index 6a9e0fec..e441bbef 100644 --- a/pkg/helpers/references.go +++ b/pkg/helpers/references.go @@ -1,5 +1,4 @@ -// Copyright © 2019-2020 Ettore Di Giacinto -// David Cassany +// Copyright © 2019-2022 Ettore Di Giacinto // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -18,18 +17,8 @@ package helpers import ( "strings" - - "github.com/asaskevich/govalidator" ) -func StripRegistryFromImage(image string) string { - img := strings.SplitN(image, "/", 2) - if len(img) == 2 && govalidator.IsURL(img[0]) { - return img[1] - } - return image -} - func SanitizeImageString(s string) string { return strings.ReplaceAll(s, "+", "-") } diff --git a/pkg/helpers/references_test.go b/pkg/helpers/references_test.go index 53c0c5bf..678e794b 100644 --- a/pkg/helpers/references_test.go +++ b/pkg/helpers/references_test.go @@ -1,5 +1,4 @@ -// Copyright © 2019-2020 Ettore Di Giacinto -// David Cassany +// Copyright © 2019-2022 Ettore Di Giacinto // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -28,22 +27,4 @@ var _ = Describe("Helpers", func() { Expect(SanitizeImageString("foo+bar")).To(Equal("foo-bar")) }) }) - Context("StripRegistryFromImage", func() { - It("Strips the domain name", func() { - out := StripRegistryFromImage("valid.domain.org/base/image:tag") - Expect(out).To(Equal("base/image:tag")) - }) - It("Strips the domain name when port is included", func() { - out := StripRegistryFromImage("valid.domain.org:5000/base/image:tag") - Expect(out).To(Equal("base/image:tag")) - }) - It("Does not strip the domain name", func() { - out := StripRegistryFromImage("not-a-domain/base/image:tag") - Expect(out).To(Equal("not-a-domain/base/image:tag")) - }) - It("Does not strip the domain name on invalid domains", func() { - out := StripRegistryFromImage("-invaliddomain.org/base/image:tag") - Expect(out).To(Equal("-invaliddomain.org/base/image:tag")) - }) - }) }) diff --git a/pkg/helpers/slice.go b/pkg/helpers/slice.go index d7bb04d1..28e105e5 100644 --- a/pkg/helpers/slice.go +++ b/pkg/helpers/slice.go @@ -1,5 +1,22 @@ +// Copyright © 2019-2022 Ettore Di Giacinto +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . + package helpers +import "reflect" + func Contains(s []string, e string) bool { for _, a := range s { if a == e { @@ -8,3 +25,11 @@ func Contains(s []string, e string) bool { } return false } + +func ReverseAny(s interface{}) { + n := reflect.ValueOf(s).Len() + swap := reflect.Swapper(s) + for i, j := 0, n-1; i < j; i, j = i+1, j-1 { + swap(i, j) + } +} diff --git a/pkg/installer/cli.go b/pkg/installer/cli.go index a9a6cdd6..44eae419 100644 --- a/pkg/installer/cli.go +++ b/pkg/installer/cli.go @@ -20,11 +20,11 @@ import ( "sort" "strings" - pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" "github.com/pterm/pterm" ) -func packsToList(p pkg.Packages) string { +func packsToList(p types.Packages) string { var packs []string for _, pp := range p { @@ -35,7 +35,7 @@ func packsToList(p pkg.Packages) string { return strings.Join(packs, " ") } -func printList(p pkg.Packages) { +func printList(p types.Packages) { fmt.Println() d := pterm.TableData{{"Program Name", "Version", "License"}} for _, m := range p { @@ -47,7 +47,7 @@ func printList(p pkg.Packages) { fmt.Println() } -func printUpgradeList(install, uninstall pkg.Packages) { +func printUpgradeList(install, uninstall types.Packages) { fmt.Println() d := pterm.TableData{{"Old version", "New version", "License"}} @@ -72,8 +72,8 @@ func printUpgradeList(install, uninstall pkg.Packages) { } -func printMatchUpgrade(artefacts map[string]ArtifactMatch, uninstall pkg.Packages) { - p := pkg.Packages{} +func printMatchUpgrade(artefacts map[string]ArtifactMatch, uninstall types.Packages) { + p := types.Packages{} for _, a := range artefacts { p = append(p, a.Package) diff --git a/pkg/installer/client/docker_test.go b/pkg/installer/client/docker_test.go index ffa766fd..93465ecd 100644 --- a/pkg/installer/client/docker_test.go +++ b/pkg/installer/client/docker_test.go @@ -20,13 +20,13 @@ import ( "os" "path/filepath" + "github.com/mudler/luet/pkg/api/core/types" + "github.com/mudler/luet/pkg/api/core/context" "github.com/mudler/luet/pkg/api/core/types/artifact" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" - . "github.com/mudler/luet/pkg/installer/client" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -62,7 +62,7 @@ var _ = Describe("Docker client", func() { f, err := c.DownloadArtifact(&artifact.PackageArtifact{ Path: "test.tar", CompileSpec: &compilerspec.LuetCompilationSpec{ - Package: &pkg.DefaultPackage{ + Package: &types.Package{ Name: "c", Category: "test", Version: "1.0", diff --git a/pkg/installer/installer.go b/pkg/installer/installer.go index 4e39beea..f58a1062 100644 --- a/pkg/installer/installer.go +++ b/pkg/installer/installer.go @@ -26,13 +26,13 @@ import ( "github.com/mudler/luet/pkg/api/core/config" "github.com/mudler/luet/pkg/api/core/logger" + "github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/api/core/bus" "github.com/mudler/luet/pkg/api/core/types" artifact "github.com/mudler/luet/pkg/api/core/types/artifact" + pkg "github.com/mudler/luet/pkg/database" fileHelper "github.com/mudler/luet/pkg/helpers/file" - "github.com/mudler/luet/pkg/helpers/match" - pkg "github.com/mudler/luet/pkg/package" "github.com/mudler/luet/pkg/solver" "github.com/pterm/pterm" @@ -63,7 +63,7 @@ type LuetInstaller struct { } type ArtifactMatch struct { - Package pkg.Package + Package *types.Package Artifact *artifact.PackageArtifact Repository Repository } @@ -74,16 +74,21 @@ func NewLuetInstaller(opts LuetInstallerOptions) *LuetInstaller { // computeUpgrade returns the packages to be uninstalled and installed in a system to perform an upgrade // based on the system repositories -func (l *LuetInstaller) computeUpgrade(syncedRepos Repositories, s *System) (pkg.Packages, pkg.Packages, error) { - toInstall := pkg.Packages{} - var uninstall pkg.Packages +func (l *LuetInstaller) computeUpgrade(syncedRepos Repositories, s *System) (types.Packages, types.Packages, error) { + toInstall := types.Packages{} + var uninstall types.Packages var err error // First match packages against repositories by priority allRepos := pkg.NewInMemoryDatabase(false) syncedRepos.SyncDatabase(allRepos) // compute a "big" world - solv := solver.NewResolver(solver.Options{Type: l.Options.SolverOptions.Implementation, Concurrency: l.Options.Concurrency}, s.Database, allRepos, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver()) - var solution solver.PackagesAssertions + solv := solver.NewResolver( + types.SolverOptions{ + Type: l.Options.SolverOptions.Implementation, + Concurrency: l.Options.Concurrency}, + s.Database, allRepos, pkg.NewInMemoryDatabase(false), + solver.NewSolverFromOptions(l.Options.SolverOptions)) + var solution types.PackagesAssertions if l.Options.SolverUpgrade { uninstall, solution, err = solv.UpgradeUniverse(l.Options.RemoveUnavailableOnUpgrade) @@ -106,7 +111,7 @@ func (l *LuetInstaller) computeUpgrade(syncedRepos Repositories, s *System) (pkg if l.Options.UpgradeNewRevisions { for _, p := range s.Database.World() { - matches := syncedRepos.PackageMatches(pkg.Packages{p}) + matches := syncedRepos.PackageMatches(types.Packages{p}) if len(matches) == 0 { // Package missing. the user should run luet upgrade --universe continue @@ -161,13 +166,13 @@ func (l *LuetInstaller) SyncRepositories() (Repositories, error) { return syncedRepos, nil } -func (l *LuetInstaller) Swap(toRemove pkg.Packages, toInstall pkg.Packages, s *System) error { +func (l *LuetInstaller) Swap(toRemove types.Packages, toInstall types.Packages, s *System) error { syncedRepos, err := l.SyncRepositories() if err != nil { return err } - toRemoveFinal := pkg.Packages{} + toRemoveFinal := types.Packages{} for _, p := range toRemove { packs, _ := s.Database.FindPackages(p) if len(packs) == 0 { @@ -189,7 +194,7 @@ func (l *LuetInstaller) Swap(toRemove pkg.Packages, toInstall pkg.Packages, s *S return l.swap(o, syncedRepos, toRemoveFinal, toInstall, s) } -func (l *LuetInstaller) computeSwap(o Option, syncedRepos Repositories, toRemove pkg.Packages, toInstall pkg.Packages, s *System) (map[string]ArtifactMatch, pkg.Packages, solver.PackagesAssertions, pkg.PackageDatabase, error) { +func (l *LuetInstaller) computeSwap(o Option, syncedRepos Repositories, toRemove types.Packages, toInstall types.Packages, s *System) (map[string]ArtifactMatch, types.Packages, types.PackagesAssertions, types.PackageDatabase, error) { allRepos := pkg.NewInMemoryDatabase(false) syncedRepos.SyncDatabase(allRepos) @@ -218,12 +223,12 @@ func (l *LuetInstaller) computeSwap(o Option, syncedRepos Repositories, toRemove match, packages, assertions, allRepos, err := l.computeInstall(o, syncedRepos, toInstall, systemAfterChanges) for _, p := range toInstall { - assertions = append(assertions, solver.PackageAssert{Package: p.(*pkg.DefaultPackage), Value: true}) + assertions = append(assertions, types.PackageAssert{Package: p, Value: true}) } return match, packages, assertions, allRepos, err } -func (l *LuetInstaller) swap(o Option, syncedRepos Repositories, toRemove pkg.Packages, toInstall pkg.Packages, s *System) error { +func (l *LuetInstaller) swap(o Option, syncedRepos Repositories, toRemove types.Packages, toInstall types.Packages, s *System) error { match, packages, assertions, allRepos, err := l.computeSwap(o, syncedRepos, toRemove, toInstall, s) if err != nil { @@ -306,15 +311,15 @@ type Option struct { type operation struct { Option Option - Package pkg.Package + Package *types.Package } type installOperation struct { operation Reposiories Repositories - Packages pkg.Packages - Assertions solver.PackagesAssertions - Database pkg.PackageDatabase + Packages types.Packages + Assertions types.PackagesAssertions + Database types.PackageDatabase Matches map[string]ArtifactMatch } @@ -399,8 +404,8 @@ func (l *LuetInstaller) installerOpWorker(i int, wg *sync.WaitGroup, systemLock pp.Option, pp.Reposiories, map[string]ArtifactMatch{pp.Package.GetFingerPrint(): artMatch}, - pkg.Packages{packageToInstall}, - solver.PackagesAssertions{*ass}, + types.Packages{packageToInstall}, + types.PackagesAssertions{*ass}, pp.Database, s, ) @@ -416,8 +421,8 @@ func (l *LuetInstaller) installerOpWorker(i int, wg *sync.WaitGroup, systemLock // checks wheter we can uninstall and install in place and compose installer worker ops func (l *LuetInstaller) generateRunOps( - toUninstall pkg.Packages, installMatch map[string]ArtifactMatch, installOpt, uninstallOpt Option, - syncedRepos Repositories, toInstall pkg.Packages, solution solver.PackagesAssertions, allRepos pkg.PackageDatabase, s *System) (resOps []installerOp, err error) { + toUninstall types.Packages, installMatch map[string]ArtifactMatch, installOpt, uninstallOpt Option, + syncedRepos Repositories, toInstall types.Packages, solution types.PackagesAssertions, allRepos types.PackageDatabase, s *System) (resOps []installerOp, err error) { uOpts := []operation{} for _, u := range toUninstall { @@ -485,13 +490,13 @@ func (l *LuetInstaller) checkAndUpgrade(r Repositories, s *System) error { } } - bus.Manager.Publish(bus.EventPreUpgrade, struct{ Uninstall, Install pkg.Packages }{Uninstall: uninstall, Install: toInstall}) + bus.Manager.Publish(bus.EventPreUpgrade, struct{ Uninstall, Install types.Packages }{Uninstall: uninstall, Install: toInstall}) err = l.swap(o, r, uninstall, toInstall, s) bus.Manager.Publish(bus.EventPostUpgrade, struct { Error error - Uninstall, Install pkg.Packages + Uninstall, Install types.Packages }{Uninstall: uninstall, Install: toInstall, Error: err}) if err != nil { @@ -515,7 +520,7 @@ func (l *LuetInstaller) checkAndUpgrade(r Repositories, s *System) error { return err } -func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error { +func (l *LuetInstaller) Install(cp types.Packages, s *System) error { l.Options.Context.Screen("Install") syncedRepos, err := l.SyncRepositories() if err != nil { @@ -547,7 +552,7 @@ func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error { return nil } // Resolvers might decide to remove some packages from being installed - if !l.Options.SolverOptions.ResolverIsSet() { + if l.Options.SolverOptions.Type != solver.QLearningResolverType { for _, p := range cp { found := false vers, _ := s.Database.FindPackageVersions(p) // If was installed, it is found, as it was filtered @@ -683,7 +688,7 @@ func (l *LuetInstaller) Reclaim(s *System) error { if err != nil && !l.Options.Force { return errors.Wrap(err, "Failed creating package") } - s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: pack.GetFingerPrint(), Files: match.Artifact.Files}) + s.Database.SetPackageFiles(&types.PackageFile{PackageFingerprint: pack.GetFingerPrint(), Files: match.Artifact.Files}) l.Options.Context.Info(":zap:Reclaimed package:", pack.HumanReadableString()) } l.Options.Context.Info("Done!") @@ -691,11 +696,11 @@ func (l *LuetInstaller) Reclaim(s *System) error { return nil } -func (l *LuetInstaller) computeInstall(o Option, syncedRepos Repositories, cp pkg.Packages, s *System) (map[string]ArtifactMatch, pkg.Packages, solver.PackagesAssertions, pkg.PackageDatabase, error) { - var p pkg.Packages +func (l *LuetInstaller) computeInstall(o Option, syncedRepos Repositories, cp types.Packages, s *System) (map[string]ArtifactMatch, types.Packages, types.PackagesAssertions, types.PackageDatabase, error) { + var p types.Packages toInstall := map[string]ArtifactMatch{} allRepos := pkg.NewInMemoryDatabase(false) - var solution solver.PackagesAssertions + var solution types.PackagesAssertions // Check if the package is installed first for _, pi := range cp { @@ -721,11 +726,16 @@ func (l *LuetInstaller) computeInstall(o Option, syncedRepos Repositories, cp pk // compute a "big" world syncedRepos.SyncDatabase(allRepos) p = syncedRepos.ResolveSelectors(p) - var packagesToInstall pkg.Packages + var packagesToInstall types.Packages var err error 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()) + solv := solver.NewResolver(types.SolverOptions{ + Type: l.Options.SolverOptions.Implementation, + Concurrency: l.Options.Concurrency}, + s.Database, allRepos, pkg.NewInMemoryDatabase(false), + solver.NewSolverFromOptions(l.Options.SolverOptions), + ) if l.Options.Relaxed { solution, err = solv.RelaxedInstall(p) @@ -759,7 +769,7 @@ func (l *LuetInstaller) computeInstall(o Option, syncedRepos Repositories, cp pk for _, currentPack := range packagesToInstall { // Check if package is already installed. - matches := syncedRepos.PackageMatches(pkg.Packages{currentPack}) + matches := syncedRepos.PackageMatches(types.Packages{currentPack}) if len(matches) == 0 { return toInstall, p, solution, allRepos, errors.New("Failed matching solutions against repository for " + currentPack.HumanReadableString() + " where are definitions coming from?!") } @@ -781,8 +791,8 @@ func (l *LuetInstaller) computeInstall(o Option, syncedRepos Repositories, cp pk return toInstall, p, solution, allRepos, nil } -func (l *LuetInstaller) getFinalizers(allRepos pkg.PackageDatabase, solution solver.PackagesAssertions, toInstall map[string]ArtifactMatch, nodeps bool) ([]pkg.Package, error) { - var toFinalize []pkg.Package +func (l *LuetInstaller) getFinalizers(allRepos types.PackageDatabase, solution types.PackagesAssertions, toInstall map[string]ArtifactMatch, nodeps bool) ([]*types.Package, error) { + var toFinalize []*types.Package if !nodeps { // TODO: Lower those errors as l.Options.Context.Warning for _, w := range toInstall { @@ -866,7 +876,7 @@ func (l *LuetInstaller) checkFileconflicts(toInstall map[string]ArtifactMatch, c return nil } -func (l *LuetInstaller) install(o Option, syncedRepos Repositories, toInstall map[string]ArtifactMatch, p pkg.Packages, solution solver.PackagesAssertions, allRepos pkg.PackageDatabase, s *System) error { +func (l *LuetInstaller) install(o Option, syncedRepos Repositories, toInstall map[string]ArtifactMatch, p types.Packages, solution types.PackagesAssertions, allRepos types.PackageDatabase, s *System) error { // Download packages in parallel first if err := l.download(syncedRepos, toInstall); err != nil { @@ -960,7 +970,7 @@ func (l *LuetInstaller) installPackage(m ArtifactMatch, s *System) error { // First create client and download // Then unpack to system - return s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: m.Package.GetFingerPrint(), Files: files}) + return s.Database.SetPackageFiles(&types.PackageFile{PackageFingerprint: m.Package.GetFingerPrint(), Files: files}) } func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, pb *pterm.ProgressbarPrinter, c <-chan ArtifactMatch, ctx types.Context) error { @@ -1057,7 +1067,7 @@ func pruneEmptyFilePath(ctx types.Context, target string, path string) { allPaths = append(allPaths, currentPath) } } - match.ReverseAny(allPaths) + helpers.ReverseAny(allPaths) for _, p := range allPaths { checkAndPrunePath(ctx, target, p) } @@ -1105,20 +1115,12 @@ func (l *LuetInstaller) pruneFile(f string, s *System, cp *config.ConfigProtect) pruneEmptyFilePath(l.Options.Context, s.Target, target) } -func (l *LuetInstaller) configProtectForPackage(p pkg.Package, s *System, files []string) *config.ConfigProtect { +func (l *LuetInstaller) configProtectForPackage(p *types.Package, s *System, files []string) *config.ConfigProtect { var cp *config.ConfigProtect - annotationDir := "" if !l.Options.Context.GetConfig().ConfigProtectSkip { - - if p.HasAnnotation(string(pkg.ConfigProtectAnnnotation)) { - dir, ok := p.GetAnnotations()[string(pkg.ConfigProtectAnnnotation)] - if ok { - annotationDir = dir - } - } - + annotationDir, _ := p.Annotations[types.ConfigProtectAnnotation] cp = config.NewConfigProtect(annotationDir) cp.Map(files, l.Options.Context.GetConfig().ConfigProtectConfFiles) } @@ -1136,7 +1138,7 @@ func (l *LuetInstaller) pruneFiles(files []string, cp *config.ConfigProtect, s * } } -func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error { +func (l *LuetInstaller) uninstall(p *types.Package, s *System) error { files, err := s.Database.GetPackageFiles(p) if err != nil { return errors.Wrap(err, "Failed getting installed files") @@ -1155,7 +1157,7 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error { return nil } -func (l *LuetInstaller) removePackage(p pkg.Package, s *System) error { +func (l *LuetInstaller) removePackage(p *types.Package, s *System) error { err := s.Database.RemovePackageFiles(p) if err != nil { return errors.Wrap(err, "Failed removing package files from database") @@ -1169,9 +1171,9 @@ func (l *LuetInstaller) removePackage(p pkg.Package, s *System) error { return nil } -func (l *LuetInstaller) computeUninstall(o Option, s *System, packs ...pkg.Package) (pkg.Packages, error) { +func (l *LuetInstaller) computeUninstall(o Option, s *System, packs ...*types.Package) (types.Packages, error) { - var toUninstall pkg.Packages + var toUninstall types.Packages // compute uninstall from all world - remove packages in parallel - run uninstall finalizer (in order) TODO - mark the uninstallation in db // Get installed definition checkConflicts := o.CheckConflicts @@ -1190,8 +1192,16 @@ func (l *LuetInstaller) computeUninstall(o Option, s *System, packs ...pkg.Packa } if !o.NoDeps { - solv := solver.NewResolver(solver.Options{Type: l.Options.SolverOptions.Implementation, Concurrency: l.Options.Concurrency}, installedtmp, installedtmp, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver()) - var solution pkg.Packages + solv := solver.NewResolver( + types.SolverOptions{ + Type: l.Options.SolverOptions.Implementation, + Concurrency: l.Options.Concurrency, + }, + installedtmp, + installedtmp, + pkg.NewInMemoryDatabase(false), + solver.NewSolverFromOptions(l.Options.SolverOptions)) + var solution types.Packages var err error if o.FullCleanUninstall { solution, err = solv.UninstallUniverse(packs) @@ -1213,7 +1223,7 @@ func (l *LuetInstaller) computeUninstall(o Option, s *System, packs ...pkg.Packa return toUninstall, nil } -func (l *LuetInstaller) generateUninstallFn(o Option, s *System, filesToInstall map[string]interface{}, packs ...pkg.Package) (pkg.Packages, func() error, error) { +func (l *LuetInstaller) generateUninstallFn(o Option, s *System, filesToInstall map[string]interface{}, packs ...*types.Package) (types.Packages, func() error, error) { for _, p := range packs { if packs, _ := s.Database.FindPackages(p); len(packs) == 0 { return nil, nil, errors.New(fmt.Sprintf("Package %s not found in the system", p.HumanReadableString())) @@ -1263,7 +1273,7 @@ func (l *LuetInstaller) generateUninstallFn(o Option, s *System, filesToInstall return toUninstall, uninstall, nil } -func (l *LuetInstaller) Uninstall(s *System, packs ...pkg.Package) error { +func (l *LuetInstaller) Uninstall(s *System, packs ...*types.Package) error { l.Options.Context.Screen("Uninstall") l.Options.Context.Spinner() diff --git a/pkg/installer/installer_test.go b/pkg/installer/installer_test.go index 57f209ec..1fc711d8 100644 --- a/pkg/installer/installer_test.go +++ b/pkg/installer/installer_test.go @@ -30,8 +30,8 @@ import ( compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" fileHelper "github.com/mudler/luet/pkg/helpers/file" + pkg "github.com/mudler/luet/pkg/database" . "github.com/mudler/luet/pkg/installer" - pkg "github.com/mudler/luet/pkg/package" "github.com/mudler/luet/pkg/tree" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -77,7 +77,7 @@ var _ = Describe("Installer", func() { generalRecipe.GetDatabase(), options.Concurrency(2)) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -144,15 +144,15 @@ urls: Expect(repo.GetType()).To(Equal("disk")) systemDB := pkg.NewInMemoryDatabase(false) system := &System{Database: systemDB, Target: fakeroot} - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "b", Category: "test", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).To(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - files, err := systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + files, err := systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(files).To(Equal([]string{"artifact42", "test5", "test6"})) Expect(err).ToNot(HaveOccurred()) @@ -161,16 +161,16 @@ urls: Expect(err).ToNot(HaveOccurred()) Expect(p.GetName()).To(Equal("b")) - err = inst.Uninstall(system, &pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + err = inst.Uninstall(system, &types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // Nothing should be there anymore (files, packagedb entry) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).ToNot(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).ToNot(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) - _, err = systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) }) @@ -194,7 +194,7 @@ urls: c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2)) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -267,15 +267,15 @@ urls: Expect(repo.GetType()).To(Equal("disk")) systemDB := pkg.NewInMemoryDatabase(false) system := &System{Database: systemDB, Target: fakeroot} - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "b", Category: "test", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).To(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - files, err := systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + files, err := systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(files).To(Equal([]string{"artifact42", "test5", "test6"})) Expect(err).ToNot(HaveOccurred()) @@ -284,16 +284,16 @@ urls: Expect(err).ToNot(HaveOccurred()) Expect(p.GetName()).To(Equal("b")) - err = inst.Uninstall(system, &pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + err = inst.Uninstall(system, &types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // Nothing should be there anymore (files, packagedb entry) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).ToNot(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).ToNot(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) - _, err = systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) }) @@ -317,7 +317,7 @@ urls: c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2)) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -398,12 +398,12 @@ urls: systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) system := &System{Database: systemDB, Target: fakeroot} - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "b", Category: "test", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).To(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(len(system.Database.GetPackages())).To(Equal(1)) @@ -411,20 +411,20 @@ urls: Expect(err).ToNot(HaveOccurred()) Expect(p.GetName()).To(Equal("b")) - files, err := systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + files, err := systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(files).To(Equal([]string{"artifact42", "test5", "test6"})) Expect(err).ToNot(HaveOccurred()) - err = inst.Uninstall(system, &pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + err = inst.Uninstall(system, &types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) // Nothing should be there anymore (files, packagedb entry) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).ToNot(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).ToNot(BeTrue()) - _, err = system.Database.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) }) @@ -446,7 +446,7 @@ urls: c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2)) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -528,7 +528,7 @@ urls: systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) system := &System{Database: systemDB, Target: fakeroot} - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "b", Category: "test", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) tmpdir2, err := ioutil.TempDir("", "tree2") @@ -544,7 +544,7 @@ urls: c = compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.Concurrency(2)) - spec, err = c.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"}) + spec, err = c.FromPackage(&types.Package{Name: "alpine", Category: "seed", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -579,9 +579,9 @@ urls: Expect(repo.GetUrls()[0]).To(Equal(tmpdir2)) Expect(repo.GetType()).To(Equal("disk")) system.Target = fakeroot - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "alpine", Category: "seed", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "alpine", Category: "seed", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) }) @@ -605,11 +605,11 @@ urls: c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2)) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + spec2, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) - spec3, err := c.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + spec3, err := c.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -667,12 +667,12 @@ urls: systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) system := &System{Database: systemDB, Target: fakeroot} - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "b", Category: "test", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).To(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(len(system.Database.GetPackages())).To(Equal(1)) @@ -680,7 +680,7 @@ urls: Expect(err).ToNot(HaveOccurred()) Expect(p.GetName()).To(Equal("b")) - files, err := systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + files, err := systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(files).To(Equal([]string{"artifact42", "test5", "test6"})) Expect(err).ToNot(HaveOccurred()) @@ -693,13 +693,13 @@ urls: // New version - new files Expect(fileHelper.Exists(filepath.Join(fakeroot, "newc"))).To(BeTrue()) - _, err = system.Database.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) // New package should be there - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) }) @@ -718,14 +718,14 @@ urls: c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2)) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + spec2, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) - spec4, err := c.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.1"}) + spec4, err := c.FromPackage(&types.Package{Name: "a", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) - spec5, err := c.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.2"}) + spec5, err := c.FromPackage(&types.Package{Name: "a", Category: "test", Version: "1.2"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -784,12 +784,12 @@ urls: systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) system := &System{Database: systemDB, Target: fakeroot} - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "b", Category: "test", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).To(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(len(system.Database.GetPackages())).To(Equal(1)) @@ -797,14 +797,14 @@ urls: Expect(err).ToNot(HaveOccurred()) Expect(p.GetName()).To(Equal("b")) - files, err := systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + files, err := systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(files).To(Equal([]string{"test5", "test6"})) Expect(err).ToNot(HaveOccurred()) - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.1"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "a", Category: "test", Version: "1.1"}}, system) Expect(err).ToNot(HaveOccurred()) - files, err = systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.1"}) + files, err = systemDB.GetPackageFiles(&types.Package{Name: "a", Category: "test", Version: "1.1"}) Expect(files).To(Equal([]string{"test3", "test4"})) Expect(err).ToNot(HaveOccurred()) @@ -835,18 +835,18 @@ urls: c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2)) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + spec2, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) - spec3, err := c.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.1"}) + spec3, err := c.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) - spec4, err := c.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.1"}) + spec4, err := c.FromPackage(&types.Package{Name: "a", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) - spec5, err := c.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.2"}) + spec5, err := c.FromPackage(&types.Package{Name: "a", Category: "test", Version: "1.2"}) Expect(err).ToNot(HaveOccurred()) - spec6, err := c.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.2"}) + spec6, err := c.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.2"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -908,12 +908,12 @@ urls: systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) system := &System{Database: systemDB, Target: fakeroot} - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "b", Category: "test", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).To(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(len(system.Database.GetPackages())).To(Equal(1)) @@ -921,20 +921,20 @@ urls: Expect(err).ToNot(HaveOccurred()) Expect(p.GetName()).To(Equal("b")) - files, err := systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + files, err := systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(files).To(Equal([]string{"test5", "test6"})) Expect(err).ToNot(HaveOccurred()) - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.1"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "c", Category: "test", Version: "1.1"}}, system) Expect(err).ToNot(HaveOccurred()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test1"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test2"))).To(BeTrue()) - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.1"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "a", Category: "test", Version: "1.1"}}, system) Expect(err).ToNot(HaveOccurred()) - files, err = systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.1"}) + files, err = systemDB.GetPackageFiles(&types.Package{Name: "a", Category: "test", Version: "1.1"}) Expect(files).To(Equal([]string{"test3", "test4"})) Expect(err).ToNot(HaveOccurred()) @@ -974,12 +974,12 @@ urls: c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.Concurrency(2)) c2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipeNewRepo.GetDatabase()) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec3, err := c.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + spec3, err := c.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := c2.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + spec2, err := c2.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -1050,12 +1050,12 @@ urls: systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) system := &System{Database: systemDB, Target: fakeroot} - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "b", Category: "test", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).To(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(len(system.Database.GetPackages())).To(Equal(1)) @@ -1063,7 +1063,7 @@ urls: Expect(err).ToNot(HaveOccurred()) Expect(p.GetName()).To(Equal("b")) - files, err := systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + files, err := systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(files).To(Equal([]string{"artifact42", "test5", "test6"})) Expect(err).ToNot(HaveOccurred()) @@ -1078,13 +1078,13 @@ urls: // New version - new files Expect(fileHelper.Exists(filepath.Join(fakeroot, "newc"))).To(BeTrue()) - _, err = system.Database.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) // New package should be there - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) }) @@ -1113,11 +1113,11 @@ urls: options.WithCompressionType(compression.GZip), ) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + spec2, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) - spec3, err := c.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + spec3, err := c.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -1177,12 +1177,12 @@ urls: systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) system := &System{Database: systemDB, Target: fakeroot} - err = inst.Install([]pkg.Package{&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}}, system) + err = inst.Install([]*types.Package{&types.Package{Name: "b", Category: "test", Version: "1.0"}}, system) Expect(err).ToNot(HaveOccurred()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test5"))).To(BeTrue()) Expect(fileHelper.Exists(filepath.Join(fakeroot, "test6"))).To(BeTrue()) - _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = systemDB.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(len(system.Database.GetPackages())).To(Equal(1)) @@ -1190,7 +1190,7 @@ urls: Expect(err).ToNot(HaveOccurred()) Expect(p.GetName()).To(Equal("b")) - files, err := systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + files, err := systemDB.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(files).To(Equal([]string{"artifact42", "test5", "test6"})) Expect(err).ToNot(HaveOccurred()) @@ -1203,13 +1203,13 @@ urls: // New version - new files Expect(fileHelper.Exists(filepath.Join(fakeroot, "newc"))).To(BeTrue()) - _, err = system.Database.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) // New package should be there - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) }) @@ -1231,12 +1231,12 @@ urls: inst := NewLuetInstaller(LuetInstallerOptions{Concurrency: 1, Context: ctx, CheckConflicts: true}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("calamares", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("kpmcore", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - Z := pkg.NewPackage("chromium", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{Z, B}, []*pkg.DefaultPackage{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("calamares", "", []*types.Package{D}, []*types.Package{}) + C := types.NewPackage("kpmcore", "", []*types.Package{B}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) + Z := types.NewPackage("chromium", "", []*types.Package{A}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{Z, B}, []*types.Package{}) Z.SetVersion("86.0.4240.193+2") Z.SetCategory("www-client") @@ -1247,7 +1247,7 @@ urls: D.SetVersion("5.19.5+9") D.SetCategory("layers") - for _, p := range []pkg.Package{A, B, C, D, Z, F} { + for _, p := range []*types.Package{A, B, C, D, Z, F} { _, err := systemDB.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1276,11 +1276,11 @@ urls: options.Concurrency(2), options.WithCompressionType(compression.GZip)) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec2, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + spec2, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) - spec3, err := c.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + spec3, err := c.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -1340,10 +1340,10 @@ urls: systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) system := &System{Database: systemDB, Target: fakeroot} - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) Expect(len(system.Database.World())).To(Equal(0)) @@ -1358,10 +1358,10 @@ urls: err = inst.Reclaim(system) Expect(err).ToNot(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(len(system.Database.World())).To(Equal(2)) @@ -1384,9 +1384,9 @@ urls: c := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithCompressionType(compression.GZip)) - spec, err := c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - spec3, err := c.FromPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + spec3, err := c.FromPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -1443,10 +1443,10 @@ urls: systemDB := pkg.NewBoltDatabase(filepath.Join(bolt, "db.db")) system := &System{Database: systemDB, Target: fakeroot} - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) Expect(len(system.Database.World())).To(Equal(0)) @@ -1461,10 +1461,10 @@ urls: err = inst.Reclaim(system) Expect(err).ToNot(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "c", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "c", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(len(system.Database.World())).To(Equal(2)) @@ -1478,7 +1478,7 @@ urls: c = compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase()) - spec, err = c.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + spec, err = c.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) tmpdir2, err := ioutil.TempDir("", "tree") @@ -1519,13 +1519,13 @@ urls: // New version - new files Expect(fileHelper.Exists(filepath.Join(fakeroot, "newc"))).To(BeTrue()) - _, err = system.Database.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.GetPackageFiles(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).To(HaveOccurred()) // New package should be there - _, err = system.Database.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.1"}) + _, err = system.Database.FindPackage(&types.Package{Name: "b", Category: "test", Version: "1.1"}) Expect(err).ToNot(HaveOccurred()) }) diff --git a/pkg/installer/repository.go b/pkg/installer/repository.go index 801ad271..bbcf0bf9 100644 --- a/pkg/installer/repository.go +++ b/pkg/installer/repository.go @@ -36,7 +36,7 @@ import ( "github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/installer/client" - pkg "github.com/mudler/luet/pkg/package" + pkg "github.com/mudler/luet/pkg/database" tree "github.com/mudler/luet/pkg/tree" "github.com/ghodss/yaml" @@ -115,7 +115,7 @@ func SystemRepositories(t types.LuetRepositories) Repositories { } // LoadBuildTree loads to the tree the compilation specs from the system repositories -func LoadBuildTree(t tree.Builder, db pkg.PackageDatabase, ctx types.Context) error { +func LoadBuildTree(t tree.Builder, db types.PackageDatabase, ctx types.Context) error { var reserr error repos := SystemRepositories(ctx.GetConfig().SystemRepositories) for _, r := range repos { @@ -301,7 +301,7 @@ func GenerateRepository(p ...RepositoryOption) (*LuetSystemRepository, error) { } // Only those which are metadata - if !strings.HasSuffix(info.Name(), pkg.PackageMetaSuffix) { + if !strings.HasSuffix(info.Name(), types.PackageMetaSuffix) { return nil } @@ -320,7 +320,7 @@ func GenerateRepository(p ...RepositoryOption) (*LuetSystemRepository, error) { runtimeTree.CreatePackage(art.Runtime) } else { // We don't have runtime at this point. So we import the package as is - r := []*pkg.DefaultPackage{} + r := []*types.Package{} p := art.CompileSpec.Package.Clone() p.Requires(r) p.SetProvides(r) @@ -362,7 +362,7 @@ func NewSystemRepository(repo types.LuetRepository) *LuetSystemRepository { } } -func NewLuetSystemRepositoryFromYaml(data []byte, db pkg.PackageDatabase) (*LuetSystemRepository, error) { +func NewLuetSystemRepositoryFromYaml(data []byte, db types.PackageDatabase) (*LuetSystemRepository, error) { var p *LuetSystemRepository err := yaml.Unmarshal(data, &p) if err != nil { @@ -393,8 +393,8 @@ func (r *LuetSystemRepository) initialize(ctx types.Context, src string) error { } // FileSearch search a pattern among the artifacts in a repository -func (r *LuetSystemRepository) FileSearch(pattern string) (pkg.Packages, error) { - var matches pkg.Packages +func (r *LuetSystemRepository) FileSearch(pattern string) (types.Packages, error) { + var matches types.Packages reg, err := regexp.Compile(pattern) if err != nil { return matches, err @@ -707,7 +707,7 @@ func (r *LuetSystemRepository) ReadSpecFile(file string) (*LuetSystemRepository, type RepositoryGenerator interface { Generate(*LuetSystemRepository, string, bool) error - Initialize(string, pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) + Initialize(string, types.PackageDatabase) ([]*artifact.PackageArtifact, error) } func (r *LuetSystemRepository) getGenerator(ctx types.Context, snapshotID string) (RepositoryGenerator, error) { @@ -766,7 +766,7 @@ func (r *LuetSystemRepository) Client(ctx types.Context) Client { return nil } -func (r *LuetSystemRepository) SearchArtefact(p pkg.Package) (*artifact.PackageArtifact, error) { +func (r *LuetSystemRepository) SearchArtefact(p *types.Package) (*artifact.PackageArtifact, error) { for _, a := range r.GetIndex() { if a.CompileSpec.GetPackage().Matches(p) { return a, nil @@ -1065,9 +1065,9 @@ func (r Repositories) Less(i, j int) bool { return r[i].GetPriority() < r[j].GetPriority() } -func (r Repositories) World() pkg.Packages { - cache := map[string]pkg.Package{} - world := pkg.Packages{} +func (r Repositories) World() types.Packages { + cache := map[string]*types.Package{} + world := types.Packages{} // Get Uniques. Walk in reverse so the definitions of most prio-repo overwrites lower ones // In this way, when we will walk again later the deps sorting them by most higher prio we have better chance of success. @@ -1084,7 +1084,7 @@ func (r Repositories) World() pkg.Packages { return world } -func (r Repositories) SyncDatabase(d pkg.PackageDatabase) { +func (r Repositories) SyncDatabase(d types.PackageDatabase) { cache := map[string]bool{} // Get Uniques. Walk in reverse so the definitions of most prio-repo overwrites lower ones @@ -1102,10 +1102,10 @@ func (r Repositories) SyncDatabase(d pkg.PackageDatabase) { type PackageMatch struct { Repo *LuetSystemRepository Artifact *artifact.PackageArtifact - Package pkg.Package + Package *types.Package } -func (re Repositories) PackageMatches(p pkg.Packages) []PackageMatch { +func (re Repositories) PackageMatches(p types.Packages) []PackageMatch { // TODO: Better heuristic. here we pick the first repo that contains the atom, sorted by priority but // we should do a permutations and get the best match, and in case there are more solutions the user should be able to pick sort.Sort(re) @@ -1126,10 +1126,10 @@ PACKAGE: } -func (re Repositories) ResolveSelectors(p pkg.Packages) pkg.Packages { +func (re Repositories) ResolveSelectors(p types.Packages) types.Packages { // If a selector is given, get the best from each repo sort.Sort(re) // respect prio - var matches pkg.Packages + var matches types.Packages PACKAGE: for _, pack := range p { REPOSITORY: @@ -1160,7 +1160,7 @@ func (re Repositories) SearchPackages(p string, t LuetSearchModeType) []PackageM var err error for _, r := range re { - var repoMatches pkg.Packages + var repoMatches types.Packages switch t { case SRegexPkg: diff --git a/pkg/installer/repository_docker.go b/pkg/installer/repository_docker.go index eb46503f..48684862 100644 --- a/pkg/installer/repository_docker.go +++ b/pkg/installer/repository_docker.go @@ -31,7 +31,6 @@ import ( compiler "github.com/mudler/luet/pkg/compiler" "github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/helpers" - pkg "github.com/mudler/luet/pkg/package" "github.com/pkg/errors" ) @@ -43,7 +42,7 @@ type dockerRepositoryGenerator struct { context types.Context } -func (l *dockerRepositoryGenerator) Initialize(path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) { +func (l *dockerRepositoryGenerator) Initialize(path string, db types.PackageDatabase) ([]*artifact.PackageArtifact, error) { l.context.Info("Generating docker images for packages in", l.imagePrefix) var art []*artifact.PackageArtifact var ff = func(currentpath string, info os.FileInfo, err error) error { diff --git a/pkg/installer/repository_local.go b/pkg/installer/repository_local.go index ee9e11a0..322e8dcb 100644 --- a/pkg/installer/repository_local.go +++ b/pkg/installer/repository_local.go @@ -26,7 +26,6 @@ import ( "github.com/mudler/luet/pkg/api/core/types" artifact "github.com/mudler/luet/pkg/api/core/types/artifact" - pkg "github.com/mudler/luet/pkg/package" "github.com/mudler/luet/pkg/api/core/bus" "github.com/pkg/errors" @@ -37,11 +36,11 @@ type localRepositoryGenerator struct { snapshotID string } -func (l *localRepositoryGenerator) Initialize(path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) { +func (l *localRepositoryGenerator) Initialize(path string, db types.PackageDatabase) ([]*artifact.PackageArtifact, error) { return buildPackageIndex(l.context, path, db) } -func buildPackageIndex(ctx types.Context, path string, db pkg.PackageDatabase) ([]*artifact.PackageArtifact, error) { +func buildPackageIndex(ctx types.Context, path string, db types.PackageDatabase) ([]*artifact.PackageArtifact, error) { var art []*artifact.PackageArtifact var ff = func(currentpath string, info os.FileInfo, err error) error { diff --git a/pkg/installer/repository_options.go b/pkg/installer/repository_options.go index a6751b3e..0c8bd626 100644 --- a/pkg/installer/repository_options.go +++ b/pkg/installer/repository_options.go @@ -18,7 +18,6 @@ package installer import ( "github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/compiler" - pkg "github.com/mudler/luet/pkg/package" ) type RepositoryOption func(cfg *RepositoryConfig) error @@ -29,7 +28,7 @@ type RepositoryConfig struct { Priority int Src string Tree []string - DB pkg.PackageDatabase + DB types.PackageDatabase CompilerBackend compiler.CompilerBackend ImagePrefix string @@ -58,7 +57,7 @@ func WithContext(c types.Context) func(cfg *RepositoryConfig) error { } } -func WithDatabase(b pkg.PackageDatabase) func(cfg *RepositoryConfig) error { +func WithDatabase(b types.PackageDatabase) func(cfg *RepositoryConfig) error { return func(cfg *RepositoryConfig) error { cfg.DB = b return nil diff --git a/pkg/installer/repository_test.go b/pkg/installer/repository_test.go index ec4c21c7..e0859acb 100644 --- a/pkg/installer/repository_test.go +++ b/pkg/installer/repository_test.go @@ -31,9 +31,9 @@ import ( backend "github.com/mudler/luet/pkg/compiler/backend" "github.com/mudler/luet/pkg/compiler/types/options" compilerspec "github.com/mudler/luet/pkg/compiler/types/spec" + pkg "github.com/mudler/luet/pkg/database" fileHelper "github.com/mudler/luet/pkg/helpers/file" . "github.com/mudler/luet/pkg/installer" - pkg "github.com/mudler/luet/pkg/package" "github.com/mudler/luet/pkg/tree" . "github.com/onsi/ginkgo/v2" @@ -75,7 +75,7 @@ var _ = Describe("Repository", func() { compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase()) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -141,12 +141,12 @@ var _ = Describe("Repository", func() { Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.WithContext(context.NewContext())) - spec2, err := compiler2.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"}) + spec2, err := compiler2.FromPackage(&types.Package{Name: "alpine", Category: "seed", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(context.NewContext())) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -238,12 +238,12 @@ urls: Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.WithContext(ctx)) - spec2, err := compiler2.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"}) + spec2, err := compiler2.FromPackage(&types.Package{Name: "alpine", Category: "seed", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(ctx)) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -356,12 +356,12 @@ urls: Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(3)) compiler2 := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe2.GetDatabase(), options.WithContext(ctx)) - spec2, err := compiler2.FromPackage(&pkg.DefaultPackage{Name: "alpine", Category: "seed", Version: "1.0"}) + spec2, err := compiler2.FromPackage(&types.Package{Name: "alpine", Category: "seed", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) compiler := compiler.NewLuetCompiler(backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(ctx)) - spec, err := compiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := compiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -447,8 +447,8 @@ urls: }) Context("Matching packages", func() { It("Matches packages in different repositories by priority", func() { - package1 := &pkg.DefaultPackage{Name: "Test"} - package2 := &pkg.DefaultPackage{Name: "Test2"} + package1 := &types.Package{Name: "Test"} + package2 := &types.Package{Name: "Test2"} builder1 := tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false)) builder2 := tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false)) @@ -460,7 +460,7 @@ urls: repo1 := &LuetSystemRepository{LuetRepository: &types.LuetRepository{Name: "test1"}, Tree: builder1} repo2 := &LuetSystemRepository{LuetRepository: &types.LuetRepository{Name: "test2"}, Tree: builder2} repositories := Repositories{repo1, repo2} - matches := repositories.PackageMatches([]pkg.Package{package1}) + matches := repositories.PackageMatches([]*types.Package{package1}) Expect(matches).To(Equal([]PackageMatch{{Repo: repo1, Package: package1}})) }) @@ -491,7 +491,7 @@ urls: localcompiler := compiler.NewLuetCompiler( backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(ctx)) - spec, err := localcompiler.FromPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + spec, err := localcompiler.FromPackage(&types.Package{Name: "b", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -537,7 +537,7 @@ urls: a, err = c.DownloadArtifact(&artifact.PackageArtifact{ Path: "test.tar", CompileSpec: &compilerspec.LuetCompilationSpec{ - Package: &pkg.DefaultPackage{ + Package: &types.Package{ Name: "b", Category: "test", Version: "1.0", @@ -566,7 +566,7 @@ urls: localcompiler := compiler.NewLuetCompiler( backend.NewSimpleDockerBackend(ctx), generalRecipe.GetDatabase(), options.WithContext(ctx)) - spec, err := localcompiler.FromPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.99"}) + spec, err := localcompiler.FromPackage(&types.Package{Name: "a", Category: "test", Version: "1.99"}) Expect(err).ToNot(HaveOccurred()) Expect(spec.GetPackage().GetPath()).ToNot(Equal("")) @@ -609,7 +609,7 @@ urls: a, err = c.DownloadArtifact(&artifact.PackageArtifact{ Path: "test.tar", CompileSpec: &compilerspec.LuetCompilationSpec{ - Package: &pkg.DefaultPackage{ + Package: &types.Package{ Name: "a", Category: "test", Version: "1.99", @@ -630,7 +630,7 @@ urls: Index: compiler.ArtifactIndex{ &artifact.PackageArtifact{ CompileSpec: &compilerspec.LuetCompilationSpec{ - Package: &pkg.DefaultPackage{}, + Package: &types.Package{}, }, Path: "bar", Files: []string{"boo"}, @@ -654,7 +654,7 @@ urls: &artifact.PackageArtifact{ Path: "foo", CompileSpec: &compilerspec.LuetCompilationSpec{ - Package: &pkg.DefaultPackage{ + Package: &types.Package{ Name: "foo", Category: "bar", Version: "1.0", @@ -664,7 +664,7 @@ urls: &artifact.PackageArtifact{ Path: "baz", CompileSpec: &compilerspec.LuetCompilationSpec{ - Package: &pkg.DefaultPackage{ + Package: &types.Package{ Name: "foo", Category: "baz", Version: "1.0", @@ -674,7 +674,7 @@ urls: }, } - a, err := repo.SearchArtefact(&pkg.DefaultPackage{ + a, err := repo.SearchArtefact(&types.Package{ Name: "foo", Category: "baz", Version: "1.0", @@ -682,7 +682,7 @@ urls: Expect(err).ToNot(HaveOccurred()) Expect(a.Path).To(Equal("baz")) - a, err = repo.SearchArtefact(&pkg.DefaultPackage{ + a, err = repo.SearchArtefact(&types.Package{ Name: "foo", Category: "bar", Version: "1.0", @@ -691,7 +691,7 @@ urls: Expect(a.Path).To(Equal("foo")) // Doesn't exist. so must fail - _, err = repo.SearchArtefact(&pkg.DefaultPackage{ + _, err = repo.SearchArtefact(&types.Package{ Name: "foo", Category: "bar", Version: "1.1", diff --git a/pkg/installer/system.go b/pkg/installer/system.go index 16182209..f351f0ed 100644 --- a/pkg/installer/system.go +++ b/pkg/installer/system.go @@ -9,23 +9,22 @@ import ( "github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/helpers" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" "github.com/mudler/luet/pkg/tree" ) type System struct { - Database pkg.PackageDatabase + Database types.PackageDatabase Target string - fileIndex map[string]pkg.Package - fileIndexPackages map[string]pkg.Package + fileIndex map[string]*types.Package + fileIndexPackages map[string]*types.Package sync.Mutex } -func (s *System) World() (pkg.Packages, error) { +func (s *System) World() (types.Packages, error) { return s.Database.World(), nil } -func (s *System) OSCheck(ctx types.Context) (notFound pkg.Packages) { +func (s *System) OSCheck(ctx types.Context) (notFound types.Packages) { s.buildFileIndex() s.Lock() defer s.Unlock() @@ -42,12 +41,12 @@ func (s *System) OSCheck(ctx types.Context) (notFound pkg.Packages) { return } -func (s *System) ExecuteFinalizers(ctx types.Context, packs []pkg.Package) error { +func (s *System) ExecuteFinalizers(ctx types.Context, packs []*types.Package) error { var errs error executedFinalizer := map[string]bool{} for _, p := range packs { if fileHelper.Exists(p.Rel(tree.FinalizerFile)) { - out, err := helpers.RenderFiles(helpers.ChartFile(p.Rel(tree.FinalizerFile)), p.Rel(pkg.PackageDefinitionFile)) + out, err := helpers.RenderFiles(helpers.ChartFile(p.Rel(tree.FinalizerFile)), p.Rel(types.PackageDefinitionFile)) if err != nil { ctx.Warning("Failed rendering finalizer for ", p.HumanReadableString(), err.Error()) errs = multierror.Append(errs, err) @@ -81,16 +80,16 @@ func (s *System) buildFileIndex() { defer s.Unlock() if s.fileIndex == nil { - s.fileIndex = make(map[string]pkg.Package) + s.fileIndex = make(map[string]*types.Package) } if s.fileIndexPackages == nil { - s.fileIndexPackages = make(map[string]pkg.Package) + s.fileIndexPackages = make(map[string]*types.Package) } // Check if cache is empty or if it got modified if len(s.Database.GetPackages()) != len(s.fileIndexPackages) { - s.fileIndexPackages = make(map[string]pkg.Package) + s.fileIndexPackages = make(map[string]*types.Package) for _, p := range s.Database.World() { files, _ := s.Database.GetPackageFiles(p) for _, f := range files { @@ -107,14 +106,14 @@ func (s *System) Clean() { s.fileIndex = nil } -func (s *System) FileIndex() map[string]pkg.Package { +func (s *System) FileIndex() map[string]*types.Package { s.buildFileIndex() s.Lock() defer s.Unlock() return s.fileIndex } -func (s *System) ExistsPackageFile(file string) (bool, pkg.Package, error) { +func (s *System) ExistsPackageFile(file string) (bool, *types.Package, error) { s.buildFileIndex() s.Lock() defer s.Unlock() diff --git a/pkg/installer/system_test.go b/pkg/installer/system_test.go index 4afb41fd..7b285aa4 100644 --- a/pkg/installer/system_test.go +++ b/pkg/installer/system_test.go @@ -24,8 +24,9 @@ import ( "path/filepath" "github.com/mudler/luet/pkg/api/core/context" + "github.com/mudler/luet/pkg/api/core/types" + pkg "github.com/mudler/luet/pkg/database" . "github.com/mudler/luet/pkg/installer" - pkg "github.com/mudler/luet/pkg/package" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -34,23 +35,23 @@ import ( var _ = Describe("System", func() { Context("Files", func() { var s *System - var db pkg.PackageDatabase - var a, b *pkg.DefaultPackage + var db types.PackageDatabase + var a, b *types.Package ctx := context.NewContext() BeforeEach(func() { db = pkg.NewInMemoryDatabase(false) s = &System{Database: db} - a = &pkg.DefaultPackage{Name: "test", Version: "1", Category: "t"} + a = &types.Package{Name: "test", Version: "1", Category: "t"} db.CreatePackage(a) - db.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: a.GetFingerPrint(), Files: []string{"foo", "f"}}) + db.SetPackageFiles(&types.PackageFile{PackageFingerprint: a.GetFingerPrint(), Files: []string{"foo", "f"}}) - b = &pkg.DefaultPackage{Name: "test2", Version: "1", Category: "t"} + b = &types.Package{Name: "test2", Version: "1", Category: "t"} db.CreatePackage(b) - db.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: b.GetFingerPrint(), Files: []string{"barz", "f"}}) + db.SetPackageFiles(&types.PackageFile{PackageFingerprint: b.GetFingerPrint(), Files: []string{"barz", "f"}}) }) It("detects when are already shipped by other packages", func() { diff --git a/pkg/package/database.go b/pkg/package/database.go deleted file mode 100644 index 882ecde5..00000000 --- a/pkg/package/database.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright © 2019 Ettore Di Giacinto -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, see . - -package pkg - -// Database is a merely simple in-memory db. -// FIXME: Use a proper structure or delegate to third-party -type PackageDatabase interface { - PackageSet - - Get(s string) (string, error) - Set(k, v string) error - - Create(string, []byte) (string, error) - Retrieve(ID string) ([]byte, error) -} - -type PackageSet interface { - Clone(PackageDatabase) error - Copy() (PackageDatabase, error) - - GetRevdeps(p Package) (Packages, error) - GetPackages() []string //Ids - CreatePackage(pkg Package) (string, error) - GetPackage(ID string) (Package, error) - Clean() error - FindPackage(Package) (Package, error) - FindPackages(p Package) (Packages, error) - UpdatePackage(p Package) error - GetAllPackages(packages chan Package) error - RemovePackage(Package) error - - GetPackageFiles(Package) ([]string, error) - SetPackageFiles(*PackageFile) error - RemovePackageFiles(Package) error - FindPackageVersions(p Package) (Packages, error) - World() Packages - - FindPackageCandidate(p Package) (Package, error) - FindPackageLabel(labelKey string) (Packages, error) - FindPackageLabelMatch(pattern string) (Packages, error) - FindPackageMatch(pattern string) (Packages, error) - FindPackageByFile(pattern string) (Packages, error) -} - -type PackageFile struct { - ID int `storm:"id,increment"` // primary key with auto increment - PackageFingerprint string - Files []string -} diff --git a/pkg/solver/benchmark_test.go b/pkg/solver/benchmark_test.go index 9a8a4a0d..e8b1b1ad 100644 --- a/pkg/solver/benchmark_test.go +++ b/pkg/solver/benchmark_test.go @@ -21,7 +21,8 @@ import ( "os" "strconv" - pkg "github.com/mudler/luet/pkg/package" + types "github.com/mudler/luet/pkg/api/core/types" + pkg "github.com/mudler/luet/pkg/database" "github.com/mudler/luet/tests/helpers" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -33,14 +34,14 @@ var _ = Describe("Solver Benchmarks", func() { db := pkg.NewInMemoryDatabase(false) dbInstalled := pkg.NewInMemoryDatabase(false) dbDefinitions := pkg.NewInMemoryDatabase(false) - var s PackageSolver + var s types.PackageSolver Context("Complex data sets", func() { BeforeEach(func() { db = pkg.NewInMemoryDatabase(false) dbInstalled = pkg.NewInMemoryDatabase(false) dbDefinitions = pkg.NewInMemoryDatabase(false) - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) if os.Getenv("BENCHMARK_TESTS") != "true" { Skip("BENCHMARK_TESTS not enabled") } @@ -49,15 +50,15 @@ var _ = Describe("Solver Benchmarks", func() { runtime := b.Time("runtime", func() { for i := 0; i < 50000; i++ { - C := pkg.NewPackage("C"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H"+strconv.Itoa(i), "", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D"+strconv.Itoa(i), "", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B"+strconv.Itoa(i), "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A"+strconv.Itoa(i), "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + C := types.NewPackage("C"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H"+strconv.Itoa(i), "", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D"+strconv.Itoa(i), "", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B"+strconv.Itoa(i), "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A"+strconv.Itoa(i), "", []*types.Package{B}, []*types.Package{}) + for _, p := range []*types.Package{A, B, C, D, E, F, G} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -66,22 +67,22 @@ var _ = Describe("Solver Benchmarks", func() { } for i := 0; i < 1; i++ { - C := pkg.NewPackage("C"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H"+strconv.Itoa(i), "", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D"+strconv.Itoa(i), "", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B"+strconv.Itoa(i), "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A"+strconv.Itoa(i), "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H"+strconv.Itoa(i), "", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D"+strconv.Itoa(i), "", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B"+strconv.Itoa(i), "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A"+strconv.Itoa(i), "", []*types.Package{B}, []*types.Package{}) - solution, err := s.Install([]pkg.Package{A}) + solution, err := s.Install([]*types.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: G, Value: true})) } }) @@ -94,7 +95,7 @@ var _ = Describe("Solver Benchmarks", func() { db = pkg.NewInMemoryDatabase(false) dbInstalled = pkg.NewInMemoryDatabase(false) dbDefinitions = pkg.NewInMemoryDatabase(false) - s = NewSolver(Options{Type: SingleCoreSimple, Concurrency: 10}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple, Concurrency: 10}, dbInstalled, dbDefinitions, db) if os.Getenv("BENCHMARK_TESTS") != "true" { Skip("BENCHMARK_TESTS not enabled") } @@ -102,15 +103,15 @@ var _ = Describe("Solver Benchmarks", func() { Measure("it should be fast in resolution from a 50000 dataset", func(b Benchmarker) { runtime := b.Time("runtime", func() { for i := 0; i < 50000; i++ { - C := pkg.NewPackage("C"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H"+strconv.Itoa(i), "", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D"+strconv.Itoa(i), "", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B"+strconv.Itoa(i), "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A"+strconv.Itoa(i), "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + C := types.NewPackage("C"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H"+strconv.Itoa(i), "", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D"+strconv.Itoa(i), "", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B"+strconv.Itoa(i), "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A"+strconv.Itoa(i), "", []*types.Package{B}, []*types.Package{}) + for _, p := range []*types.Package{A, B, C, D, E, F, G} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -118,22 +119,22 @@ var _ = Describe("Solver Benchmarks", func() { Expect(err).ToNot(HaveOccurred()) } for i := 0; i < 1; i++ { - C := pkg.NewPackage("C"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G"+strconv.Itoa(i), "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H"+strconv.Itoa(i), "", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D"+strconv.Itoa(i), "", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B"+strconv.Itoa(i), "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A"+strconv.Itoa(i), "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G"+strconv.Itoa(i), "", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H"+strconv.Itoa(i), "", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D"+strconv.Itoa(i), "", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B"+strconv.Itoa(i), "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A"+strconv.Itoa(i), "", []*types.Package{B}, []*types.Package{}) - solution, err := s.Install([]pkg.Package{A}) + solution, err := s.Install([]*types.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: G, Value: true})) // Expect(len(solution)).To(Equal(6)) } @@ -152,7 +153,7 @@ var _ = Describe("Solver Benchmarks", func() { // dbInstalled = pkg.NewInMemoryDatabase(false) dbDefinitions = pkg.NewInMemoryDatabase(false) - s = NewSolver(Options{Type: SingleCoreSimple, Concurrency: 100}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple, Concurrency: 100}, dbInstalled, dbDefinitions, db) if os.Getenv("BENCHMARK_TESTS") != "true" { Skip("BENCHMARK_TESTS not enabled") } @@ -161,26 +162,26 @@ var _ = Describe("Solver Benchmarks", func() { Measure("it should be fast in resolution from a 10000*8 dataset", func(b Benchmarker) { runtime := b.Time("runtime", func() { for i := 2; i < 10000; i++ { - C := pkg.NewPackage("C", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", strconv.Itoa(i), []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", strconv.Itoa(i), []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", strconv.Itoa(i), []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", strconv.Itoa(i), []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - for _, p := range []pkg.Package{A, B, C, D, E, F, G, H} { + C := types.NewPackage("C", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", strconv.Itoa(i), []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", strconv.Itoa(i), []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", strconv.Itoa(i), []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", strconv.Itoa(i), []*types.Package{B}, []*types.Package{}) + for _, p := range []*types.Package{A, B, C, D, E, F, G, H} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } } - //C := pkg.NewPackage("C", "1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G", "1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", "1", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "1", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "1", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "1", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + //C := types.NewPackage("C", "1", []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G", "1", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", "1", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", "1", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", "1", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "1", []*types.Package{B}, []*types.Package{}) _, err := dbInstalled.CreatePackage(A) Expect(err).ToNot(HaveOccurred()) _, err = dbInstalled.CreatePackage(B) @@ -198,12 +199,12 @@ var _ = Describe("Solver Benchmarks", func() { Expect(packages).To(ContainElement(A)) - G = pkg.NewPackage("G", "9999", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H = pkg.NewPackage("H", "9999", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D = pkg.NewPackage("D", "9999", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B = pkg.NewPackage("B", "9999", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A = pkg.NewPackage("A", "9999", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - Expect(ass).To(ContainElement(PackageAssert{Package: A, Value: true})) + G = types.NewPackage("G", "9999", []*types.Package{}, []*types.Package{}) + H = types.NewPackage("H", "9999", []*types.Package{G}, []*types.Package{}) + D = types.NewPackage("D", "9999", []*types.Package{H}, []*types.Package{}) + B = types.NewPackage("B", "9999", []*types.Package{D}, []*types.Package{}) + A = types.NewPackage("A", "9999", []*types.Package{B}, []*types.Package{}) + Expect(ass).To(ContainElement(types.PackageAssert{Package: A, Value: true})) Expect(len(packages)).To(Equal(5)) // Expect(len(solution)).To(Equal(6)) @@ -216,15 +217,15 @@ var _ = Describe("Solver Benchmarks", func() { Measure("it should be fast in installation with 12000 packages installed and 2000*8 available", func(b Benchmarker) { runtime := b.Time("runtime", func() { for i := 0; i < 2000; i++ { - C := pkg.NewPackage("C", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", strconv.Itoa(i), []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", strconv.Itoa(i), []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", strconv.Itoa(i), []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", strconv.Itoa(i), []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + C := types.NewPackage("C", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", strconv.Itoa(i), []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", strconv.Itoa(i), []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", strconv.Itoa(i), []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", strconv.Itoa(i), []*types.Package{B}, []*types.Package{}) + for _, p := range []*types.Package{A, B, C, D, E, F, G} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -237,16 +238,16 @@ var _ = Describe("Solver Benchmarks", func() { Expect(err).ToNot(HaveOccurred()) } - G := pkg.NewPackage("G", strconv.Itoa(50000), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", strconv.Itoa(50000), []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", strconv.Itoa(50000), []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", strconv.Itoa(50000), []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", strconv.Itoa(50000), []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + G := types.NewPackage("G", strconv.Itoa(50000), []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", strconv.Itoa(50000), []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", strconv.Itoa(50000), []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", strconv.Itoa(50000), []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", strconv.Itoa(50000), []*types.Package{B}, []*types.Package{}) - ass, err := s.Install([]pkg.Package{A}) + ass, err := s.Install([]*types.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(ass).To(ContainElement(PackageAssert{Package: pkg.NewPackage("A", "50000", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}), Value: true})) + Expect(ass).To(ContainElement(types.PackageAssert{Package: types.NewPackage("A", "50000", []*types.Package{B}, []*types.Package{}), Value: true})) //Expect(ass).To(Equal(5)) // Expect(len(solution)).To(Equal(6)) @@ -258,26 +259,26 @@ var _ = Describe("Solver Benchmarks", func() { Measure("it should be fast in resolution from a 50000 dataset with upgrade universe", func(b Benchmarker) { runtime := b.Time("runtime", func() { for i := 0; i < 2; i++ { - C := pkg.NewPackage("C", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G", strconv.Itoa(i), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", strconv.Itoa(i), []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", strconv.Itoa(i), []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", strconv.Itoa(i), []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", strconv.Itoa(i), []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + C := types.NewPackage("C", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G", strconv.Itoa(i), []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", strconv.Itoa(i), []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", strconv.Itoa(i), []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", strconv.Itoa(i), []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", strconv.Itoa(i), []*types.Package{B}, []*types.Package{}) + for _, p := range []*types.Package{A, B, C, D, E, F, G} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } fmt.Println("Creating package, run", i) } - G := pkg.NewPackage("G", "1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", "1", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "1", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "1", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "1", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + G := types.NewPackage("G", "1", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", "1", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", "1", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", "1", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "1", []*types.Package{B}, []*types.Package{}) _, err := dbInstalled.CreatePackage(A) Expect(err).ToNot(HaveOccurred()) fmt.Println("Upgrade starts") @@ -285,8 +286,8 @@ var _ = Describe("Solver Benchmarks", func() { packages, ass, err := s.UpgradeUniverse(true) Expect(err).ToNot(HaveOccurred()) - Expect(ass).To(ContainElement(PackageAssert{Package: pkg.NewPackage("A", "50000", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}), Value: true})) - Expect(packages).To(ContainElement(pkg.NewPackage("A", "50000", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}))) + Expect(ass).To(ContainElement(types.PackageAssert{Package: types.NewPackage("A", "50000", []*types.Package{B}, []*types.Package{}), Value: true})) + Expect(packages).To(ContainElement(types.NewPackage("A", "50000", []*types.Package{B}, []*types.Package{}))) Expect(packages).To(Equal(5)) // Expect(len(solution)).To(Equal(6)) diff --git a/pkg/solver/decoder.go b/pkg/solver/decoder.go index 20e2ec12..f5bf2184 100644 --- a/pkg/solver/decoder.go +++ b/pkg/solver/decoder.go @@ -16,339 +16,19 @@ package solver import ( - "crypto/sha256" - "fmt" - "sort" - "unicode" - - pkg "github.com/mudler/luet/pkg/package" - "github.com/mudler/topsort" - toposort "github.com/philopon/go-toposort" - "github.com/pkg/errors" + types "github.com/mudler/luet/pkg/api/core/types" ) -type PackagesAssertions []PackageAssert - -type PackageHash struct { - BuildHash string - PackageHash string -} - -// PackageAssert represent a package assertion. -// It is composed of a Package and a Value which is indicating the absence or not -// of the associated package state. -type PackageAssert struct { - Package *pkg.DefaultPackage - Value bool - Hash PackageHash -} - -// DecodeModel decodes a model from the SAT solver to package assertions (PackageAssert) -func DecodeModel(model map[string]bool, db pkg.PackageDatabase) (PackagesAssertions, error) { - ass := make(PackagesAssertions, 0) +// DecodeModel decodes a model from the SAT solver to package assertions (types.PackageAssert) +func DecodeModel(model map[string]bool, db types.PackageDatabase) (types.PackagesAssertions, error) { + ass := make(types.PackagesAssertions, 0) for k, v := range model { - a, err := pkg.DecodePackage(k, db) + a, err := types.DecodePackage(k, db) if err != nil { return nil, err } - ass = append(ass, PackageAssert{Package: a.(*pkg.DefaultPackage), Value: v}) + ass = append(ass, types.PackageAssert{Package: a, Value: v}) } return ass, nil } - -func (a *PackageAssert) Explain() { - fmt.Println(a.ToString()) - a.Package.Explain() -} - -func (a *PackageAssert) String() string { - return a.ToString() -} - -func (a *PackageAssert) ToString() string { - var msg string - if a.Value { - msg = "installed" - } else { - msg = "not installed" - } - return fmt.Sprintf("%s/%s %s %s", a.Package.GetCategory(), a.Package.GetName(), a.Package.GetVersion(), msg) -} - -func (assertions PackagesAssertions) EnsureOrder() PackagesAssertions { - - orderedAssertions := PackagesAssertions{} - unorderedAssertions := PackagesAssertions{} - fingerprints := []string{} - - tmpMap := map[string]PackageAssert{} - - for _, a := range assertions { - tmpMap[a.Package.GetFingerPrint()] = a - fingerprints = append(fingerprints, a.Package.GetFingerPrint()) - unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered - - if a.Value { - unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered - } else { - orderedAssertions = append(orderedAssertions, a) // Keep last the ones which are not meant to be installed - } - } - - sort.Sort(unorderedAssertions) - - // Build a topological graph - graph := toposort.NewGraph(len(unorderedAssertions)) - graph.AddNodes(fingerprints...) - for _, a := range unorderedAssertions { - for _, req := range a.Package.GetRequires() { - graph.AddEdge(a.Package.GetFingerPrint(), req.GetFingerPrint()) - } - } - result, ok := graph.Toposort() - if !ok { - panic("Cycle found") - } - for _, res := range result { - a, ok := tmpMap[res] - if !ok { - panic("fail") - // continue - } - orderedAssertions = append(orderedAssertions, a) - // orderedAssertions = append(PackagesAssertions{a}, orderedAssertions...) // push upfront - } - //helpers.ReverseAny(orderedAssertions) - return orderedAssertions -} - -func (assertions PackagesAssertions) SearchByName(f string) *PackageAssert { - for _, a := range assertions { - if a.Value { - if a.Package.GetPackageName() == f { - return &a - } - } - } - - return nil -} -func (assertions PackagesAssertions) Search(f string) *PackageAssert { - for _, a := range assertions { - if a.Value { - if a.Package.GetFingerPrint() == f { - return &a - } - } - } - - return nil -} - -func (assertions PackagesAssertions) ToDB() pkg.PackageDatabase { - db := pkg.NewInMemoryDatabase(false) - for _, a := range assertions { - if a.Value { - db.CreatePackage(a.Package) - } - } - - return db -} - -func (assertions PackagesAssertions) Order(definitiondb pkg.PackageDatabase, fingerprint string) (PackagesAssertions, error) { - - orderedAssertions := PackagesAssertions{} - unorderedAssertions := PackagesAssertions{} - - tmpMap := map[string]PackageAssert{} - graph := topsort.NewGraph() - for _, a := range assertions { - graph.AddNode(a.Package.GetFingerPrint()) - tmpMap[a.Package.GetFingerPrint()] = a - unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered - } - - sort.Sort(unorderedAssertions) - // Build a topological graph - for _, a := range unorderedAssertions { - currentPkg := a.Package - added := map[string]interface{}{} - REQUIRES: - for _, requiredDef := range currentPkg.GetRequires() { - if def, err := definitiondb.FindPackage(requiredDef); err == nil { // Provides: Get a chance of being override here - requiredDef = def.(*pkg.DefaultPackage) - } - - // We cannot search for fingerprint, as we could have selector in versions. - // We know that the assertions are unique for packages, so look for a package with such name in the assertions - req := assertions.SearchByName(requiredDef.GetPackageName()) - if req != nil { - requiredDef = req.Package - } - if _, ok := added[requiredDef.GetFingerPrint()]; ok { - continue REQUIRES - } - // Expand also here, as we need to order them (or instead the solver should give back the dep correctly?) - graph.AddEdge(currentPkg.GetFingerPrint(), requiredDef.GetFingerPrint()) - added[requiredDef.GetFingerPrint()] = true - } - } - result, err := graph.TopSort(fingerprint) - if err != nil { - return nil, errors.Wrap(err, "fail on sorting "+fingerprint) - } - for _, res := range result { - a, ok := tmpMap[res] - if !ok { - //return nil, errors.New("fail looking for " + res) - // Since now we don't return the entire world as part of assertions - // if we don't find any reference must be because fingerprint we are analyzing (which is the one we are ordering against) - // is not part of the assertions, thus we can omit it from the result - continue - } - orderedAssertions = append(orderedAssertions, a) - // orderedAssertions = append(PackagesAssertions{a}, orderedAssertions...) // push upfront - } - //helpers.ReverseAny(orderedAssertions) - return orderedAssertions, nil -} - -func (assertions PackagesAssertions) Explain() string { - var fingerprint string - for _, assertion := range assertions { // Always order them - fingerprint += assertion.ToString() + "\n" - } - return fingerprint -} - -func (a PackagesAssertions) Len() int { return len(a) } -func (a PackagesAssertions) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a PackagesAssertions) Less(i, j int) bool { - - iRunes := []rune(a[i].Package.GetName()) - jRunes := []rune(a[j].Package.GetName()) - - max := len(iRunes) - if max > len(jRunes) { - max = len(jRunes) - } - - for idx := 0; idx < max; idx++ { - ir := iRunes[idx] - jr := jRunes[idx] - - lir := unicode.ToLower(ir) - ljr := unicode.ToLower(jr) - - if lir != ljr { - return lir < ljr - } - - // the lowercase runes are the same, so compare the original - if ir != jr { - return ir < jr - } - } - - return false - -} - -func (a PackagesAssertions) TrueLen() int { - count := 0 - for _, ass := range a { - if ass.Value { - count++ - } - } - - return count -} - -// HashFrom computes the assertion hash From a given package. It drops it from the assertions -// and checks it's not the only one. if it's unique it marks it specially - so the hash -// which is generated is unique for the selected package -func (assertions PackagesAssertions) HashFrom(p pkg.Package) string { - return assertions.SaltedHashFrom(p, map[string]string{}) -} - -func (assertions PackagesAssertions) AssertionHash() string { - return assertions.SaltedAssertionHash(map[string]string{}) -} - -func (assertions PackagesAssertions) SaltedHashFrom(p pkg.Package, salts map[string]string) string { - var assertionhash string - - // When we don't have any solution to hash for, we need to generate an UUID by ourselves - latestsolution := assertions.Drop(p) - if latestsolution.TrueLen() == 0 { - // Preserve the hash if supplied of marked packages - marked := p.Mark() - if markedHash, exists := salts[p.GetFingerPrint()]; exists { - salts[marked.GetFingerPrint()] = markedHash - } - assertionhash = assertions.Mark(p).SaltedAssertionHash(salts) - } else { - assertionhash = latestsolution.SaltedAssertionHash(salts) - } - return assertionhash -} - -func (assertions PackagesAssertions) SaltedAssertionHash(salts map[string]string) string { - var fingerprint string - for _, assertion := range assertions { // Note: Always order them first! - if assertion.Value { // Tke into account only dependencies installed (get fingerprint of subgraph) - salt, exists := salts[assertion.Package.GetFingerPrint()] - if exists { - fingerprint += assertion.ToString() + salt + "\n" - - } else { - fingerprint += assertion.ToString() + "\n" - } - } - } - hash := sha256.Sum256([]byte(fingerprint)) - return fmt.Sprintf("%x", hash) -} - -func (assertions PackagesAssertions) Drop(p pkg.Package) PackagesAssertions { - ass := PackagesAssertions{} - - for _, a := range assertions { - if !a.Package.Matches(p) { - ass = append(ass, a) - } - } - return ass -} - -// Cut returns an assertion list of installed (filter by Value) "cutted" until the package is found (included) -func (assertions PackagesAssertions) Cut(p pkg.Package) PackagesAssertions { - ass := PackagesAssertions{} - - for _, a := range assertions { - if a.Value { - ass = append(ass, a) - if a.Package.Matches(p) { - break - } - } - } - return ass -} - -// Mark returns a new assertion with the package marked -func (assertions PackagesAssertions) Mark(p pkg.Package) PackagesAssertions { - ass := PackagesAssertions{} - - for _, a := range assertions { - if a.Package.Matches(p) { - marked := a.Package.Mark() - a = PackageAssert{Package: marked.(*pkg.DefaultPackage), Value: a.Value, Hash: a.Hash} - } - ass = append(ass, a) - } - return ass -} diff --git a/pkg/solver/decoder_test.go b/pkg/solver/decoder_test.go index 81147150..d1c5b713 100644 --- a/pkg/solver/decoder_test.go +++ b/pkg/solver/decoder_test.go @@ -18,8 +18,8 @@ package solver_test import ( "strconv" - pkg "github.com/mudler/luet/pkg/package" - "github.com/mudler/luet/pkg/solver" + "github.com/mudler/luet/pkg/api/core/types" + pkg "github.com/mudler/luet/pkg/database" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -30,13 +30,13 @@ var _ = Describe("Decoder", func() { db := pkg.NewInMemoryDatabase(false) dbInstalled := pkg.NewInMemoryDatabase(false) dbDefinitions := pkg.NewInMemoryDatabase(false) - s := NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s := NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) BeforeEach(func() { db = pkg.NewInMemoryDatabase(false) dbInstalled = pkg.NewInMemoryDatabase(false) dbDefinitions = pkg.NewInMemoryDatabase(false) - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) }) Context("Assertion ordering", func() { @@ -44,32 +44,32 @@ var _ = Describe("Decoder", func() { for index := 0; index < 300; index++ { // Just to make sure we don't have false positives It("Orders them correctly #"+strconv.Itoa(index), func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", "", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G", "", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", "", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + for _, p := range []*types.Package{A, B, C, D, E, F, G} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) + solution, err := s.Install([]*types.Package{A}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) @@ -95,32 +95,32 @@ var _ = Describe("Decoder", func() { for index := 0; index < 300; index++ { // Just to make sure we don't have false positives It("Doesn't order them correctly otherwise #"+strconv.Itoa(index), func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", "", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G", "", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", "", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + for _, p := range []*types.Package{A, B, C, D, E, F, G} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) + solution, err := s.Install([]*types.Package{A}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) @@ -161,32 +161,32 @@ var _ = Describe("Decoder", func() { Context("Assertion hashing", func() { It("Hashes them, and could be used for comparison", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", "", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G", "", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", "", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + for _, p := range []*types.Package{A, B, C, D, E, F, G} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) + solution, err := s.Install([]*types.Package{A}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) @@ -200,12 +200,12 @@ var _ = Describe("Decoder", func() { hash := solution.AssertionHash() - solution, err = s.Install([]pkg.Package{B}) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) + solution, err = s.Install([]*types.Package{B}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) @@ -226,24 +226,24 @@ var _ = Describe("Decoder", func() { }) It("Hashes them, and could be used for comparison", func() { - X := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - Y := pkg.NewPackage("Y", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) - Z := pkg.NewPackage("Z", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) + X := types.NewPackage("X", "", []*types.Package{}, []*types.Package{}) + Y := types.NewPackage("Y", "", []*types.Package{X}, []*types.Package{}) + Z := types.NewPackage("Z", "", []*types.Package{X}, []*types.Package{}) - for _, p := range []pkg.Package{X, Y, Z} { + for _, p := range []*types.Package{X, Y, Z} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{Y}) + solution, err := s.Install([]*types.Package{Y}) Expect(err).ToNot(HaveOccurred()) - solution2, err := s.Install([]pkg.Package{Z}) + solution2, err := s.Install([]*types.Package{Z}) Expect(err).ToNot(HaveOccurred()) orderY, err := solution.Order(dbDefinitions, Y.GetFingerPrint()) Expect(err).ToNot(HaveOccurred()) @@ -254,24 +254,24 @@ var _ = Describe("Decoder", func() { It("Hashes them, Cuts them and could be used for comparison", func() { - X := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - Y := pkg.NewPackage("Y", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) - Z := pkg.NewPackage("Z", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) + X := types.NewPackage("X", "", []*types.Package{}, []*types.Package{}) + Y := types.NewPackage("Y", "", []*types.Package{X}, []*types.Package{}) + Z := types.NewPackage("Z", "", []*types.Package{X}, []*types.Package{}) - for _, p := range []pkg.Package{X, Y, Z} { + for _, p := range []*types.Package{X, Y, Z} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{Y}) + solution, err := s.Install([]*types.Package{Y}) Expect(err).ToNot(HaveOccurred()) - solution2, err := s.Install([]pkg.Package{Z}) + solution2, err := s.Install([]*types.Package{Z}) Expect(err).ToNot(HaveOccurred()) orderY, err := solution.Order(dbDefinitions, Y.GetFingerPrint()) Expect(err).ToNot(HaveOccurred()) @@ -284,24 +284,24 @@ var _ = Describe("Decoder", func() { It("HashFrom can be used equally", func() { - X := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - Y := pkg.NewPackage("Y", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) - Z := pkg.NewPackage("Z", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) + X := types.NewPackage("X", "", []*types.Package{}, []*types.Package{}) + Y := types.NewPackage("Y", "", []*types.Package{X}, []*types.Package{}) + Z := types.NewPackage("Z", "", []*types.Package{X}, []*types.Package{}) - for _, p := range []pkg.Package{X, Y, Z} { + for _, p := range []*types.Package{X, Y, Z} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{Y}) + solution, err := s.Install([]*types.Package{Y}) Expect(err).ToNot(HaveOccurred()) - solution2, err := s.Install([]pkg.Package{Z}) + solution2, err := s.Install([]*types.Package{Z}) Expect(err).ToNot(HaveOccurred()) orderY, err := solution.Order(dbDefinitions, Y.GetFingerPrint()) Expect(err).ToNot(HaveOccurred()) @@ -314,27 +314,27 @@ var _ = Describe("Decoder", func() { It("Unique hashes for single packages", func() { - X := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + X := types.NewPackage("X", "", []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("X", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{X, F, D} { + for _, p := range []*types.Package{X, F, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{X}) + solution, err := s.Install([]*types.Package{X}) Expect(err).ToNot(HaveOccurred()) - solution2, err := s.Install([]pkg.Package{F}) + solution2, err := s.Install([]*types.Package{F}) Expect(err).ToNot(HaveOccurred()) - solution3, err := s.Install([]pkg.Package{D}) + solution3, err := s.Install([]*types.Package{D}) Expect(err).ToNot(HaveOccurred()) Expect(solution.AssertionHash()).ToNot(Equal(solution2.AssertionHash())) @@ -343,41 +343,41 @@ var _ = Describe("Decoder", func() { }) It("Unique hashes for empty assertions", func() { - empty := solver.PackagesAssertions{} - empty2 := solver.PackagesAssertions{} + empty := types.PackagesAssertions{} + empty2 := types.PackagesAssertions{} Expect(empty.AssertionHash()).To(Equal(empty2.AssertionHash())) }) It("Unique hashes for single packages with HashFrom", func() { - X := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - Y := pkg.NewPackage("Y", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) + X := types.NewPackage("X", "", []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("X", "", []*types.Package{}, []*types.Package{}) + Y := types.NewPackage("Y", "", []*types.Package{X}, []*types.Package{}) - empty := solver.PackagesAssertions{} + empty := types.PackagesAssertions{} - for _, p := range []pkg.Package{X, F, D, Y} { + for _, p := range []*types.Package{X, F, D, Y} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{X}) + solution, err := s.Install([]*types.Package{X}) Expect(err).ToNot(HaveOccurred()) - solution2, err := s.Install([]pkg.Package{F}) + solution2, err := s.Install([]*types.Package{F}) Expect(err).ToNot(HaveOccurred()) - solution3, err := s.Install([]pkg.Package{D}) + solution3, err := s.Install([]*types.Package{D}) Expect(err).ToNot(HaveOccurred()) - solution4, err := s.Install([]pkg.Package{Y}) + solution4, err := s.Install([]*types.Package{Y}) Expect(err).ToNot(HaveOccurred()) Expect(solution.HashFrom(X)).ToNot(Equal(solution2.HashFrom(F))) @@ -395,22 +395,22 @@ var _ = Describe("Decoder", func() { It("Always same solution", func() { - X := pkg.NewPackage("X", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - Y := pkg.NewPackage("Y", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) - Z := pkg.NewPackage("Z", "", []*pkg.DefaultPackage{X}, []*pkg.DefaultPackage{}) - W := pkg.NewPackage("W", "", []*pkg.DefaultPackage{Z, Y}, []*pkg.DefaultPackage{}) + X := types.NewPackage("X", "", []*types.Package{}, []*types.Package{}) + Y := types.NewPackage("Y", "", []*types.Package{X}, []*types.Package{}) + Z := types.NewPackage("Z", "", []*types.Package{X}, []*types.Package{}) + W := types.NewPackage("W", "", []*types.Package{Z, Y}, []*types.Package{}) - for _, p := range []pkg.Package{X, Y, Z} { + for _, p := range []*types.Package{X, Y, Z} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{W}) + solution, err := s.Install([]*types.Package{W}) Expect(err).ToNot(HaveOccurred()) orderW, err := solution.Order(dbDefinitions, W.GetFingerPrint()) diff --git a/pkg/solver/explainer.go b/pkg/solver/explainer.go new file mode 100644 index 00000000..1f4d5e01 --- /dev/null +++ b/pkg/solver/explainer.go @@ -0,0 +1,135 @@ +// Copyright © 2021-2022 Ettore Di Giacinto +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . + +package solver + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" + + "github.com/crillab/gophersat/bf" + "github.com/crillab/gophersat/explain" + types "github.com/mudler/luet/pkg/api/core/types" + "github.com/pkg/errors" +) + +type Explainer struct{} + +func decodeDimacs(vars map[string]string, dimacs string) (string, error) { + res := "" + sc := bufio.NewScanner(bytes.NewBufferString(dimacs)) + lines := strings.Split(dimacs, "\n") + linenum := 1 +SCAN: + for sc.Scan() { + + line := sc.Text() + fields := strings.Fields(line) + if len(fields) == 0 { + continue + } + switch fields[0] { + case "p": + continue SCAN + default: + for i := 0; i < len(fields)-1; i++ { + v := fields[i] + negative := false + if strings.HasPrefix(fields[i], "-") { + v = strings.TrimLeft(fields[i], "-") + negative = true + } + variable := vars[v] + if negative { + res += fmt.Sprintf("!(%s)", variable) + } else { + res += variable + } + + if i != len(fields)-2 { + res += fmt.Sprintf(" or ") + } + } + if linenum != len(lines)-1 { + res += fmt.Sprintf(" and \n") + } + } + linenum++ + } + if err := sc.Err(); err != nil { + return res, fmt.Errorf("could not parse problem: %v", err) + } + return res, nil +} + +func parseVars(r io.Reader) (map[string]string, error) { + sc := bufio.NewScanner(r) + res := map[string]string{} + for sc.Scan() { + line := sc.Text() + fields := strings.Fields(line) + if len(fields) == 0 { + continue + } + switch fields[0] { + case "c": + data := strings.Split(fields[1], "=") + res[data[1]] = data[0] + + default: + continue + + } + } + if err := sc.Err(); err != nil { + return nil, fmt.Errorf("could not parse problem: %v", err) + } + return res, nil +} + +// Solve tries to find the MUS (minimum unsat) formula from the original problem. +// it returns an error with the decoded dimacs +func (*Explainer) Solve(f bf.Formula, s types.PackageSolver) (types.PackagesAssertions, error) { + buf := bytes.NewBufferString("") + if err := bf.Dimacs(f, buf); err != nil { + return nil, errors.Wrap(err, "cannot extract dimacs from formula") + } + + copy := *buf + + pb, err := explain.ParseCNF(©) + if err != nil { + return nil, errors.Wrap(err, "could not parse problem") + } + pb2, err := pb.MUS() + if err != nil { + return nil, errors.Wrap(err, "could not extract subset") + } + + variables, err := parseVars(buf) + if err != nil { + return nil, errors.Wrap(err, "could not parse variables") + } + + res, err := decodeDimacs(variables, pb2.CNF()) + if err != nil { + return nil, errors.Wrap(err, "could not parse dimacs") + } + + return nil, fmt.Errorf("could not satisfy the constraints: \n%s", res) +} diff --git a/pkg/solver/resolver.go b/pkg/solver/resolver.go index 54b14597..0d61657e 100644 --- a/pkg/solver/resolver.go +++ b/pkg/solver/resolver.go @@ -16,21 +16,16 @@ package solver import ( - "bufio" - "bytes" "encoding/json" "fmt" - "io" "strconv" - "strings" "github.com/crillab/gophersat/bf" - "github.com/crillab/gophersat/explain" + "github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/helpers" "gopkg.in/yaml.v2" "github.com/ecooper/qlearning" - pkg "github.com/mudler/luet/pkg/package" "github.com/pkg/errors" ) @@ -56,117 +51,6 @@ const ( QLearningResolverType = "qlearning" ) -// PackageResolver assists PackageSolver on unsat cases -type PackageResolver interface { - Solve(bf.Formula, PackageSolver) (PackagesAssertions, error) -} - -type Explainer struct{} - -func decodeDimacs(vars map[string]string, dimacs string) (string, error) { - res := "" - sc := bufio.NewScanner(bytes.NewBufferString(dimacs)) - lines := strings.Split(dimacs, "\n") - linenum := 1 -SCAN: - for sc.Scan() { - - line := sc.Text() - fields := strings.Fields(line) - if len(fields) == 0 { - continue - } - switch fields[0] { - case "p": - continue SCAN - default: - for i := 0; i < len(fields)-1; i++ { - v := fields[i] - negative := false - if strings.HasPrefix(fields[i], "-") { - v = strings.TrimLeft(fields[i], "-") - negative = true - } - variable := vars[v] - if negative { - res += fmt.Sprintf("!(%s)", variable) - } else { - res += variable - } - - if i != len(fields)-2 { - res += fmt.Sprintf(" or ") - } - } - if linenum != len(lines)-1 { - res += fmt.Sprintf(" and \n") - } - } - linenum++ - } - if err := sc.Err(); err != nil { - return res, fmt.Errorf("could not parse problem: %v", err) - } - return res, nil -} - -func parseVars(r io.Reader) (map[string]string, error) { - sc := bufio.NewScanner(r) - res := map[string]string{} - for sc.Scan() { - line := sc.Text() - fields := strings.Fields(line) - if len(fields) == 0 { - continue - } - switch fields[0] { - case "c": - data := strings.Split(fields[1], "=") - res[data[1]] = data[0] - - default: - continue - - } - } - if err := sc.Err(); err != nil { - return nil, fmt.Errorf("could not parse problem: %v", err) - } - return res, nil -} - -// Solve tries to find the MUS (minimum unsat) formula from the original problem. -// it returns an error with the decoded dimacs -func (*Explainer) Solve(f bf.Formula, s PackageSolver) (PackagesAssertions, error) { - buf := bytes.NewBufferString("") - if err := bf.Dimacs(f, buf); err != nil { - return nil, errors.Wrap(err, "cannot extract dimacs from formula") - } - - copy := *buf - - pb, err := explain.ParseCNF(©) - if err != nil { - return nil, errors.Wrap(err, "could not parse problem") - } - pb2, err := pb.MUS() - if err != nil { - return nil, errors.Wrap(err, "could not extract subset") - } - - variables, err := parseVars(buf) - if err != nil { - return nil, errors.Wrap(err, "could not parse variables") - } - - res, err := decodeDimacs(variables, pb2.CNF()) - if err != nil { - return nil, errors.Wrap(err, "could not parse dimacs") - } - - return nil, fmt.Errorf("could not satisfy the constraints: \n%s", res) -} - type QLearningResolver struct { Attempts int @@ -176,24 +60,24 @@ type QLearningResolver struct { Attempted map[string]bool - Solver PackageSolver + Solver types.PackageSolver Formula bf.Formula - Targets pkg.Packages - Current pkg.Packages + Targets types.Packages + Current types.Packages observedDelta int - observedDeltaChoice pkg.Packages + observedDeltaChoice types.Packages Agent *qlearning.SimpleAgent } -func SimpleQLearningSolver() PackageResolver { +func SimpleQLearningSolver() types.PackageResolver { return NewQLearningResolver(DefaultLearningRate, DefaultDiscount, DefaultMaxAttempts, DefaultInitialObserved) } // Defaults LearningRate 0.7, Discount 1.0 -func NewQLearningResolver(LearningRate, Discount float32, MaxAttempts, initialObservedDelta int) PackageResolver { +func NewQLearningResolver(LearningRate, Discount float32, MaxAttempts, initialObservedDelta int) types.PackageResolver { return &QLearningResolver{ Agent: qlearning.NewSimpleAgent(LearningRate, Discount), observedDelta: initialObservedDelta, @@ -201,7 +85,7 @@ func NewQLearningResolver(LearningRate, Discount float32, MaxAttempts, initialOb } } -func (resolver *QLearningResolver) Solve(f bf.Formula, s PackageSolver) (PackagesAssertions, error) { +func (resolver *QLearningResolver) Solve(f bf.Formula, s types.PackageSolver) (types.PackagesAssertions, error) { // Info("Using QLearning solver to resolve conflicts. Please be patient.") resolver.Solver = s @@ -276,10 +160,10 @@ func (resolver *QLearningResolver) IsComplete() int { func (resolver *QLearningResolver) Try(c Choice) error { pack := c.Package - packtoAdd := pkg.FromString(pack) + packtoAdd := types.PackageFromString(pack) resolver.Attempted[pack+strconv.Itoa(int(c.Action))] = true // increase the count s, _ := resolver.Solver.(*Solver) - var filtered pkg.Packages + var filtered types.Packages switch c.Action { case ActionAdded: diff --git a/pkg/solver/resolver_test.go b/pkg/solver/resolver_test.go index c0694c72..e3b62628 100644 --- a/pkg/solver/resolver_test.go +++ b/pkg/solver/resolver_test.go @@ -16,7 +16,9 @@ package solver_test import ( - pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" + + pkg "github.com/mudler/luet/pkg/database" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -28,65 +30,65 @@ var _ = Describe("Resolver", func() { db := pkg.NewInMemoryDatabase(false) dbInstalled := pkg.NewInMemoryDatabase(false) dbDefinitions := pkg.NewInMemoryDatabase(false) - s := NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s := NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) BeforeEach(func() { db = pkg.NewInMemoryDatabase(false) dbInstalled = pkg.NewInMemoryDatabase(false) dbDefinitions = pkg.NewInMemoryDatabase(false) - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) }) Context("Conflict set", func() { Context("Explainer", func() { It("is unsolvable - as we something we ask to install conflict with system stuff", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{C}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{C}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C} { + for _, p := range []*types.Package{A, B, C} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{A}) + solution, err := s.Install([]*types.Package{A}) Expect(len(solution)).To(Equal(0)) Expect(err).To(HaveOccurred()) }) It("succeeds to install D and F if explictly requested", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{C}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{C}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E", "", []*types.Package{B}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E, F} { + for _, p := range []*types.Package{A, B, C, D, E, F} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{D, F}) // D and F should go as they have no deps. A/E should be filtered by QLearn + solution, err := s.Install([]*types.Package{D, F}) // D and F should go as they have no deps. A/E should be filtered by QLearn Expect(err).ToNot(HaveOccurred()) Expect(len(solution)).To(Equal(6)) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).ToNot(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).ToNot(ContainElement(PackageAssert{Package: E, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: F, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: E, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: F, Value: true})) }) @@ -94,82 +96,82 @@ var _ = Describe("Resolver", func() { Context("QLearningResolver", func() { It("will find out that we can install D by ignoring A", func() { s.SetResolver(SimpleQLearningSolver()) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{C}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{C}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{A, D}) + solution, err := s.Install([]*types.Package{A, D}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).ToNot(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).ToNot(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) Expect(len(solution)).To(Equal(4)) }) It("will find out that we can install D and F by ignoring E and A", func() { s.SetResolver(SimpleQLearningSolver()) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{C}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{C}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E", "", []*types.Package{B}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E, F} { + for _, p := range []*types.Package{A, B, C, D, E, F} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{A, D, E, F}) // D and F should go as they have no deps. A/E should be filtered by QLearn + solution, err := s.Install([]*types.Package{A, D, E, F}) // D and F should go as they have no deps. A/E should be filtered by QLearn Expect(err).ToNot(HaveOccurred()) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) // Was already installed - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: F, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) // Was already installed + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: E, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: F, Value: true})) Expect(len(solution)).To(Equal(6)) }) }) Context("Explainer", func() { It("cannot find a solution", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{C}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{C}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{A, D}) + solution, err := s.Install([]*types.Package{A, D}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(Equal(`could not satisfy the constraints: A-- and diff --git a/pkg/solver/solver.go b/pkg/solver/solver.go index bfff08d6..d306b94c 100644 --- a/pkg/solver/solver.go +++ b/pkg/solver/solver.go @@ -19,68 +19,52 @@ import ( //. "github.com/mudler/luet/pkg/logger" "fmt" + "strings" "github.com/pkg/errors" "github.com/crillab/gophersat/bf" - pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" + pkg "github.com/mudler/luet/pkg/database" ) -type SolverType int - -const ( - SingleCoreSimple = 0 -) - -// PackageSolver is an interface to a generic package solving algorithm -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) - Conflicts(pack pkg.Package, lsp pkg.Packages) (bool, error) - - World() pkg.Packages - Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAssertions, error) - - UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAssertions, error) - UninstallUniverse(toremove pkg.Packages) (pkg.Packages, error) - - SetResolver(PackageResolver) - - Solve() (PackagesAssertions, error) - // BestInstall(c pkg.Packages) (PackagesAssertions, error) -} +var AvailableResolvers = strings.Join([]string{QLearningResolverType}, " ") // Solver is the default solver for luet type Solver struct { - DefinitionDatabase pkg.PackageDatabase - SolverDatabase pkg.PackageDatabase - Wanted pkg.Packages - InstalledDatabase pkg.PackageDatabase + DefinitionDatabase types.PackageDatabase + SolverDatabase types.PackageDatabase + Wanted types.Packages + InstalledDatabase types.PackageDatabase - Resolver PackageResolver -} - -type Options struct { - Type SolverType `yaml:"type,omitempty"` - Concurrency int `yaml:"concurrency,omitempty"` + Resolver types.PackageResolver } // NewSolver accepts as argument two lists of packages, the first is the initial set, // the second represent all the known packages. -func NewSolver(t Options, installed pkg.PackageDatabase, definitiondb pkg.PackageDatabase, solverdb pkg.PackageDatabase) PackageSolver { +func NewSolver(t types.SolverOptions, installed types.PackageDatabase, definitiondb types.PackageDatabase, solverdb types.PackageDatabase) types.PackageSolver { return NewResolver(t, installed, definitiondb, solverdb, &Explainer{}) } +func NewSolverFromOptions(t types.LuetSolverOptions) types.PackageResolver { + switch t.Type { + case QLearningResolverType: + if t.LearnRate != 0.0 { + return NewQLearningResolver(t.LearnRate, t.Discount, t.MaxAttempts, 999999) + + } + return SimpleQLearningSolver() + } + + return &Explainer{} + +} + // NewResolver accepts as argument two lists of packages, the first is the initial set, // the second represent all the known packages. // Using constructors as in the future we foresee warmups for hot-restore solver cache -func NewResolver(t Options, installed pkg.PackageDatabase, definitiondb pkg.PackageDatabase, solverdb pkg.PackageDatabase, re PackageResolver) PackageSolver { - var s PackageSolver +func NewResolver(t types.SolverOptions, installed types.PackageDatabase, definitiondb types.PackageDatabase, solverdb types.PackageDatabase, re types.PackageResolver) types.PackageSolver { + var s types.PackageSolver switch t.Type { default: s = &Solver{InstalledDatabase: installed, DefinitionDatabase: definitiondb, SolverDatabase: solverdb, Resolver: re} @@ -91,20 +75,20 @@ func NewResolver(t Options, installed pkg.PackageDatabase, definitiondb pkg.Pack // SetDefinitionDatabase is a setter for the definition Database -func (s *Solver) SetDefinitionDatabase(db pkg.PackageDatabase) { +func (s *Solver) SetDefinitionDatabase(db types.PackageDatabase) { s.DefinitionDatabase = db } // SetResolver is a setter for the unsat resolver backend -func (s *Solver) SetResolver(r PackageResolver) { +func (s *Solver) SetResolver(r types.PackageResolver) { s.Resolver = r } -func (s *Solver) World() pkg.Packages { +func (s *Solver) World() types.Packages { return s.DefinitionDatabase.World() } -func (s *Solver) Installed() pkg.Packages { +func (s *Solver) Installed() types.Packages { return s.InstalledDatabase.World() } @@ -131,7 +115,7 @@ func (s *Solver) noRulesInstalled() bool { func (s *Solver) BuildInstalled() (bf.Formula, error) { var formulas []bf.Formula - var packages pkg.Packages + var packages types.Packages for _, p := range s.Installed() { packages = append(packages, p) for _, dep := range p.Related(s.InstalledDatabase) { @@ -190,7 +174,7 @@ func (s *Solver) BuildPartialWorld(includeInstalled bool) (bf.Formula, error) { formulas = append(formulas, solvable) } - var packages pkg.Packages + var packages types.Packages for _, p := range s.Wanted { // packages = append(packages, p) for _, dep := range p.Related(s.DefinitionDatabase) { @@ -214,8 +198,8 @@ func (s *Solver) BuildPartialWorld(includeInstalled bool) (bf.Formula, error) { return bf.True, nil } -func (s *Solver) getList(db pkg.PackageDatabase, lsp pkg.Packages) (pkg.Packages, error) { - var ls pkg.Packages +func (s *Solver) getList(db types.PackageDatabase, lsp types.Packages) (types.Packages, error) { + var ls types.Packages for _, pp := range lsp { cp, err := db.FindPackage(pp) @@ -235,7 +219,7 @@ func (s *Solver) getList(db pkg.PackageDatabase, lsp pkg.Packages) (pkg.Packages // Conflicts acts like ConflictsWith, but uses package's reverse dependencies to // determine if it conflicts with the given set -func (s *Solver) Conflicts(pack pkg.Package, lsp pkg.Packages) (bool, error) { +func (s *Solver) Conflicts(pack *types.Package, lsp types.Packages) (bool, error) { p, err := s.DefinitionDatabase.FindPackage(pack) if err != nil { p = pack @@ -273,7 +257,7 @@ func (s *Solver) Conflicts(pack pkg.Package, lsp pkg.Packages) (bool, error) { // ConflictsWith return true if a package is part of the requirement set of a list of package // return false otherwise (and thus it is NOT relevant to the given list) -func (s *Solver) ConflictsWith(pack pkg.Package, lsp pkg.Packages) (bool, error) { +func (s *Solver) ConflictsWith(pack *types.Package, lsp types.Packages) (bool, error) { p, err := s.DefinitionDatabase.FindPackage(pack) if err != nil { p = pack //Relax search, otherwise we cannot compute solutions for packages not in definitions @@ -329,7 +313,7 @@ func (s *Solver) ConflictsWith(pack pkg.Package, lsp pkg.Packages) (bool, error) } -func (s *Solver) ConflictsWithInstalled(p pkg.Package) (bool, error) { +func (s *Solver) ConflictsWithInstalled(p *types.Package) (bool, error) { return s.ConflictsWith(p, s.Installed()) } @@ -339,7 +323,7 @@ func (s *Solver) ConflictsWithInstalled(p pkg.Package) (bool, error) { // It can be compared to the counterpart Uninstall as this method acts like a uninstall --full // it removes all the packages and its deps. taking also in consideration other packages that might have // revdeps -func (s *Solver) UninstallUniverse(toremove pkg.Packages) (pkg.Packages, error) { +func (s *Solver) UninstallUniverse(toremove types.Packages) (types.Packages, error) { if s.noRulesInstalled() { return s.getList(s.InstalledDatabase, toremove) @@ -367,7 +351,7 @@ func (s *Solver) UninstallUniverse(toremove pkg.Packages) (pkg.Packages, error) formulas = append(formulas, bf.And(bf.Not(P), r)) } - markedForRemoval := pkg.Packages{} + markedForRemoval := types.Packages{} model := bf.Solve(bf.And(formulas...)) if model == nil { return nil, errors.New("Failed finding a solution") @@ -390,14 +374,14 @@ func (s *Solver) UninstallUniverse(toremove pkg.Packages) (pkg.Packages, error) // UpgradeUniverse mark packages for removal and returns a solution. It considers // the Universe db as authoritative // See also on the subject: https://arxiv.org/pdf/1007.1021.pdf -func (s *Solver) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAssertions, error) { +func (s *Solver) UpgradeUniverse(dropremoved bool) (types.Packages, types.PackagesAssertions, error) { // we first figure out which aren't up-to-date // which has to be removed // and which needs to be upgraded - notUptodate := pkg.Packages{} - removed := pkg.Packages{} - toUpgrade := pkg.Packages{} - replacements := map[pkg.Package]pkg.Package{} + notUptodate := types.Packages{} + removed := types.Packages{} + toUpgrade := types.Packages{} + replacements := map[*types.Package]*types.Package{} // TODO: this is memory expensive, we need to optimize this universe, err := s.DefinitionDatabase.Copy() @@ -467,10 +451,10 @@ func (s *Solver) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAssert //formulas = append(formulas, r) - markedForRemoval := pkg.Packages{} + markedForRemoval := types.Packages{} if len(formulas) == 0 { - return pkg.Packages{}, PackagesAssertions{}, nil + return types.Packages{}, types.PackagesAssertions{}, nil } model := bf.Solve(bf.And(formulas...)) if model == nil { @@ -493,7 +477,7 @@ func (s *Solver) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAssert return markedForRemoval, assertion, nil } -func inPackage(list []pkg.Package, p pkg.Package) bool { +func inPackage(list []*types.Package, p *types.Package) bool { for _, l := range list { if l.AtomMatches(p) { return true @@ -503,10 +487,10 @@ func inPackage(list []pkg.Package, p pkg.Package) bool { } // Compute upgrade between packages if specified, or all if none is specified -func (s *Solver) computeUpgrade(ppsToUpgrade, ppsToNotUpgrade []pkg.Package) func(defDB pkg.PackageDatabase, installDB pkg.PackageDatabase) (pkg.Packages, pkg.Packages, pkg.PackageDatabase, []pkg.Package) { - return func(defDB pkg.PackageDatabase, installDB pkg.PackageDatabase) (pkg.Packages, pkg.Packages, pkg.PackageDatabase, []pkg.Package) { - toUninstall := pkg.Packages{} - toInstall := pkg.Packages{} +func (s *Solver) computeUpgrade(ppsToUpgrade, ppsToNotUpgrade []*types.Package) func(defDB types.PackageDatabase, installDB types.PackageDatabase) (types.Packages, types.Packages, types.PackageDatabase, []*types.Package) { + return func(defDB types.PackageDatabase, installDB types.PackageDatabase) (types.Packages, types.Packages, types.PackageDatabase, []*types.Package) { + toUninstall := types.Packages{} + toInstall := types.Packages{} // we do this in memory so we take into account of provides, and its faster universe, _ := defDB.Copy() @@ -535,15 +519,25 @@ func (s *Solver) computeUpgrade(ppsToUpgrade, ppsToNotUpgrade []pkg.Package) fun } } -func (s *Solver) upgrade(psToUpgrade, psToNotUpgrade pkg.Packages, fn func(defDB pkg.PackageDatabase, installDB pkg.PackageDatabase) (pkg.Packages, pkg.Packages, pkg.PackageDatabase, []pkg.Package), defDB pkg.PackageDatabase, installDB pkg.PackageDatabase, checkconflicts, full bool) (pkg.Packages, PackagesAssertions, error) { +func assertionToMemDB(assertions types.PackagesAssertions) types.PackageDatabase { + db := pkg.NewInMemoryDatabase(false) + for _, a := range assertions { + if a.Value { + db.CreatePackage(a.Package) + } + } + return db +} + +func (s *Solver) upgrade(psToUpgrade, psToNotUpgrade types.Packages, fn func(defDB types.PackageDatabase, installDB types.PackageDatabase) (types.Packages, types.Packages, types.PackageDatabase, []*types.Package), defDB types.PackageDatabase, installDB types.PackageDatabase, checkconflicts, full bool) (types.Packages, types.PackagesAssertions, error) { toUninstall, toInstall, installedcopy, packsToUpgrade := fn(defDB, installDB) - s2 := NewSolver(Options{Type: SingleCoreSimple}, installedcopy, defDB, pkg.NewInMemoryDatabase(false)) + s2 := NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, installedcopy, defDB, pkg.NewInMemoryDatabase(false)) s2.SetResolver(s.Resolver) if !full { - ass := PackagesAssertions{} + ass := types.PackagesAssertions{} for _, i := range toInstall { - ass = append(ass, PackageAssert{Package: i.(*pkg.DefaultPackage), Value: true}) + ass = append(ass, types.PackageAssert{Package: i, Value: true}) } } // Then try to uninstall the versions in the system, and store that tree @@ -559,23 +553,23 @@ func (s *Solver) upgrade(psToUpgrade, psToNotUpgrade pkg.Packages, fn func(defDB } if len(toInstall) == 0 { - ass := PackagesAssertions{} + ass := types.PackagesAssertions{} for _, i := range installDB.World() { - ass = append(ass, PackageAssert{Package: i.(*pkg.DefaultPackage), Value: true}) + ass = append(ass, types.PackageAssert{Package: i, Value: true}) } return toUninstall, ass, nil } assertions, err := s2.RelaxedInstall(toInstall.Unique()) - wantedSystem := assertions.ToDB() + wantedSystem := assertionToMemDB(assertions) - fn = s.computeUpgrade(pkg.Packages{}, pkg.Packages{}) + fn = s.computeUpgrade(types.Packages{}, types.Packages{}) if len(packsToUpgrade) > 0 { // If we have packages in input, // compute what we are looking to upgrade. // those are assertions minus packsToUpgrade - var selectedPackages []pkg.Package + var selectedPackages []*types.Package for _, p := range assertions { if p.Value && !inPackage(psToUpgrade, p.Package) { @@ -593,25 +587,25 @@ func (s *Solver) upgrade(psToUpgrade, psToNotUpgrade pkg.Packages, fn func(defDB return toUninstall, assertions, err } -func (s *Solver) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAssertions, error) { +func (s *Solver) Upgrade(checkconflicts, full bool) (types.Packages, types.PackagesAssertions, error) { installedcopy := pkg.NewInMemoryDatabase(false) err := s.InstalledDatabase.Clone(installedcopy) if err != nil { return nil, nil, err } - return s.upgrade(pkg.Packages{}, pkg.Packages{}, s.computeUpgrade(pkg.Packages{}, pkg.Packages{}), s.DefinitionDatabase, installedcopy, checkconflicts, full) + return s.upgrade(types.Packages{}, types.Packages{}, s.computeUpgrade(types.Packages{}, types.Packages{}), s.DefinitionDatabase, installedcopy, checkconflicts, full) } // Uninstall takes a candidate package and return a list of packages that would be removed // in order to purge the candidate. Returns error if unsat. -func (s *Solver) Uninstall(checkconflicts, full bool, packs ...pkg.Package) (pkg.Packages, error) { +func (s *Solver) Uninstall(checkconflicts, full bool, packs ...*types.Package) (types.Packages, error) { if len(packs) == 0 { - return pkg.Packages{}, nil + return types.Packages{}, nil } - var res pkg.Packages + var res types.Packages - toRemove := pkg.Packages{} + toRemove := types.Packages{} for _, c := range packs { candidate, err := s.InstalledDatabase.FindPackage(c) @@ -633,7 +627,7 @@ func (s *Solver) Uninstall(checkconflicts, full bool, packs ...pkg.Package) (pkg } // Build a fake "Installed" - Candidate and its requires tree - var InstalledMinusCandidate pkg.Packages + var InstalledMinusCandidate types.Packages // We are asked to not perform a full uninstall (checking all the possible requires that could // be removed). Let's only check if we can remove the selected package @@ -666,7 +660,7 @@ func (s *Solver) Uninstall(checkconflicts, full bool, packs ...pkg.Package) (pkg } } - s2 := NewSolver(Options{Type: SingleCoreSimple}, pkg.NewInMemoryDatabase(false), s.InstalledDatabase, pkg.NewInMemoryDatabase(false)) + s2 := NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, pkg.NewInMemoryDatabase(false), s.InstalledDatabase, pkg.NewInMemoryDatabase(false)) s2.SetResolver(s.Resolver) // Get the requirements to install the candidate @@ -756,7 +750,7 @@ func (s *Solver) solve(f bf.Formula) (map[string]bool, bf.Formula, error) { } // Solve builds the formula given the current state and returns package assertions -func (s *Solver) Solve() (PackagesAssertions, error) { +func (s *Solver) Solve() (types.PackagesAssertions, error) { var model map[string]bool var err error @@ -780,7 +774,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) RelaxedInstall(c pkg.Packages) (PackagesAssertions, error) { +func (s *Solver) RelaxedInstall(c types.Packages) (types.PackagesAssertions, error) { coll, err := s.getList(s.DefinitionDatabase, c) if err != nil { @@ -790,13 +784,13 @@ func (s *Solver) RelaxedInstall(c pkg.Packages) (PackagesAssertions, error) { s.Wanted = coll if s.noRulesWorld() { - var ass PackagesAssertions + var ass types.PackagesAssertions for _, p := range s.Installed() { - ass = append(ass, PackageAssert{Package: p.(*pkg.DefaultPackage), Value: true}) + ass = append(ass, types.PackageAssert{Package: p, Value: true}) } for _, p := range s.Wanted { - ass = append(ass, PackageAssert{Package: p.(*pkg.DefaultPackage), Value: true}) + ass = append(ass, types.PackageAssert{Package: p, Value: true}) } return ass, nil } @@ -811,7 +805,7 @@ func (s *Solver) RelaxedInstall(c pkg.Packages) (PackagesAssertions, error) { // 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) { +func (s *Solver) Install(c types.Packages) (types.PackagesAssertions, error) { assertions, err := s.RelaxedInstall(c) if err != nil { return nil, err @@ -819,8 +813,8 @@ func (s *Solver) Install(c pkg.Packages) (PackagesAssertions, error) { systemAfterInstall := pkg.NewInMemoryDatabase(false) - toUpgrade := pkg.Packages{} - toNotUpgrade := pkg.Packages{} + toUpgrade := types.Packages{} + toNotUpgrade := types.Packages{} for _, p := range c { if p.GetVersion() == ">=0" || p.GetVersion() == ">0" { toUpgrade = append(toUpgrade, p) diff --git a/pkg/solver/solver_test.go b/pkg/solver/solver_test.go index bb7470ac..6d741d09 100644 --- a/pkg/solver/solver_test.go +++ b/pkg/solver/solver_test.go @@ -16,7 +16,8 @@ package solver_test import ( - pkg "github.com/mudler/luet/pkg/package" + types "github.com/mudler/luet/pkg/api/core/types" + pkg "github.com/mudler/luet/pkg/database" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -28,13 +29,13 @@ var _ = Describe("Solver", func() { db := pkg.NewInMemoryDatabase(false) dbInstalled := pkg.NewInMemoryDatabase(false) dbDefinitions := pkg.NewInMemoryDatabase(false) - s := NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s := NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) BeforeEach(func() { db = pkg.NewInMemoryDatabase(false) dbInstalled = pkg.NewInMemoryDatabase(false) dbDefinitions = pkg.NewInMemoryDatabase(false) - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) }) Context("Select of best available package", func() { @@ -42,132 +43,132 @@ var _ = Describe("Solver", 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{}) + B1 := types.NewPackage("B", "1.1", []*types.Package{}, []*types.Package{}) + B2 := types.NewPackage("B", "1.2", []*types.Package{}, []*types.Package{}) + B3 := types.NewPackage("B", "1.3", []*types.Package{}, []*types.Package{}) + B4 := types.NewPackage("B", "1.4", []*types.Package{}, []*types.Package{}) - 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{}) + A1 := types.NewPackage("A", "1.1", []*types.Package{ + types.NewPackage("B", ">=0", []*types.Package{}, []*types.Package{}), + }, []*types.Package{}) + A2 := types.NewPackage("A", "1.2", []*types.Package{ + types.NewPackage("B", ">=0", []*types.Package{}, []*types.Package{}), + }, []*types.Package{}) - D := pkg.NewPackage("D", "1.0", []*pkg.DefaultPackage{ - pkg.NewPackage("A", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}), - }, []*pkg.DefaultPackage{}) + D := types.NewPackage("D", "1.0", []*types.Package{ + types.NewPackage("A", ">=0", []*types.Package{}, []*types.Package{}), + }, []*types.Package{}) - C := pkg.NewPackage("C", "1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "1", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A1, A2, B1, B2, B3, B4, C, D} { + for _, p := range []*types.Package{A1, A2, B1, B2, B3, B4, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.(*Solver).Install([]pkg.Package{D}) + solution, err := s.(*Solver).Install([]*types.Package{D}) 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(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A2, Value: true})) + Expect(solution).To(ContainElement(types.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})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A1, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B1, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B2, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B3, Value: false})) - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err = s.(*Solver).Install([]pkg.Package{D, B2}) + solution, err = s.(*Solver).Install([]*types.Package{D, B2}) 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(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A2, Value: true})) + Expect(solution).To(ContainElement(types.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})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A1, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B1, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B4, Value: false})) + Expect(solution).To(ContainElement(types.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{}) + B1 := types.NewPackage("B", "1.1", []*types.Package{}, []*types.Package{}) + B2 := types.NewPackage("B", "1.2", []*types.Package{}, []*types.Package{}) + B3 := types.NewPackage("B", "1.3", []*types.Package{}, []*types.Package{}) + B4 := types.NewPackage("B", "1.4", []*types.Package{}, []*types.Package{}) - 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{}) + A1 := types.NewPackage("A", "1.1", []*types.Package{ + types.NewPackage("B", ">=0", []*types.Package{}, []*types.Package{}), + }, []*types.Package{}) + A2 := types.NewPackage("A", "1.2", []*types.Package{ + types.NewPackage("B", ">=0", []*types.Package{}, []*types.Package{}), + }, []*types.Package{}) - D := pkg.NewPackage("D", "1.0", []*pkg.DefaultPackage{ - pkg.NewPackage("A", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}), - }, []*pkg.DefaultPackage{}) + D := types.NewPackage("D", "1.0", []*types.Package{ + types.NewPackage("A", ">=0", []*types.Package{}, []*types.Package{}), + }, []*types.Package{}) - C := pkg.NewPackage("C", "1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "1", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A1, A2, B1, B2, B3, B4, C, D} { + for _, p := range []*types.Package{A1, A2, B1, B2, B3, B4, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.(*Solver).Install([]pkg.Package{pkg.NewPackage("D", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})}) + solution, err := s.(*Solver).Install([]*types.Package{types.NewPackage("D", ">=0", []*types.Package{}, []*types.Package{})}) 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(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A2, Value: true})) + Expect(solution).To(ContainElement(types.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})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A1, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B1, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B2, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B3, Value: false})) - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err = s.(*Solver).Install([]pkg.Package{pkg.NewPackage("D", ">=0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}), B2}) + solution, err = s.(*Solver).Install([]*types.Package{types.NewPackage("D", ">=0", []*types.Package{}, []*types.Package{}), B2}) 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(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A2, Value: true})) + Expect(solution).To(ContainElement(types.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})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A1, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B1, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B4, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B3, Value: false})) }) @@ -177,322 +178,322 @@ var _ = Describe("Solver", func() { Context("Simple set", func() { It("Solves correctly if the selected package has no requirements or conflicts and we have nothing installed yet", func() { - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C} { + for _, p := range []*types.Package{A, B, C} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A}) + solution, err := s.Install([]*types.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("Solves correctly if the selected package has no requirements or conflicts and we have installed one package", func() { - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C} { + for _, p := range []*types.Package{A, B, C} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{B}) + solution, err := s.Install([]*types.Package{B}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(2)) }) It("Solves correctly if the selected package to install has no requirement or conflicts, but in the world there is one with a requirement", func() { - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{B}, []*types.Package{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E} { + for _, p := range []*types.Package{A, B, C, D, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{E, C} { + for _, p := range []*types.Package{E, C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A}) + solution, err := s.Install([]*types.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: E, Value: true})) - // Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: false})) - //Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: E, Value: true})) + // Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: false})) + //Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: false})) Expect(len(solution)).To(Equal(5)) }) It("Solves correctly if the selected package to install has requirements", func() { - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{D}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A}) + solution, err := s.Install([]*types.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) Expect(len(solution)).To(Equal(3)) }) It("Solves correctly", func() { - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C} { + for _, p := range []*types.Package{A, B, C} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A}) + solution, err := s.Install([]*types.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(3)) }) It("Solves correctly more complex ones", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + solution, err := s.Install([]*types.Package{A}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(4)) Expect(err).ToNot(HaveOccurred()) }) It("Solves correctly more complex ones", func() { - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E} { + for _, p := range []*types.Package{A, B, C, D, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + solution, err := s.Install([]*types.Package{A}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) Expect(len(solution)).To(Equal(3)) Expect(err).ToNot(HaveOccurred()) }) It("Solves deps with expansion", func() { - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "B", Version: ">1.0"}}, []*pkg.DefaultPackage{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "1.1", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{&types.Package{Name: "B", Version: ">1.0"}}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E} { + for _, p := range []*types.Package{A, B, C, D, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + solution, err := s.Install([]*types.Package{A}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) Expect(len(solution)).To(Equal(3)) Expect(err).ToNot(HaveOccurred()) }) It("Solves deps with more expansion", func() { - C := pkg.NewPackage("c", "", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + C := types.NewPackage("c", "", []*types.Package{&types.Package{Name: "a", Version: ">=1.0", Category: "test"}}, []*types.Package{}) C.SetCategory("test") - B := pkg.NewPackage("b", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B := types.NewPackage("b", "1.0", []*types.Package{}, []*types.Package{}) B.SetCategory("test") - A := pkg.NewPackage("a", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + A := types.NewPackage("a", "1.1", []*types.Package{&types.Package{Name: "b", Version: "1.0", Category: "test"}}, []*types.Package{}) A.SetCategory("test") - for _, p := range []pkg.Package{A, B, C} { + for _, p := range []*types.Package{A, B, C} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{C}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + solution, err := s.Install([]*types.Package{C}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(3)) Expect(err).ToNot(HaveOccurred()) }) It("Solves deps with more expansion", func() { - C := pkg.NewPackage("c", "1.5", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + C := types.NewPackage("c", "1.5", []*types.Package{&types.Package{Name: "a", Version: ">=1.0", Category: "test"}}, []*types.Package{}) C.SetCategory("test") - B := pkg.NewPackage("b", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B := types.NewPackage("b", "1.0", []*types.Package{}, []*types.Package{}) B.SetCategory("test") - A := pkg.NewPackage("a", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + A := types.NewPackage("a", "1.1", []*types.Package{&types.Package{Name: "b", Version: "1.0", Category: "test"}}, []*types.Package{}) A.SetCategory("test") - for _, p := range []pkg.Package{A, B, C} { + for _, p := range []*types.Package{A, B, C} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{&pkg.DefaultPackage{Name: "c", Version: ">1.0", Category: "test"}}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + solution, err := s.Install([]*types.Package{&types.Package{Name: "c", Version: ">1.0", Category: "test"}}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(3)) Expect(err).ToNot(HaveOccurred()) }) It("Solves deps with more expansion", func() { - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "1.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0"}}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "B", Version: ">=1.0"}}, []*pkg.DefaultPackage{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "1.4", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "1.1", []*types.Package{&types.Package{Name: "D", Version: ">=1.0"}}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{&types.Package{Name: "B", Version: ">=1.0"}}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E} { + for _, p := range []*types.Package{A, B, C, D, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) + solution, err := s.Install([]*types.Package{A}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) Expect(len(solution)).To(Equal(3)) Expect(err).ToNot(HaveOccurred()) }) It("Selects one version", func() { - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D2 := pkg.NewPackage("D", "1.9", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "1.8", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D1 := pkg.NewPackage("D", "1.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: "1.4"}}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0"}}, []*pkg.DefaultPackage{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D2 := types.NewPackage("D", "1.9", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "1.8", []*types.Package{}, []*types.Package{}) + D1 := types.NewPackage("D", "1.4", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "1.1", []*types.Package{&types.Package{Name: "D", Version: "1.4"}}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{&types.Package{Name: "D", Version: ">=1.0"}}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, D1, D2, E} { + for _, p := range []*types.Package{A, B, C, D, D1, D2, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A, B}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D2, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: false})) - Expect(solution).To(ContainElement(PackageAssert{Package: D2, Value: false})) + solution, err := s.Install([]*types.Package{A, B}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D1, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D2, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D2, Value: false})) Expect(len(solution)).To(Equal(5)) Expect(err).ToNot(HaveOccurred()) @@ -500,44 +501,44 @@ var _ = Describe("Solver", func() { It("Install only package requires", func() { - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{ + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) + C := types.NewPackage("C", "1.1", []*types.Package{&types.Package{ Name: "A", Version: ">=1.0", - }}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "1.9", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{ - &pkg.DefaultPackage{ + }}, []*types.Package{}) + D := types.NewPackage("D", "1.9", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "1.1", []*types.Package{ + &types.Package{ Name: "D", Version: ">=0", }, - }, []*pkg.DefaultPackage{}) + }, []*types.Package{}) - A := pkg.NewPackage("A", "1.2", []*pkg.DefaultPackage{ - &pkg.DefaultPackage{ + A := types.NewPackage("A", "1.2", []*types.Package{ + &types.Package{ Name: "D", Version: ">=1.0", }, - }, []*pkg.DefaultPackage{}) + }, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E} { + for _, p := range []*types.Package{A, B, C, D, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{C}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).ToNot(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).ToNot(ContainElement(PackageAssert{Package: D, Value: false})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true})) + solution, err := s.Install([]*types.Package{C}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D, Value: false})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: E, Value: true})) Expect(len(solution)).To(Equal(4)) Expect(err).ToNot(HaveOccurred()) @@ -545,40 +546,40 @@ var _ = Describe("Solver", func() { It("Selects best version", func() { - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) E.SetCategory("test") - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) C.SetCategory("test") - D2 := pkg.NewPackage("D", "1.9", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + D2 := types.NewPackage("D", "1.9", []*types.Package{}, []*types.Package{}) D2.SetCategory("test") - D := pkg.NewPackage("D", "1.8", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + D := types.NewPackage("D", "1.8", []*types.Package{}, []*types.Package{}) D.SetCategory("test") - D1 := pkg.NewPackage("D", "1.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + D1 := types.NewPackage("D", "1.4", []*types.Package{}, []*types.Package{}) D1.SetCategory("test") - B := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "1.1", []*types.Package{&types.Package{Name: "D", Version: ">=1.0", Category: "test"}}, []*types.Package{}) B.SetCategory("test") - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + A := types.NewPackage("A", "", []*types.Package{&types.Package{Name: "D", Version: ">=1.0", Category: "test"}}, []*types.Package{}) A.SetCategory("test") - for _, p := range []pkg.Package{A, B, C, D, D1, D2, E} { + for _, p := range []*types.Package{A, B, C, D, D1, D2, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A, B}) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D1, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D2, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: false})) - Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false})) + solution, err := s.Install([]*types.Package{A, B}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D1, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D2, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D1, Value: false})) Expect(len(solution)).To(Equal(5)) Expect(err).ToNot(HaveOccurred()) @@ -586,127 +587,127 @@ var _ = Describe("Solver", func() { It("Support provides", func() { - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) E.SetCategory("test") - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) C.SetCategory("test") - D2 := pkg.NewPackage("D", "1.9", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + D2 := types.NewPackage("D", "1.9", []*types.Package{}, []*types.Package{}) D2.SetCategory("test") - D := pkg.NewPackage("D", "1.8", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + D := types.NewPackage("D", "1.8", []*types.Package{}, []*types.Package{}) D.SetCategory("test") - D1 := pkg.NewPackage("D", "1.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + D1 := types.NewPackage("D", "1.4", []*types.Package{}, []*types.Package{}) D1.SetCategory("test") - B := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "1.1", []*types.Package{&types.Package{Name: "D", Version: ">=1.0", Category: "test"}}, []*types.Package{}) B.SetCategory("test") - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + A := types.NewPackage("A", "", []*types.Package{&types.Package{Name: "D", Version: ">=1.0", Category: "test"}}, []*types.Package{}) A.SetCategory("test") - D2.SetProvides([]*pkg.DefaultPackage{{Name: "E", Category: "test"}}) - A2 := pkg.NewPackage("A", "1.3", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "E", Version: "", Category: "test"}}, []*pkg.DefaultPackage{}) + D2.SetProvides([]*types.Package{{Name: "E", Category: "test"}}) + A2 := types.NewPackage("A", "1.3", []*types.Package{&types.Package{Name: "E", Version: "", Category: "test"}}, []*types.Package{}) A2.SetCategory("test") - for _, p := range []pkg.Package{A, B, C, D, D1, D2, A2, E} { + for _, p := range []*types.Package{A, B, C, D, D1, D2, A2, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A2, B}) - Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D1, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D2, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: false})) - Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true})) + solution, err := s.Install([]*types.Package{A2, B}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A2, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D1, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D2, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D1, Value: false})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: E, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) }) It("Support provides with versions", func() { - E := pkg.NewPackage("E", "1.3", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + E := types.NewPackage("E", "1.3", []*types.Package{}, []*types.Package{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D2 := pkg.NewPackage("D", "1.9", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "1.8", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D1 := pkg.NewPackage("D", "1.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0"}}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0"}}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D2 := types.NewPackage("D", "1.9", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "1.8", []*types.Package{}, []*types.Package{}) + D1 := types.NewPackage("D", "1.4", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "1.1", []*types.Package{&types.Package{Name: "D", Version: ">=1.0"}}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{&types.Package{Name: "D", Version: ">=1.0"}}, []*types.Package{}) - D2.SetProvides([]*pkg.DefaultPackage{{Name: "E", Version: "1.3"}}) - A2 := pkg.NewPackage("A", "1.3", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "E", Version: ">=1.0"}}, []*pkg.DefaultPackage{}) + D2.SetProvides([]*types.Package{{Name: "E", Version: "1.3"}}) + A2 := types.NewPackage("A", "1.3", []*types.Package{&types.Package{Name: "E", Version: ">=1.0"}}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, D1, D2, A2, E} { + for _, p := range []*types.Package{A, B, C, D, D1, D2, A2, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A2}) - Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D1, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: A, Value: true})) + solution, err := s.Install([]*types.Package{A2}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A2, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D1, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D2, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: false})) - Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D2, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D1, Value: false})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: E, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) }) It("Support provides with selectors", func() { - E := pkg.NewPackage("E", "1.3", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + E := types.NewPackage("E", "1.3", []*types.Package{}, []*types.Package{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D2 := pkg.NewPackage("D", "1.9", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "1.8", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D1 := pkg.NewPackage("D", "1.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0"}}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "D", Version: ">=1.0"}}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D2 := types.NewPackage("D", "1.9", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "1.8", []*types.Package{}, []*types.Package{}) + D1 := types.NewPackage("D", "1.4", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "1.1", []*types.Package{&types.Package{Name: "D", Version: ">=1.0"}}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{&types.Package{Name: "D", Version: ">=1.0"}}, []*types.Package{}) - D2.SetProvides([]*pkg.DefaultPackage{{Name: "E", Version: ">=1.3"}}) - A2 := pkg.NewPackage("A", "1.3", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "E", Version: ">=1.0"}}, []*pkg.DefaultPackage{}) + D2.SetProvides([]*types.Package{{Name: "E", Version: ">=1.3"}}) + A2 := types.NewPackage("A", "1.3", []*types.Package{&types.Package{Name: "E", Version: ">=1.0"}}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, D1, D2, A2, E} { + for _, p := range []*types.Package{A, B, C, D, D1, D2, A2, E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{} { + for _, p := range []*types.Package{} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Install([]pkg.Package{A2}) - Expect(solution).To(ContainElement(PackageAssert{Package: A2, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D1, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: A, Value: true})) + solution, err := s.Install([]*types.Package{A2}) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A2, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D1, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D2, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: false})) - Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D2, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D1, Value: false})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: E, Value: true})) Expect(len(solution)).To(Equal(6)) Expect(err).ToNot(HaveOccurred()) @@ -715,69 +716,69 @@ var _ = Describe("Solver", func() { Context("Uninstall", func() { It("Uninstalls simple package correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) solution, err := s.Uninstall(true, true, A) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A)) - // Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + // Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("Uninstalls simple package expanded correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "1.2", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "1.2", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.Uninstall(true, true, &pkg.DefaultPackage{Name: "A", Version: ">1.0"}) + solution, err := s.Uninstall(true, true, &types.Package{Name: "A", Version: ">1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A)) - // Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + // Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("Uninstalls simple packages not in world correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{B, C, D} { + for _, p := range []*types.Package{B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -786,22 +787,22 @@ var _ = Describe("Solver", func() { Expect(solution).To(ContainElement(A)) - // Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + // Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("Uninstalls complex packages not in world correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{B, C, D} { + for _, p := range []*types.Package{B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -815,17 +816,17 @@ var _ = Describe("Solver", func() { }) It("Uninstalls complex packages correctly, even if shared deps are required by system packages", func() { - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -839,17 +840,17 @@ var _ = Describe("Solver", func() { }) It("Uninstalls complex packages in world correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{C}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{C}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, C, D} { + for _, p := range []*types.Package{A, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -864,18 +865,18 @@ var _ = Describe("Solver", func() { }) It("Uninstalls complex package correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) // C // installed - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -892,23 +893,23 @@ var _ = Describe("Solver", func() { }) It("Fails to uninstall if a package is required", func() { - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - Z := pkg.NewPackage("Z", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{Z, B}, []*pkg.DefaultPackage{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{D}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{B}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) + Z := types.NewPackage("Z", "", []*types.Package{A}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{Z, B}, []*types.Package{}) Z.SetVersion("1.4101.dvw.dqc.") B.SetVersion("1.4101qe.eq.ff..dvw.dqc.") C.SetVersion("1.aaaa.eq.ff..dvw.dqc.") - for _, p := range []pkg.Package{A, B, C, D, Z, F} { + for _, p := range []*types.Package{A, B, C, D, Z, F} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D, Z, F} { + for _, p := range []*types.Package{A, B, C, D, Z, F} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -920,98 +921,98 @@ var _ = Describe("Solver", func() { It("UninstallUniverse simple package correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.UninstallUniverse(pkg.Packages{A}) + solution, err := s.UninstallUniverse(types.Packages{A}) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A)) - // Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + // Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("UninstallUniverse simple package expanded correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "1.2", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "1.2", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db) + s = NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, dbInstalled, dbDefinitions, db) - solution, err := s.UninstallUniverse(pkg.Packages{ - &pkg.DefaultPackage{Name: "A", Version: ">1.0"}}) + solution, err := s.UninstallUniverse(types.Packages{ + &types.Package{Name: "A", Version: ">1.0"}}) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A)) - // Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + // Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("UninstallUniverse simple packages not in world correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{B, C, D} { + for _, p := range []*types.Package{B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.UninstallUniverse(pkg.Packages{A}) + solution, err := s.UninstallUniverse(types.Packages{A}) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A)) - // Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) + // Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("UninstallUniverse complex packages not in world correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{B, C, D} { + for _, p := range []*types.Package{B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.UninstallUniverse(pkg.Packages{A}) + solution, err := s.UninstallUniverse(types.Packages{A}) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A)) @@ -1023,21 +1024,21 @@ var _ = Describe("Solver", func() { It("UninstallUniverse complex packages correctly, even if shared deps are required by system packages", func() { // Here we diff a lot from standard Uninstall: // all the packages that has reverse deps will be removed (aka --full) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) + C := types.NewPackage("C", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.UninstallUniverse(pkg.Packages{A}) + solution, err := s.UninstallUniverse(types.Packages{A}) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A)) @@ -1048,22 +1049,22 @@ var _ = Describe("Solver", func() { }) It("UninstallUniverse complex packages in world correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{C}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{C}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, C, D} { + for _, p := range []*types.Package{A, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.UninstallUniverse(pkg.Packages{A}) + solution, err := s.UninstallUniverse(types.Packages{A}) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A)) @@ -1073,23 +1074,23 @@ var _ = Describe("Solver", func() { }) It("UninstallUniverse complex package correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) // C // installed - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.UninstallUniverse(pkg.Packages{A}) + solution, err := s.UninstallUniverse(types.Packages{A}) Expect(err).ToNot(HaveOccurred()) Expect(solution).To(ContainElement(A)) @@ -1103,18 +1104,18 @@ var _ = Describe("Solver", func() { }) It("Find conflicts", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{A}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1127,18 +1128,18 @@ var _ = Describe("Solver", func() { It("Find nested conflicts", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{D}, []*types.Package{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{A}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1150,18 +1151,18 @@ var _ = Describe("Solver", func() { It("Doesn't find nested conflicts", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{D}, []*types.Package{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{A}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1173,18 +1174,18 @@ var _ = Describe("Solver", func() { It("Doesn't find conflicts", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1195,18 +1196,18 @@ var _ = Describe("Solver", func() { It("Find conflicts using revdeps", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{A}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1219,18 +1220,18 @@ var _ = Describe("Solver", func() { It("Find nested conflicts with revdeps", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{D}, []*types.Package{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{A}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1242,18 +1243,18 @@ var _ = Describe("Solver", func() { It("Doesn't find nested conflicts with revdeps", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{D}, []*types.Package{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{A}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{A}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1265,18 +1266,18 @@ var _ = Describe("Solver", func() { It("Doesn't find conflicts with revdeps", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{}, []*types.Package{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, D} { + for _, p := range []*types.Package{A, B, C, D} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1290,22 +1291,22 @@ var _ = Describe("Solver", func() { Context("Conflict set", func() { It("is unsolvable - as we something we ask to install conflict with system stuff", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - // D := pkg.NewPackage("D", "", []pkg.Package{}, []pkg.Package{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{C}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + // D := types.NewPackage("D", "", []*types.Package{}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{}, []*types.Package{C}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C} { + for _, p := range []*types.Package{A, B, C} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{A}) + solution, err := s.Install([]*types.Package{A}) Expect(len(solution)).To(Equal(0)) Expect(err).To(HaveOccurred()) }) @@ -1314,50 +1315,50 @@ var _ = Describe("Solver", func() { Context("Complex data sets", func() { It("Solves them correctly", func() { - C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - E := pkg.NewPackage("E", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - F := pkg.NewPackage("F", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - G := pkg.NewPackage("G", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - H := pkg.NewPackage("H", "", []*pkg.DefaultPackage{G}, []*pkg.DefaultPackage{}) - D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{H}, []*pkg.DefaultPackage{}) - B := pkg.NewPackage("B", "", []*pkg.DefaultPackage{D}, []*pkg.DefaultPackage{}) - A := pkg.NewPackage("A", "", []*pkg.DefaultPackage{B}, []*pkg.DefaultPackage{}) + C := types.NewPackage("C", "", []*types.Package{}, []*types.Package{}) + E := types.NewPackage("E", "", []*types.Package{}, []*types.Package{}) + F := types.NewPackage("F", "", []*types.Package{}, []*types.Package{}) + G := types.NewPackage("G", "", []*types.Package{}, []*types.Package{}) + H := types.NewPackage("H", "", []*types.Package{G}, []*types.Package{}) + D := types.NewPackage("D", "", []*types.Package{H}, []*types.Package{}) + B := types.NewPackage("B", "", []*types.Package{D}, []*types.Package{}) + A := types.NewPackage("A", "", []*types.Package{B}, []*types.Package{}) - for _, p := range []pkg.Package{A, B, C, D, E, F, G} { + for _, p := range []*types.Package{A, B, C, D, E, F, G} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{C} { + for _, p := range []*types.Package{C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - solution, err := s.Install([]pkg.Package{A}) + solution, err := s.Install([]*types.Package{A}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: D, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: H, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: G, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: H, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: G, Value: true})) Expect(len(solution)).To(Equal(6)) }) }) Context("Selection", func() { - a := pkg.NewPackage("A", ">=2.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - a1 := pkg.NewPackage("A", "2.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - a11 := pkg.NewPackage("A", "2.1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - a01 := pkg.NewPackage("A", "2.2", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - a02 := pkg.NewPackage("A", "2.3", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - a03 := pkg.NewPackage("A", "2.3.4", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - old := pkg.NewPackage("A", "1.3.1", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + a := types.NewPackage("A", ">=2.0", []*types.Package{}, []*types.Package{}) + a1 := types.NewPackage("A", "2.0", []*types.Package{}, []*types.Package{}) + a11 := types.NewPackage("A", "2.1", []*types.Package{}, []*types.Package{}) + a01 := types.NewPackage("A", "2.2", []*types.Package{}, []*types.Package{}) + a02 := types.NewPackage("A", "2.3", []*types.Package{}, []*types.Package{}) + a03 := types.NewPackage("A", "2.3.4", []*types.Package{}, []*types.Package{}) + old := types.NewPackage("A", "1.3.1", []*types.Package{}, []*types.Package{}) It("Expands correctly", func() { definitions := pkg.NewInMemoryDatabase(false) - for _, p := range []pkg.Package{a1, a11, a01, a02, a03, old} { + for _, p := range []*types.Package{a1, a11, a01, a02, a03, old} { _, err := definitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1375,35 +1376,35 @@ var _ = Describe("Solver", func() { }) }) Context("Upgrades", func() { - E := pkg.NewPackage("e", "1.5", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + E := types.NewPackage("e", "1.5", []*types.Package{}, []*types.Package{}) E.SetCategory("test") - C := pkg.NewPackage("c", "1.5", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + C := types.NewPackage("c", "1.5", []*types.Package{&types.Package{Name: "a", Version: ">=1.0", Category: "test"}}, []*types.Package{}) C.SetCategory("test") - B := pkg.NewPackage("b", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B := types.NewPackage("b", "1.0", []*types.Package{}, []*types.Package{}) B.SetCategory("test") - A := pkg.NewPackage("a", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + A := types.NewPackage("a", "1.1", []*types.Package{&types.Package{Name: "b", Version: "1.0", Category: "test"}}, []*types.Package{}) A.SetCategory("test") - A1 := pkg.NewPackage("a", "1.2", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + A1 := types.NewPackage("a", "1.2", []*types.Package{&types.Package{Name: "b", Version: "1.0", Category: "test"}}, []*types.Package{}) A1.SetCategory("test") BeforeEach(func() { - C = pkg.NewPackage("c", "1.5", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + C = types.NewPackage("c", "1.5", []*types.Package{&types.Package{Name: "a", Version: ">=1.0", Category: "test"}}, []*types.Package{}) C.SetCategory("test") - B = pkg.NewPackage("b", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + B = types.NewPackage("b", "1.0", []*types.Package{}, []*types.Package{}) B.SetCategory("test") - A = pkg.NewPackage("a", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + A = types.NewPackage("a", "1.1", []*types.Package{&types.Package{Name: "b", Version: "1.0", Category: "test"}}, []*types.Package{}) A.SetCategory("test") - A1 = pkg.NewPackage("a", "1.2", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{}) + A1 = types.NewPackage("a", "1.2", []*types.Package{&types.Package{Name: "b", Version: "1.0", Category: "test"}}, []*types.Package{}) A1.SetCategory("test") }) It("upgrades correctly", func() { - for _, p := range []pkg.Package{A1, B, C} { + for _, p := range []*types.Package{A1, B, C} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B} { + for _, p := range []*types.Package{A, B} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1414,24 +1415,24 @@ var _ = Describe("Solver", func() { Expect(uninstall[0].GetName()).To(Equal("a")) Expect(uninstall[0].GetVersion()).To(Equal("1.1")) - Expect(solution).To(ContainElement(PackageAssert{Package: A1, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A1, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: false})) Expect(len(solution)).To(Equal(3)) }) It("upgrades correctly with provides", func() { - B.SetProvides([]*pkg.DefaultPackage{ - &pkg.DefaultPackage{Name: "a", Version: ">=0", Category: "test"}, - &pkg.DefaultPackage{Name: "c", Version: ">=0", Category: "test"}, + B.SetProvides([]*types.Package{ + &types.Package{Name: "a", Version: ">=0", Category: "test"}, + &types.Package{Name: "c", Version: ">=0", Category: "test"}, }) - for _, p := range []pkg.Package{B} { + for _, p := range []*types.Package{B} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, C} { + for _, p := range []*types.Package{A, C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1443,22 +1444,22 @@ var _ = Describe("Solver", func() { Expect(uninstall).To(ContainElement(C)) Expect(uninstall).To(ContainElement(A)) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) Expect(len(solution)).To(Equal(1)) }) PIt("upgrades correctly with provides, also if definitiondb contains both a provide, and the package to be provided", func() { - B.SetProvides([]*pkg.DefaultPackage{ - &pkg.DefaultPackage{Name: "a", Version: ">=0", Category: "test"}, - &pkg.DefaultPackage{Name: "c", Version: ">=0", Category: "test"}, + B.SetProvides([]*types.Package{ + &types.Package{Name: "a", Version: ">=0", Category: "test"}, + &types.Package{Name: "c", Version: ">=0", Category: "test"}, }) - for _, p := range []pkg.Package{A1, B} { + for _, p := range []*types.Package{A1, B} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, C} { + for _, p := range []*types.Package{A, C} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1470,17 +1471,17 @@ var _ = Describe("Solver", func() { Expect(uninstall).To(ContainElement(C)) Expect(uninstall).To(ContainElement(A)) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) Expect(len(solution)).To(Equal(1)) }) It("UpgradeUniverse upgrades correctly", func() { - for _, p := range []pkg.Package{A1, B, C} { + for _, p := range []*types.Package{A1, B, C} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B} { + for _, p := range []*types.Package{A, B} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1491,23 +1492,23 @@ var _ = Describe("Solver", func() { Expect(uninstall[0].GetName()).To(Equal("a")) Expect(uninstall[0].GetVersion()).To(Equal("1.1")) - Expect(solution).To(ContainElement(PackageAssert{Package: A1, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: true})) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A1, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: false})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: C, Value: true})) - Expect(solution).ToNot(ContainElement(PackageAssert{Package: A, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: C, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: A, Value: true})) Expect(len(solution)).To(Equal(3)) }) It("Suggests to remove untracked packages", func() { - for _, p := range []pkg.Package{E} { + for _, p := range []*types.Package{E} { _, err := dbDefinitions.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } - for _, p := range []pkg.Package{A, B, C, E} { + for _, p := range []*types.Package{A, B, C, E} { _, err := dbInstalled.CreatePackage(p) Expect(err).ToNot(HaveOccurred()) } @@ -1519,9 +1520,9 @@ var _ = Describe("Solver", func() { Expect(uninstall).To(ContainElement(A)) Expect(uninstall).To(ContainElement(C)) - Expect(solution).To(ContainElement(PackageAssert{Package: C, Value: false})) - Expect(solution).To(ContainElement(PackageAssert{Package: B, Value: false})) - Expect(solution).To(ContainElement(PackageAssert{Package: A, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: C, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: B, Value: false})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: A, Value: false})) Expect(len(solution)).To(Equal(3)) }) diff --git a/pkg/spectooling/definition.go b/pkg/spectooling/definition.go index b0fa7ee2..4a9ce2e6 100644 --- a/pkg/spectooling/definition.go +++ b/pkg/spectooling/definition.go @@ -17,19 +17,19 @@ package spectooling import ( - pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" "gopkg.in/yaml.v2" ) -type DefaultPackageSanitized struct { - Name string `json:"name" yaml:"name"` - Version string `json:"version" yaml:"version"` - Category string `json:"category" yaml:"category"` - UseFlags []string `json:"use_flags,omitempty" yaml:"use_flags,omitempty"` - PackageRequires []*DefaultPackageSanitized `json:"requires,omitempty" yaml:"requires,omitempty"` - PackageConflicts []*DefaultPackageSanitized `json:"conflicts,omitempty" yaml:"conflicts,omitempty"` - Provides []*DefaultPackageSanitized `json:"provides,omitempty" yaml:"provides,omitempty"` +type PackageSanitized struct { + Name string `json:"name" yaml:"name"` + Version string `json:"version" yaml:"version"` + Category string `json:"category" yaml:"category"` + UseFlags []string `json:"use_flags,omitempty" yaml:"use_flags,omitempty"` + PackageRequires []*PackageSanitized `json:"requires,omitempty" yaml:"requires,omitempty"` + PackageConflicts []*PackageSanitized `json:"conflicts,omitempty" yaml:"conflicts,omitempty"` + Provides []*PackageSanitized `json:"provides,omitempty" yaml:"provides,omitempty"` Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` @@ -44,16 +44,26 @@ type DefaultPackageSanitized struct { Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` } -func NewDefaultPackageSanitizedFromYaml(data []byte) (*DefaultPackageSanitized, error) { - ans := &DefaultPackageSanitized{} +func NewDefaultPackageSanitizedFromYaml(data []byte) (*PackageSanitized, error) { + ans := &PackageSanitized{} if err := yaml.Unmarshal(data, ans); err != nil { return nil, err } return ans, nil } -func NewDefaultPackageSanitized(p pkg.Package) *DefaultPackageSanitized { - ans := &DefaultPackageSanitized{ +func NewDefaultPackageSanitized(p *types.Package) (ans *PackageSanitized) { + + ann := map[string]string{} + if len(p.Annotations) == 0 { + ann = nil + } else { + for k, v := range p.Annotations { + ann[string(k)] = v + } + } + + ans = &PackageSanitized{ Name: p.GetName(), Version: p.GetVersion(), Category: p.GetCategory(), @@ -64,15 +74,15 @@ func NewDefaultPackageSanitized(p pkg.Package) *DefaultPackageSanitized { Uri: p.GetURI(), License: p.GetLicense(), Labels: p.GetLabels(), - Annotations: p.GetAnnotations(), + Annotations: ann, } if p.GetRequires() != nil && len(p.GetRequires()) > 0 { - ans.PackageRequires = []*DefaultPackageSanitized{} + ans.PackageRequires = []*PackageSanitized{} for _, r := range p.GetRequires() { // I avoid recursive call of NewDefaultPackageSanitized ans.PackageRequires = append(ans.PackageRequires, - &DefaultPackageSanitized{ + &PackageSanitized{ Name: r.Name, Version: r.Version, Category: r.Category, @@ -83,11 +93,11 @@ func NewDefaultPackageSanitized(p pkg.Package) *DefaultPackageSanitized { } if p.GetConflicts() != nil && len(p.GetConflicts()) > 0 { - ans.PackageConflicts = []*DefaultPackageSanitized{} + ans.PackageConflicts = []*PackageSanitized{} for _, c := range p.GetConflicts() { // I avoid recursive call of NewDefaultPackageSanitized ans.PackageConflicts = append(ans.PackageConflicts, - &DefaultPackageSanitized{ + &PackageSanitized{ Name: c.Name, Version: c.Version, Category: c.Category, @@ -98,11 +108,11 @@ func NewDefaultPackageSanitized(p pkg.Package) *DefaultPackageSanitized { } if p.GetProvides() != nil && len(p.GetProvides()) > 0 { - ans.Provides = []*DefaultPackageSanitized{} + ans.Provides = []*PackageSanitized{} for _, prov := range p.GetProvides() { // I avoid recursive call of NewDefaultPackageSanitized ans.Provides = append(ans.Provides, - &DefaultPackageSanitized{ + &PackageSanitized{ Name: prov.Name, Version: prov.Version, Category: prov.Category, @@ -112,14 +122,14 @@ func NewDefaultPackageSanitized(p pkg.Package) *DefaultPackageSanitized { } } - return ans + return } -func (p *DefaultPackageSanitized) Yaml() ([]byte, error) { +func (p PackageSanitized) Yaml() ([]byte, error) { return yaml.Marshal(p) } -func (p *DefaultPackageSanitized) Clone() (*DefaultPackageSanitized, error) { +func (p PackageSanitized) Clone() (*PackageSanitized, error) { data, err := p.Yaml() if err != nil { return nil, err diff --git a/pkg/spectooling/package_test.go b/pkg/spectooling/package_test.go index e9a86f8f..57360891 100644 --- a/pkg/spectooling/package_test.go +++ b/pkg/spectooling/package_test.go @@ -17,7 +17,8 @@ package spectooling_test import ( - pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" + . "github.com/mudler/luet/pkg/spectooling" . "github.com/onsi/ginkgo/v2" @@ -27,13 +28,13 @@ import ( var _ = Describe("Spec Tooling", func() { Context("Conversion1", func() { - b := pkg.NewPackage("B", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - c := pkg.NewPackage("C", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - d := pkg.NewPackage("D", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) - p1 := pkg.NewPackage("A", "1.0", []*pkg.DefaultPackage{b, c}, []*pkg.DefaultPackage{d}) - virtual := pkg.NewPackage("E", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) + b := types.NewPackage("B", "1.0", []*types.Package{}, []*types.Package{}) + c := types.NewPackage("C", "1.0", []*types.Package{}, []*types.Package{}) + d := types.NewPackage("D", "1.0", []*types.Package{}, []*types.Package{}) + p1 := types.NewPackage("A", "1.0", []*types.Package{b, c}, []*types.Package{d}) + virtual := types.NewPackage("E", "1.0", []*types.Package{}, []*types.Package{}) virtual.SetCategory("virtual") - p1.Provides = []*pkg.DefaultPackage{virtual} + p1.Provides = []*types.Package{virtual} p1.AddLabel("label1", "value1") p1.AddLabel("label2", "value2") p1.SetDescription("Package1") @@ -43,28 +44,28 @@ var _ = Describe("Spec Tooling", func() { p1.AddUse("systemd") It("Convert pkg1", func() { res := NewDefaultPackageSanitized(p1) - expected_res := &DefaultPackageSanitized{ + expected_res := &PackageSanitized{ Name: "A", Version: "1.0", Category: "cat1", - PackageRequires: []*DefaultPackageSanitized{ - &DefaultPackageSanitized{ + PackageRequires: []*PackageSanitized{ + &PackageSanitized{ Name: "B", Version: "1.0", }, - &DefaultPackageSanitized{ + &PackageSanitized{ Name: "C", Version: "1.0", }, }, - PackageConflicts: []*DefaultPackageSanitized{ - &DefaultPackageSanitized{ + PackageConflicts: []*PackageSanitized{ + &PackageSanitized{ Name: "D", Version: "1.0", }, }, - Provides: []*DefaultPackageSanitized{ - &DefaultPackageSanitized{ + Provides: []*PackageSanitized{ + &PackageSanitized{ Name: "E", Category: "virtual", Version: "1.0", diff --git a/pkg/tree/builder.go b/pkg/tree/builder.go index d98e651b..f51aac08 100644 --- a/pkg/tree/builder.go +++ b/pkg/tree/builder.go @@ -15,16 +15,14 @@ package tree -import ( - pkg "github.com/mudler/luet/pkg/package" -) +import "github.com/mudler/luet/pkg/api/core/types" // reads a luet tree and generates the package lists type Builder interface { Save(string) error // A tree might be saved to a folder structure (human editable) Load(string) error // A tree might be loaded from a db (e.g. bolt) and written to folder - GetDatabase() pkg.PackageDatabase - WithDatabase(d pkg.PackageDatabase) + GetDatabase() types.PackageDatabase + WithDatabase(d types.PackageDatabase) GetSourcePath() []string } diff --git a/pkg/tree/compiler_recipe.go b/pkg/tree/compiler_recipe.go index 9f401742..30556bb8 100644 --- a/pkg/tree/compiler_recipe.go +++ b/pkg/tree/compiler_recipe.go @@ -25,9 +25,9 @@ import ( "os" "path/filepath" + "github.com/mudler/luet/pkg/api/core/types" "github.com/mudler/luet/pkg/helpers" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" "github.com/pkg/errors" ) @@ -35,17 +35,17 @@ const ( CompilerDefinitionFile = "build.yaml" ) -func NewCompilerRecipe(d pkg.PackageDatabase) Builder { +func NewCompilerRecipe(d types.PackageDatabase) Builder { return &CompilerRecipe{Recipe: Recipe{Database: d}} } -func ReadDefinitionFile(path string) (pkg.DefaultPackage, error) { - empty := pkg.DefaultPackage{} +func ReadDefinitionFile(path string) (types.Package, error) { + empty := types.Package{} dat, err := ioutil.ReadFile(path) if err != nil { return empty, errors.Wrap(err, "Error reading file "+path) } - pack, err := pkg.DefaultPackageFromYaml(dat) + pack, err := types.PackageFromYaml(dat) if err != nil { return empty, errors.Wrap(err, "Error reading yaml "+path) } @@ -90,12 +90,12 @@ func (r *CompilerRecipe) Load(path string) error { return errors.Wrap(err, "Error on walk path "+currentpath) } - if info.Name() != pkg.PackageDefinitionFile && info.Name() != pkg.PackageCollectionFile { + if info.Name() != types.PackageDefinitionFile && info.Name() != types.PackageCollectionFile { return nil // Skip with no errors } switch info.Name() { - case pkg.PackageDefinitionFile: + case types.PackageDefinitionFile: pack, err := ReadDefinitionFile(currentpath) if err != nil { @@ -115,7 +115,7 @@ func (r *CompilerRecipe) Load(path string) error { filepath.Dir(currentpath)) } - packbuild, err := pkg.DefaultPackageFromYaml([]byte(dat)) + packbuild, err := types.PackageFromYaml([]byte(dat)) if err != nil { return errors.Wrap(err, "Error reading yaml "+CompilerDefinitionFile+" from "+ @@ -130,19 +130,19 @@ func (r *CompilerRecipe) Load(path string) error { return errors.Wrap(err, "Error creating package "+pack.GetName()) } - case pkg.PackageCollectionFile: + case types.PackageCollectionFile: dat, err := ioutil.ReadFile(currentpath) if err != nil { return errors.Wrap(err, "Error reading file "+currentpath) } - packs, err := pkg.DefaultPackagesFromYAML(dat) + packs, err := types.PackagesFromYAML(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) } - packsRaw, err := pkg.GetRawPackages(dat) + packsRaw, err := types.GetRawPackages(dat) if err != nil { return errors.Wrap(err, "Error reading raw packages from "+currentpath) } @@ -167,7 +167,7 @@ func (r *CompilerRecipe) Load(path string) error { filepath.Dir(currentpath)) } - packbuild, err := pkg.DefaultPackageFromYaml([]byte(dat)) + packbuild, err := types.PackageFromYaml([]byte(dat)) if err != nil { return errors.Wrap(err, "Error reading yaml "+CompilerDefinitionFile+" from "+ @@ -194,6 +194,6 @@ func (r *CompilerRecipe) Load(path string) error { return nil } -func (r *CompilerRecipe) GetDatabase() pkg.PackageDatabase { return r.Database } -func (r *CompilerRecipe) WithDatabase(d pkg.PackageDatabase) { r.Database = d } -func (r *CompilerRecipe) GetSourcePath() []string { return r.SourcePath } +func (r *CompilerRecipe) GetDatabase() types.PackageDatabase { return r.Database } +func (r *CompilerRecipe) WithDatabase(d types.PackageDatabase) { r.Database = d } +func (r *CompilerRecipe) GetSourcePath() []string { return r.SourcePath } diff --git a/pkg/tree/installer_recipe.go b/pkg/tree/installer_recipe.go index 974e0af6..bed49b90 100644 --- a/pkg/tree/installer_recipe.go +++ b/pkg/tree/installer_recipe.go @@ -26,8 +26,8 @@ import ( "os" "path/filepath" + "github.com/mudler/luet/pkg/api/core/types" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" "github.com/pkg/errors" ) @@ -36,14 +36,14 @@ const ( FinalizerFile = "finalize.yaml" ) -func NewInstallerRecipe(db pkg.PackageDatabase) Builder { +func NewInstallerRecipe(db types.PackageDatabase) Builder { return &InstallerRecipe{Database: db} } // InstallerRecipe is the "general" reciper for Trees type InstallerRecipe struct { SourcePath []string - Database pkg.PackageDatabase + Database types.PackageDatabase } func (r *InstallerRecipe) Save(path string) error { @@ -56,7 +56,7 @@ func (r *InstallerRecipe) Save(path string) error { if err != nil { return err } - err = ioutil.WriteFile(filepath.Join(dir, pkg.PackageDefinitionFile), data, 0644) + err = ioutil.WriteFile(filepath.Join(dir, types.PackageDefinitionFile), data, 0644) if err != nil { return err } @@ -86,7 +86,7 @@ func (r *InstallerRecipe) Load(path string) error { // the function that handles each file or dir var ff = func(currentpath string, info os.FileInfo, err error) error { - if info.Name() != pkg.PackageDefinitionFile && info.Name() != pkg.PackageCollectionFile { + if info.Name() != types.PackageDefinitionFile && info.Name() != types.PackageCollectionFile { return nil // Skip with no errors } @@ -96,8 +96,8 @@ func (r *InstallerRecipe) Load(path string) error { } switch info.Name() { - case pkg.PackageDefinitionFile: - pack, err := pkg.DefaultPackageFromYaml(dat) + case types.PackageDefinitionFile: + pack, err := types.PackageFromYaml(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) } @@ -109,8 +109,8 @@ func (r *InstallerRecipe) Load(path string) error { return errors.Wrap(err, "Error creating package "+pack.GetName()) } - case pkg.PackageCollectionFile: - packs, err := pkg.DefaultPackagesFromYAML(dat) + case types.PackageCollectionFile: + packs, err := types.PackagesFromYAML(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) } @@ -135,6 +135,6 @@ func (r *InstallerRecipe) Load(path string) error { return nil } -func (r *InstallerRecipe) GetDatabase() pkg.PackageDatabase { return r.Database } -func (r *InstallerRecipe) WithDatabase(d pkg.PackageDatabase) { r.Database = d } -func (r *InstallerRecipe) GetSourcePath() []string { return r.SourcePath } +func (r *InstallerRecipe) GetDatabase() types.PackageDatabase { return r.Database } +func (r *InstallerRecipe) WithDatabase(d types.PackageDatabase) { r.Database = d } +func (r *InstallerRecipe) GetSourcePath() []string { return r.SourcePath } diff --git a/pkg/tree/parser.go b/pkg/tree/parser.go index 34d0fefb..971c12c0 100644 --- a/pkg/tree/parser.go +++ b/pkg/tree/parser.go @@ -15,9 +15,9 @@ package tree -import pkg "github.com/mudler/luet/pkg/package" +import "github.com/mudler/luet/pkg/api/core/types" // parses ebuilds (?) and generates data which is readable by the builder type Parser interface { - Generate(string) (pkg.PackageDatabase, error) // Generate scannable luet tree (by builder) + Generate(string) (types.PackageDatabase, error) // Generate scannable luet tree (by builder) } diff --git a/pkg/tree/recipes.go b/pkg/tree/recipes.go index 2738839b..449e19f9 100644 --- a/pkg/tree/recipes.go +++ b/pkg/tree/recipes.go @@ -26,22 +26,23 @@ import ( "os" "path/filepath" + "github.com/mudler/luet/pkg/api/core/types" + pkg "github.com/mudler/luet/pkg/database" fileHelper "github.com/mudler/luet/pkg/helpers/file" - pkg "github.com/mudler/luet/pkg/package" spectooling "github.com/mudler/luet/pkg/spectooling" "github.com/pkg/errors" ) -func NewGeneralRecipe(db pkg.PackageDatabase) Builder { return &Recipe{Database: db} } +func NewGeneralRecipe(db types.PackageDatabase) Builder { return &Recipe{Database: db} } // Recipe is the "general" reciper for Trees type Recipe struct { SourcePath []string - Database pkg.PackageDatabase + Database types.PackageDatabase } -func WriteDefinitionFile(p pkg.Package, definitionFilePath string) error { +func WriteDefinitionFile(p *types.Package, definitionFilePath string) error { data, err := spectooling.NewDefaultPackageSanitized(p).Yaml() if err != nil { return err @@ -59,7 +60,7 @@ func (r *Recipe) Save(path string) error { dir := filepath.Join(path, p.GetCategory(), p.GetName(), p.GetVersion()) os.MkdirAll(dir, os.ModePerm) - err := WriteDefinitionFile(p, filepath.Join(dir, pkg.PackageDefinitionFile)) + err := WriteDefinitionFile(p, filepath.Join(dir, types.PackageDefinitionFile)) if err != nil { return err } @@ -91,7 +92,7 @@ func (r *Recipe) Load(path string) error { // the function that handles each file or dir var ff = func(currentpath string, info os.FileInfo, err error) error { - if info.Name() != pkg.PackageDefinitionFile && info.Name() != pkg.PackageCollectionFile { + if info.Name() != types.PackageDefinitionFile && info.Name() != types.PackageCollectionFile { return nil // Skip with no errors } @@ -101,8 +102,8 @@ func (r *Recipe) Load(path string) error { } switch info.Name() { - case pkg.PackageDefinitionFile: - pack, err := pkg.DefaultPackageFromYaml(dat) + case types.PackageDefinitionFile: + pack, err := types.PackageFromYaml(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) } @@ -113,8 +114,8 @@ func (r *Recipe) Load(path string) error { if err != nil { return errors.Wrap(err, "Error creating package "+pack.GetName()) } - case pkg.PackageCollectionFile: - packs, err := pkg.DefaultPackagesFromYAML(dat) + case types.PackageCollectionFile: + packs, err := types.PackagesFromYAML(dat) if err != nil { return errors.Wrap(err, "Error reading yaml "+currentpath) } @@ -139,6 +140,6 @@ func (r *Recipe) Load(path string) error { return nil } -func (r *Recipe) GetDatabase() pkg.PackageDatabase { return r.Database } -func (r *Recipe) WithDatabase(d pkg.PackageDatabase) { r.Database = d } -func (r *Recipe) GetSourcePath() []string { return r.SourcePath } +func (r *Recipe) GetDatabase() types.PackageDatabase { return r.Database } +func (r *Recipe) WithDatabase(d types.PackageDatabase) { r.Database = d } +func (r *Recipe) GetSourcePath() []string { return r.SourcePath } diff --git a/pkg/tree/tree_test.go b/pkg/tree/tree_test.go index d5263620..49ab52c8 100644 --- a/pkg/tree/tree_test.go +++ b/pkg/tree/tree_test.go @@ -28,7 +28,8 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" + pkg "github.com/mudler/luet/pkg/database" "github.com/mudler/luet/pkg/solver" . "github.com/mudler/luet/pkg/tree" ) @@ -49,7 +50,7 @@ var _ = Describe("Tree", func() { Expect(len(generalRecipe.GetDatabase().World())).To(Equal(4)) - D, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) + D, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "d", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(D.GetRequires()[0].GetName()).To(Equal("c")) @@ -59,11 +60,11 @@ var _ = Describe("Tree", func() { Expect(len(CfromD.GetRequires()) != 0).To(BeTrue()) Expect(CfromD.GetRequires()[0].GetName()).To(Equal("b")) - s := solver.NewSolver(solver.Options{Type: solver.SingleCoreSimple}, pkg.NewInMemoryDatabase(false), generalRecipe.GetDatabase(), db) - pack, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) + s := solver.NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, pkg.NewInMemoryDatabase(false), generalRecipe.GetDatabase(), db) + pack, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "d", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - solution, err := s.Install([]pkg.Package{pack}) + solution, err := s.Install([]*types.Package{pack}) Expect(err).ToNot(HaveOccurred()) solution, err = solution.Order(generalRecipe.GetDatabase(), pack.GetFingerPrint()) @@ -79,7 +80,7 @@ var _ = Describe("Tree", func() { Expect(solution[2].Value).To(BeTrue()) Expect(len(solution)).To(Equal(3)) - newsolution := solution.Drop(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) + newsolution := solution.Drop(&types.Package{Name: "d", Category: "test", Version: "1.0"}) Expect(len(newsolution)).To(Equal(2)) Expect(newsolution[0].Package.GetName()).To(Equal("b")) @@ -111,11 +112,11 @@ var _ = Describe("Tree", func() { Expect(len(generalRecipe.GetDatabase().World())).To(Equal(6)) - extra, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "extra", Category: "layer", Version: "1.0"}) + extra, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "extra", Category: "layer", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(extra).ToNot(BeNil()) - D, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) + D, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "d", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) Expect(D.GetRequires()[0].GetName()).To(Equal("c")) @@ -125,25 +126,25 @@ var _ = Describe("Tree", func() { Expect(len(CfromD.GetRequires()) != 0).To(BeTrue()) Expect(CfromD.GetRequires()[0].GetName()).To(Equal("b")) - s := solver.NewSolver(solver.Options{Type: solver.SingleCoreSimple}, pkg.NewInMemoryDatabase(false), generalRecipe.GetDatabase(), db) + s := solver.NewSolver(types.SolverOptions{Type: types.SolverSingleCoreSimple}, pkg.NewInMemoryDatabase(false), generalRecipe.GetDatabase(), db) - Dd, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "d", Category: "test", Version: "1.0"}) + Dd, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "d", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - solution, err := s.Install([]pkg.Package{Dd}) + solution, err := s.Install([]*types.Package{Dd}) Expect(err).ToNot(HaveOccurred()) solution, err = solution.Order(generalRecipe.GetDatabase(), Dd.GetFingerPrint()) Expect(err).ToNot(HaveOccurred()) - pack, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "a", Category: "test", Version: "1.0"}) + pack, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "a", Category: "test", Version: "1.0"}) Expect(err).ToNot(HaveOccurred()) - base, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "base", Category: "layer", Version: "0.2"}) + base, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "base", Category: "layer", Version: "0.2"}) Expect(err).ToNot(HaveOccurred()) - Expect(solution).ToNot(ContainElement(solver.PackageAssert{Package: pack.(*pkg.DefaultPackage), Value: true})) - Expect(solution).To(ContainElement(solver.PackageAssert{Package: D.(*pkg.DefaultPackage), Value: true})) - Expect(solution).ToNot(ContainElement(solver.PackageAssert{Package: extra.(*pkg.DefaultPackage), Value: true})) - Expect(solution).ToNot(ContainElement(solver.PackageAssert{Package: base.(*pkg.DefaultPackage), Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: pack, Value: true})) + Expect(solution).To(ContainElement(types.PackageAssert{Package: D, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: extra, Value: true})) + Expect(solution).ToNot(ContainElement(types.PackageAssert{Package: base, Value: true})) Expect(len(solution)).To(Equal(3)) } }) @@ -158,7 +159,7 @@ var _ = Describe("Tree", func() { Expect(err).ToNot(HaveOccurred()) Expect(len(generalRecipe.GetDatabase().World())).To(Equal(1)) - pack, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "pkgA", Category: "test", Version: "0.1"}) + pack, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "pkgA", Category: "test", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) Expect(pack.HasLabel("label1")).To(Equal(true)) @@ -176,11 +177,13 @@ var _ = Describe("Tree", func() { Expect(err).ToNot(HaveOccurred()) Expect(len(generalRecipe.GetDatabase().World())).To(Equal(1)) - pack, err := generalRecipe.GetDatabase().FindPackage(&pkg.DefaultPackage{Name: "pkgA", Category: "test", Version: "0.1"}) + pack, err := generalRecipe.GetDatabase().FindPackage(&types.Package{Name: "pkgA", Category: "test", Version: "0.1"}) Expect(err).ToNot(HaveOccurred()) - Expect(pack.HasAnnotation("label1")).To(Equal(true)) - Expect(pack.HasAnnotation("label3")).To(Equal(false)) + _, existsLabel1 := pack.Annotations["label1"] + _, existsLabel2 := pack.Annotations["label3"] + Expect(existsLabel1).To(Equal(true)) + Expect(existsLabel2).To(Equal(false)) Expect(pack.MatchAnnotation(r)).To(Equal(true)) }) }) diff --git a/tests/helpers/package.go b/tests/helpers/package.go index b236db4f..cf3f5ac2 100644 --- a/tests/helpers/package.go +++ b/tests/helpers/package.go @@ -5,7 +5,7 @@ import ( "strconv" "time" - pkg "github.com/mudler/luet/pkg/package" + "github.com/mudler/luet/pkg/api/core/types" ) const charset = "abcdefghijklmnopqrstuvwxyz" + @@ -26,6 +26,6 @@ func String(length int) string { return StringWithCharset(length, charset) } -func RandomPackage() pkg.Package { - return pkg.NewPackage(String(5), strconv.Itoa(rand.Intn(100)), []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{}) +func RandomPackage() *types.Package { + return types.NewPackage(String(5), strconv.Itoa(rand.Intn(100)), []*types.Package{}, []*types.Package{}) } diff --git a/tests/integration/28_nobuildtreedocker.sh b/tests/integration/28_nobuildtreedocker.sh index 32c8946e..66885e47 100755 --- a/tests/integration/28_nobuildtreedocker.sh +++ b/tests/integration/28_nobuildtreedocker.sh @@ -51,7 +51,7 @@ testBuild() { assertTrue 'create package' "[ -e '$tmpdir/testbuild/c-test-1.0.package.tar.zst' ]" assertTrue 'create package Z' "[ -e '$tmpdir/testbuild/z-test-1.0+2.package.tar.zst' ]" assertTrue 'create package interpolated' "[ -e '$tmpdir/testbuild/interpolated-test-1.0+2.package.tar.zst' ]" - assertContains 'Does use the upstream cache without specifying it test/c' "$build_output" "Images available remotely for test/c-1.0 generating artifact from remote images: quay.io/mocaccinoos/integration-test-cache:45aee5952a98ec9fb7bf6de0eb238e7a7ad1a2ca0645be33400b4d52b8a6527a" + assertContains 'Does use the upstream cache without specifying it test/c' "$build_output" "Images available remotely for test/c-1.0 generating artifact from remote images: quay.io/mocaccinoos/integration-test-cache:d6a82b43c97322cfc549176f54b459d6e6b4a7c756ba5bcd17f1775469ad42c7" assertContains 'Does use the upstream cache without specifying it test/z' "$build_output" "Images available remotely for test/z-1.0+2 generating artifact from remote images: quay.io/mocaccinoos/integration-test-cache:e324d35eca913bde850b6fd130496b3b347f0090d5bbed900d4b64b837df89d8" assertContains 'Does use the upstream cache without specifying it test/interpolated' "$build_output" "Images available remotely for test/interpolated-1.0+2 generating artifact from remote images: quay.io/mocaccinoos/integration-test-cache:bec91b2b88dfeb68c9cad762a99a35233f7a38722573c4982d9b2168aac5992e" } diff --git a/vendor/github.com/asaskevich/govalidator/.gitignore b/vendor/github.com/asaskevich/govalidator/.gitignore deleted file mode 100644 index 8d69a941..00000000 --- a/vendor/github.com/asaskevich/govalidator/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -bin/ -.idea/ -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - diff --git a/vendor/github.com/asaskevich/govalidator/.travis.yml b/vendor/github.com/asaskevich/govalidator/.travis.yml deleted file mode 100644 index bb83c667..00000000 --- a/vendor/github.com/asaskevich/govalidator/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: go -dist: xenial -go: - - '1.10' - - '1.11' - - '1.12' - - '1.13' - - 'tip' - -script: - - go test -coverpkg=./... -coverprofile=coverage.info -timeout=5s - - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/asaskevich/govalidator/CODE_OF_CONDUCT.md b/vendor/github.com/asaskevich/govalidator/CODE_OF_CONDUCT.md deleted file mode 100644 index 4b462b0d..00000000 --- a/vendor/github.com/asaskevich/govalidator/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,43 +0,0 @@ -# Contributor Code of Conduct - -This project adheres to [The Code Manifesto](http://codemanifesto.com) -as its guidelines for contributor interactions. - -## The Code Manifesto - -We want to work in an ecosystem that empowers developers to reach their -potential — one that encourages growth and effective collaboration. A space -that is safe for all. - -A space such as this benefits everyone that participates in it. It encourages -new developers to enter our field. It is through discussion and collaboration -that we grow, and through growth that we improve. - -In the effort to create such a place, we hold to these values: - -1. **Discrimination limits us.** This includes discrimination on the basis of - race, gender, sexual orientation, gender identity, age, nationality, - technology and any other arbitrary exclusion of a group of people. -2. **Boundaries honor us.** Your comfort levels are not everyone’s comfort - levels. Remember that, and if brought to your attention, heed it. -3. **We are our biggest assets.** None of us were born masters of our trade. - Each of us has been helped along the way. Return that favor, when and where - you can. -4. **We are resources for the future.** As an extension of #3, share what you - know. Make yourself a resource to help those that come after you. -5. **Respect defines us.** Treat others as you wish to be treated. Make your - discussions, criticisms and debates from a position of respectfulness. Ask - yourself, is it true? Is it necessary? Is it constructive? Anything less is - unacceptable. -6. **Reactions require grace.** Angry responses are valid, but abusive language - and vindictive actions are toxic. When something happens that offends you, - handle it assertively, but be respectful. Escalate reasonably, and try to - allow the offender an opportunity to explain themselves, and possibly - correct the issue. -7. **Opinions are just that: opinions.** Each and every one of us, due to our - background and upbringing, have varying opinions. That is perfectly - acceptable. Remember this: if you respect your own opinions, you should - respect the opinions of others. -8. **To err is human.** You might not intend it, but mistakes do happen and - contribute to build experience. Tolerate honest mistakes, and don't - hesitate to apologize if you make one yourself. diff --git a/vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md b/vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md deleted file mode 100644 index 7ed268a1..00000000 --- a/vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md +++ /dev/null @@ -1,63 +0,0 @@ -#### Support -If you do have a contribution to the package, feel free to create a Pull Request or an Issue. - -#### What to contribute -If you don't know what to do, there are some features and functions that need to be done - -- [ ] Refactor code -- [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check -- [ ] Create actual list of contributors and projects that currently using this package -- [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues) -- [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions) -- [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new -- [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc -- [x] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224) -- [ ] Implement fuzzing testing -- [ ] Implement some struct/map/array utilities -- [ ] Implement map/array validation -- [ ] Implement benchmarking -- [ ] Implement batch of examples -- [ ] Look at forks for new features and fixes - -#### Advice -Feel free to create what you want, but keep in mind when you implement new features: -- Code must be clear and readable, names of variables/constants clearly describes what they are doing -- Public functions must be documented and described in source file and added to README.md to the list of available functions -- There are must be unit-tests for any new functions and improvements - -## Financial contributions - -We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/govalidator). -Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed. - - -## Credits - - -### Contributors - -Thank you to all the people who have already contributed to govalidator! - - - -### Backers - -Thank you to all our backers! [[Become a backer](https://opencollective.com/govalidator#backer)] - - - - -### Sponsors - -Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/govalidator#sponsor)) - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/asaskevich/govalidator/LICENSE b/vendor/github.com/asaskevich/govalidator/LICENSE deleted file mode 100644 index cacba910..00000000 --- a/vendor/github.com/asaskevich/govalidator/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014-2020 Alex Saskevich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/asaskevich/govalidator/README.md b/vendor/github.com/asaskevich/govalidator/README.md deleted file mode 100644 index 39121ea8..00000000 --- a/vendor/github.com/asaskevich/govalidator/README.md +++ /dev/null @@ -1,619 +0,0 @@ -govalidator -=========== -[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/asaskevich/govalidator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![GoDoc](https://godoc.org/github.com/asaskevich/govalidator?status.png)](https://godoc.org/github.com/asaskevich/govalidator) -[![Build Status](https://travis-ci.org/asaskevich/govalidator.svg?branch=master)](https://travis-ci.org/asaskevich/govalidator) -[![Coverage](https://codecov.io/gh/asaskevich/govalidator/branch/master/graph/badge.svg)](https://codecov.io/gh/asaskevich/govalidator) [![Go Report Card](https://goreportcard.com/badge/github.com/asaskevich/govalidator)](https://goreportcard.com/report/github.com/asaskevich/govalidator) [![GoSearch](http://go-search.org/badge?id=github.com%2Fasaskevich%2Fgovalidator)](http://go-search.org/view?id=github.com%2Fasaskevich%2Fgovalidator) [![Backers on Open Collective](https://opencollective.com/govalidator/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/govalidator/sponsors/badge.svg)](#sponsors) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator?ref=badge_shield) - -A package of validators and sanitizers for strings, structs and collections. Based on [validator.js](https://github.com/chriso/validator.js). - -#### Installation -Make sure that Go is installed on your computer. -Type the following command in your terminal: - - go get github.com/asaskevich/govalidator - -or you can get specified release of the package with `gopkg.in`: - - go get gopkg.in/asaskevich/govalidator.v10 - -After it the package is ready to use. - - -#### Import package in your project -Add following line in your `*.go` file: -```go -import "github.com/asaskevich/govalidator" -``` -If you are unhappy to use long `govalidator`, you can do something like this: -```go -import ( - valid "github.com/asaskevich/govalidator" -) -``` - -#### Activate behavior to require all fields have a validation tag by default -`SetFieldsRequiredByDefault` causes validation to fail when struct fields do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). A good place to activate this is a package init function or the main() function. - -`SetNilPtrAllowedByRequired` causes validation to pass when struct fields marked by `required` are set to nil. This is disabled by default for consistency, but some packages that need to be able to determine between `nil` and `zero value` state can use this. If disabled, both `nil` and `zero` values cause validation errors. - -```go -import "github.com/asaskevich/govalidator" - -func init() { - govalidator.SetFieldsRequiredByDefault(true) -} -``` - -Here's some code to explain it: -```go -// this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter): -type exampleStruct struct { - Name string `` - Email string `valid:"email"` -} - -// this, however, will only fail when Email is empty or an invalid email address: -type exampleStruct2 struct { - Name string `valid:"-"` - Email string `valid:"email"` -} - -// lastly, this will only fail when Email is an invalid email address but not when it's empty: -type exampleStruct2 struct { - Name string `valid:"-"` - Email string `valid:"email,optional"` -} -``` - -#### Recent breaking changes (see [#123](https://github.com/asaskevich/govalidator/pull/123)) -##### Custom validator function signature -A context was added as the second parameter, for structs this is the object being validated – this makes dependent validation possible. -```go -import "github.com/asaskevich/govalidator" - -// old signature -func(i interface{}) bool - -// new signature -func(i interface{}, o interface{}) bool -``` - -##### Adding a custom validator -This was changed to prevent data races when accessing custom validators. -```go -import "github.com/asaskevich/govalidator" - -// before -govalidator.CustomTypeTagMap["customByteArrayValidator"] = func(i interface{}, o interface{}) bool { - // ... -} - -// after -govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, o interface{}) bool { - // ... -}) -``` - -#### List of functions: -```go -func Abs(value float64) float64 -func BlackList(str, chars string) string -func ByteLength(str string, params ...string) bool -func CamelCaseToUnderscore(str string) string -func Contains(str, substring string) bool -func Count(array []interface{}, iterator ConditionIterator) int -func Each(array []interface{}, iterator Iterator) -func ErrorByField(e error, field string) string -func ErrorsByField(e error) map[string]string -func Filter(array []interface{}, iterator ConditionIterator) []interface{} -func Find(array []interface{}, iterator ConditionIterator) interface{} -func GetLine(s string, index int) (string, error) -func GetLines(s string) []string -func HasLowerCase(str string) bool -func HasUpperCase(str string) bool -func HasWhitespace(str string) bool -func HasWhitespaceOnly(str string) bool -func InRange(value interface{}, left interface{}, right interface{}) bool -func InRangeFloat32(value, left, right float32) bool -func InRangeFloat64(value, left, right float64) bool -func InRangeInt(value, left, right interface{}) bool -func IsASCII(str string) bool -func IsAlpha(str string) bool -func IsAlphanumeric(str string) bool -func IsBase64(str string) bool -func IsByteLength(str string, min, max int) bool -func IsCIDR(str string) bool -func IsCRC32(str string) bool -func IsCRC32b(str string) bool -func IsCreditCard(str string) bool -func IsDNSName(str string) bool -func IsDataURI(str string) bool -func IsDialString(str string) bool -func IsDivisibleBy(str, num string) bool -func IsEmail(str string) bool -func IsExistingEmail(email string) bool -func IsFilePath(str string) (bool, int) -func IsFloat(str string) bool -func IsFullWidth(str string) bool -func IsHalfWidth(str string) bool -func IsHash(str string, algorithm string) bool -func IsHexadecimal(str string) bool -func IsHexcolor(str string) bool -func IsHost(str string) bool -func IsIP(str string) bool -func IsIPv4(str string) bool -func IsIPv6(str string) bool -func IsISBN(str string, version int) bool -func IsISBN10(str string) bool -func IsISBN13(str string) bool -func IsISO3166Alpha2(str string) bool -func IsISO3166Alpha3(str string) bool -func IsISO4217(str string) bool -func IsISO693Alpha2(str string) bool -func IsISO693Alpha3b(str string) bool -func IsIn(str string, params ...string) bool -func IsInRaw(str string, params ...string) bool -func IsInt(str string) bool -func IsJSON(str string) bool -func IsLatitude(str string) bool -func IsLongitude(str string) bool -func IsLowerCase(str string) bool -func IsMAC(str string) bool -func IsMD4(str string) bool -func IsMD5(str string) bool -func IsMagnetURI(str string) bool -func IsMongoID(str string) bool -func IsMultibyte(str string) bool -func IsNatural(value float64) bool -func IsNegative(value float64) bool -func IsNonNegative(value float64) bool -func IsNonPositive(value float64) bool -func IsNotNull(str string) bool -func IsNull(str string) bool -func IsNumeric(str string) bool -func IsPort(str string) bool -func IsPositive(value float64) bool -func IsPrintableASCII(str string) bool -func IsRFC3339(str string) bool -func IsRFC3339WithoutZone(str string) bool -func IsRGBcolor(str string) bool -func IsRequestURI(rawurl string) bool -func IsRequestURL(rawurl string) bool -func IsRipeMD128(str string) bool -func IsRipeMD160(str string) bool -func IsRsaPub(str string, params ...string) bool -func IsRsaPublicKey(str string, keylen int) bool -func IsSHA1(str string) bool -func IsSHA256(str string) bool -func IsSHA384(str string) bool -func IsSHA512(str string) bool -func IsSSN(str string) bool -func IsSemver(str string) bool -func IsTiger128(str string) bool -func IsTiger160(str string) bool -func IsTiger192(str string) bool -func IsTime(str string, format string) bool -func IsType(v interface{}, params ...string) bool -func IsURL(str string) bool -func IsUTFDigit(str string) bool -func IsUTFLetter(str string) bool -func IsUTFLetterNumeric(str string) bool -func IsUTFNumeric(str string) bool -func IsUUID(str string) bool -func IsUUIDv3(str string) bool -func IsUUIDv4(str string) bool -func IsUUIDv5(str string) bool -func IsUnixTime(str string) bool -func IsUpperCase(str string) bool -func IsVariableWidth(str string) bool -func IsWhole(value float64) bool -func LeftTrim(str, chars string) string -func Map(array []interface{}, iterator ResultIterator) []interface{} -func Matches(str, pattern string) bool -func MaxStringLength(str string, params ...string) bool -func MinStringLength(str string, params ...string) bool -func NormalizeEmail(str string) (string, error) -func PadBoth(str string, padStr string, padLen int) string -func PadLeft(str string, padStr string, padLen int) string -func PadRight(str string, padStr string, padLen int) string -func PrependPathToErrors(err error, path string) error -func Range(str string, params ...string) bool -func RemoveTags(s string) string -func ReplacePattern(str, pattern, replace string) string -func Reverse(s string) string -func RightTrim(str, chars string) string -func RuneLength(str string, params ...string) bool -func SafeFileName(str string) string -func SetFieldsRequiredByDefault(value bool) -func SetNilPtrAllowedByRequired(value bool) -func Sign(value float64) float64 -func StringLength(str string, params ...string) bool -func StringMatches(s string, params ...string) bool -func StripLow(str string, keepNewLines bool) string -func ToBoolean(str string) (bool, error) -func ToFloat(str string) (float64, error) -func ToInt(value interface{}) (res int64, err error) -func ToJSON(obj interface{}) (string, error) -func ToString(obj interface{}) string -func Trim(str, chars string) string -func Truncate(str string, length int, ending string) string -func TruncatingErrorf(str string, args ...interface{}) error -func UnderscoreToCamelCase(s string) string -func ValidateMap(inputMap map[string]interface{}, validationMap map[string]interface{}) (bool, error) -func ValidateStruct(s interface{}) (bool, error) -func WhiteList(str, chars string) string -type ConditionIterator -type CustomTypeValidator -type Error -func (e Error) Error() string -type Errors -func (es Errors) Error() string -func (es Errors) Errors() []error -type ISO3166Entry -type ISO693Entry -type InterfaceParamValidator -type Iterator -type ParamValidator -type ResultIterator -type UnsupportedTypeError -func (e *UnsupportedTypeError) Error() string -type Validator -``` - -#### Examples -###### IsURL -```go -println(govalidator.IsURL(`http://user@pass:domain.com/path/page`)) -``` -###### IsType -```go -println(govalidator.IsType("Bob", "string")) -println(govalidator.IsType(1, "int")) -i := 1 -println(govalidator.IsType(&i, "*int")) -``` - -IsType can be used through the tag `type` which is essential for map validation: -```go -type User struct { - Name string `valid:"type(string)"` - Age int `valid:"type(int)"` - Meta interface{} `valid:"type(string)"` -} -result, err := govalidator.ValidateStruct(User{"Bob", 20, "meta"}) -if err != nil { - println("error: " + err.Error()) -} -println(result) -``` -###### ToString -```go -type User struct { - FirstName string - LastName string -} - -str := govalidator.ToString(&User{"John", "Juan"}) -println(str) -``` -###### Each, Map, Filter, Count for slices -Each iterates over the slice/array and calls Iterator for every item -```go -data := []interface{}{1, 2, 3, 4, 5} -var fn govalidator.Iterator = func(value interface{}, index int) { - println(value.(int)) -} -govalidator.Each(data, fn) -``` -```go -data := []interface{}{1, 2, 3, 4, 5} -var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} { - return value.(int) * 3 -} -_ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15} -``` -```go -data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} -var fn govalidator.ConditionIterator = func(value interface{}, index int) bool { - return value.(int)%2 == 0 -} -_ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10} -_ = govalidator.Count(data, fn) // result = 5 -``` -###### ValidateStruct [#2](https://github.com/asaskevich/govalidator/pull/2) -If you want to validate structs, you can use tag `valid` for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place `-` in your tag. If you need a validator that is not on the list below, you can add it like this: -```go -govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool { - return str == "duck" -}) -``` -For completely custom validators (interface-based), see below. - -Here is a list of available validators for struct fields (validator - used function): -```go -"email": IsEmail, -"url": IsURL, -"dialstring": IsDialString, -"requrl": IsRequestURL, -"requri": IsRequestURI, -"alpha": IsAlpha, -"utfletter": IsUTFLetter, -"alphanum": IsAlphanumeric, -"utfletternum": IsUTFLetterNumeric, -"numeric": IsNumeric, -"utfnumeric": IsUTFNumeric, -"utfdigit": IsUTFDigit, -"hexadecimal": IsHexadecimal, -"hexcolor": IsHexcolor, -"rgbcolor": IsRGBcolor, -"lowercase": IsLowerCase, -"uppercase": IsUpperCase, -"int": IsInt, -"float": IsFloat, -"null": IsNull, -"uuid": IsUUID, -"uuidv3": IsUUIDv3, -"uuidv4": IsUUIDv4, -"uuidv5": IsUUIDv5, -"creditcard": IsCreditCard, -"isbn10": IsISBN10, -"isbn13": IsISBN13, -"json": IsJSON, -"multibyte": IsMultibyte, -"ascii": IsASCII, -"printableascii": IsPrintableASCII, -"fullwidth": IsFullWidth, -"halfwidth": IsHalfWidth, -"variablewidth": IsVariableWidth, -"base64": IsBase64, -"datauri": IsDataURI, -"ip": IsIP, -"port": IsPort, -"ipv4": IsIPv4, -"ipv6": IsIPv6, -"dns": IsDNSName, -"host": IsHost, -"mac": IsMAC, -"latitude": IsLatitude, -"longitude": IsLongitude, -"ssn": IsSSN, -"semver": IsSemver, -"rfc3339": IsRFC3339, -"rfc3339WithoutZone": IsRFC3339WithoutZone, -"ISO3166Alpha2": IsISO3166Alpha2, -"ISO3166Alpha3": IsISO3166Alpha3, -``` -Validators with parameters - -```go -"range(min|max)": Range, -"length(min|max)": ByteLength, -"runelength(min|max)": RuneLength, -"stringlength(min|max)": StringLength, -"matches(pattern)": StringMatches, -"in(string1|string2|...|stringN)": IsIn, -"rsapub(keylength)" : IsRsaPub, -"minstringlength(int): MinStringLength, -"maxstringlength(int): MaxStringLength, -``` -Validators with parameters for any type - -```go -"type(type)": IsType, -``` - -And here is small example of usage: -```go -type Post struct { - Title string `valid:"alphanum,required"` - Message string `valid:"duck,ascii"` - Message2 string `valid:"animal(dog)"` - AuthorIP string `valid:"ipv4"` - Date string `valid:"-"` -} -post := &Post{ - Title: "My Example Post", - Message: "duck", - Message2: "dog", - AuthorIP: "123.234.54.3", -} - -// Add your own struct validation tags -govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool { - return str == "duck" -}) - -// Add your own struct validation tags with parameter -govalidator.ParamTagMap["animal"] = govalidator.ParamValidator(func(str string, params ...string) bool { - species := params[0] - return str == species -}) -govalidator.ParamTagRegexMap["animal"] = regexp.MustCompile("^animal\\((\\w+)\\)$") - -result, err := govalidator.ValidateStruct(post) -if err != nil { - println("error: " + err.Error()) -} -println(result) -``` -###### ValidateMap [#2](https://github.com/asaskevich/govalidator/pull/338) -If you want to validate maps, you can use the map to be validated and a validation map that contain the same tags used in ValidateStruct, both maps have to be in the form `map[string]interface{}` - -So here is small example of usage: -```go -var mapTemplate = map[string]interface{}{ - "name":"required,alpha", - "family":"required,alpha", - "email":"required,email", - "cell-phone":"numeric", - "address":map[string]interface{}{ - "line1":"required,alphanum", - "line2":"alphanum", - "postal-code":"numeric", - }, -} - -var inputMap = map[string]interface{}{ - "name":"Bob", - "family":"Smith", - "email":"foo@bar.baz", - "address":map[string]interface{}{ - "line1":"", - "line2":"", - "postal-code":"", - }, -} - -result, err := govalidator.ValidateMap(inputMap, mapTemplate) -if err != nil { - println("error: " + err.Error()) -} -println(result) -``` - -###### WhiteList -```go -// Remove all characters from string ignoring characters between "a" and "z" -println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa") -``` - -###### Custom validation functions -Custom validation using your own domain specific validators is also available - here's an example of how to use it: -```go -import "github.com/asaskevich/govalidator" - -type CustomByteArray [6]byte // custom types are supported and can be validated - -type StructWithCustomByteArray struct { - ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` // multiple custom validators are possible as well and will be evaluated in sequence - Email string `valid:"email"` - CustomMinLength int `valid:"-"` -} - -govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, context interface{}) bool { - switch v := context.(type) { // you can type switch on the context interface being validated - case StructWithCustomByteArray: - // you can check and validate against some other field in the context, - // return early or not validate against the context at all – your choice - case SomeOtherType: - // ... - default: - // expecting some other type? Throw/panic here or continue - } - - switch v := i.(type) { // type switch on the struct field being validated - case CustomByteArray: - for _, e := range v { // this validator checks that the byte array is not empty, i.e. not all zeroes - if e != 0 { - return true - } - } - } - return false -}) -govalidator.CustomTypeTagMap.Set("customMinLengthValidator", func(i interface{}, context interface{}) bool { - switch v := context.(type) { // this validates a field against the value in another field, i.e. dependent validation - case StructWithCustomByteArray: - return len(v.ID) >= v.CustomMinLength - } - return false -}) -``` - -###### Loop over Error() -By default .Error() returns all errors in a single String. To access each error you can do this: -```go - if err != nil { - errs := err.(govalidator.Errors).Errors() - for _, e := range errs { - fmt.Println(e.Error()) - } - } -``` - -###### Custom error messages -Custom error messages are supported via annotations by adding the `~` separator - here's an example of how to use it: -```go -type Ticket struct { - Id int64 `json:"id"` - FirstName string `json:"firstname" valid:"required~First name is blank"` -} -``` - -#### Notes -Documentation is available here: [godoc.org](https://godoc.org/github.com/asaskevich/govalidator). -Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator). - -#### Support -If you do have a contribution to the package, feel free to create a Pull Request or an Issue. - -#### What to contribute -If you don't know what to do, there are some features and functions that need to be done - -- [ ] Refactor code -- [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check -- [ ] Create actual list of contributors and projects that currently using this package -- [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues) -- [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions) -- [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new -- [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc -- [x] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224) -- [ ] Implement fuzzing testing -- [ ] Implement some struct/map/array utilities -- [ ] Implement map/array validation -- [ ] Implement benchmarking -- [ ] Implement batch of examples -- [ ] Look at forks for new features and fixes - -#### Advice -Feel free to create what you want, but keep in mind when you implement new features: -- Code must be clear and readable, names of variables/constants clearly describes what they are doing -- Public functions must be documented and described in source file and added to README.md to the list of available functions -- There are must be unit-tests for any new functions and improvements - -## Credits -### Contributors - -This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. - -#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors) -* [Daniel Lohse](https://github.com/annismckenzie) -* [Attila Oláh](https://github.com/attilaolah) -* [Daniel Korner](https://github.com/Dadie) -* [Steven Wilkin](https://github.com/stevenwilkin) -* [Deiwin Sarjas](https://github.com/deiwin) -* [Noah Shibley](https://github.com/slugmobile) -* [Nathan Davies](https://github.com/nathj07) -* [Matt Sanford](https://github.com/mzsanford) -* [Simon ccl1115](https://github.com/ccl1115) - - - - -### Backers - -Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/govalidator#backer)] - - - - -### Sponsors - -Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/govalidator#sponsor)] - - - - - - - - - - - - - - - -## License -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator?ref=badge_large) diff --git a/vendor/github.com/asaskevich/govalidator/arrays.go b/vendor/github.com/asaskevich/govalidator/arrays.go deleted file mode 100644 index 3e1da7cb..00000000 --- a/vendor/github.com/asaskevich/govalidator/arrays.go +++ /dev/null @@ -1,87 +0,0 @@ -package govalidator - -// Iterator is the function that accepts element of slice/array and its index -type Iterator func(interface{}, int) - -// ResultIterator is the function that accepts element of slice/array and its index and returns any result -type ResultIterator func(interface{}, int) interface{} - -// ConditionIterator is the function that accepts element of slice/array and its index and returns boolean -type ConditionIterator func(interface{}, int) bool - -// ReduceIterator is the function that accepts two element of slice/array and returns result of merging those values -type ReduceIterator func(interface{}, interface{}) interface{} - -// Some validates that any item of array corresponds to ConditionIterator. Returns boolean. -func Some(array []interface{}, iterator ConditionIterator) bool { - res := false - for index, data := range array { - res = res || iterator(data, index) - } - return res -} - -// Every validates that every item of array corresponds to ConditionIterator. Returns boolean. -func Every(array []interface{}, iterator ConditionIterator) bool { - res := true - for index, data := range array { - res = res && iterator(data, index) - } - return res -} - -// Reduce boils down a list of values into a single value by ReduceIterator -func Reduce(array []interface{}, iterator ReduceIterator, initialValue interface{}) interface{} { - for _, data := range array { - initialValue = iterator(initialValue, data) - } - return initialValue -} - -// Each iterates over the slice and apply Iterator to every item -func Each(array []interface{}, iterator Iterator) { - for index, data := range array { - iterator(data, index) - } -} - -// Map iterates over the slice and apply ResultIterator to every item. Returns new slice as a result. -func Map(array []interface{}, iterator ResultIterator) []interface{} { - var result = make([]interface{}, len(array)) - for index, data := range array { - result[index] = iterator(data, index) - } - return result -} - -// Find iterates over the slice and apply ConditionIterator to every item. Returns first item that meet ConditionIterator or nil otherwise. -func Find(array []interface{}, iterator ConditionIterator) interface{} { - for index, data := range array { - if iterator(data, index) { - return data - } - } - return nil -} - -// Filter iterates over the slice and apply ConditionIterator to every item. Returns new slice. -func Filter(array []interface{}, iterator ConditionIterator) []interface{} { - var result = make([]interface{}, 0) - for index, data := range array { - if iterator(data, index) { - result = append(result, data) - } - } - return result -} - -// Count iterates over the slice and apply ConditionIterator to every item. Returns count of items that meets ConditionIterator. -func Count(array []interface{}, iterator ConditionIterator) int { - count := 0 - for index, data := range array { - if iterator(data, index) { - count = count + 1 - } - } - return count -} diff --git a/vendor/github.com/asaskevich/govalidator/converter.go b/vendor/github.com/asaskevich/govalidator/converter.go deleted file mode 100644 index d68e990f..00000000 --- a/vendor/github.com/asaskevich/govalidator/converter.go +++ /dev/null @@ -1,81 +0,0 @@ -package govalidator - -import ( - "encoding/json" - "fmt" - "reflect" - "strconv" -) - -// ToString convert the input to a string. -func ToString(obj interface{}) string { - res := fmt.Sprintf("%v", obj) - return res -} - -// ToJSON convert the input to a valid JSON string -func ToJSON(obj interface{}) (string, error) { - res, err := json.Marshal(obj) - if err != nil { - res = []byte("") - } - return string(res), err -} - -// ToFloat convert the input string to a float, or 0.0 if the input is not a float. -func ToFloat(value interface{}) (res float64, err error) { - val := reflect.ValueOf(value) - - switch value.(type) { - case int, int8, int16, int32, int64: - res = float64(val.Int()) - case uint, uint8, uint16, uint32, uint64: - res = float64(val.Uint()) - case float32, float64: - res = val.Float() - case string: - res, err = strconv.ParseFloat(val.String(), 64) - if err != nil { - res = 0 - } - default: - err = fmt.Errorf("ToInt: unknown interface type %T", value) - res = 0 - } - - return -} - -// ToInt convert the input string or any int type to an integer type 64, or 0 if the input is not an integer. -func ToInt(value interface{}) (res int64, err error) { - val := reflect.ValueOf(value) - - switch value.(type) { - case int, int8, int16, int32, int64: - res = val.Int() - case uint, uint8, uint16, uint32, uint64: - res = int64(val.Uint()) - case float32, float64: - res = int64(val.Float()) - case string: - if IsInt(val.String()) { - res, err = strconv.ParseInt(val.String(), 0, 64) - if err != nil { - res = 0 - } - } else { - err = fmt.Errorf("ToInt: invalid numeric format %g", value) - res = 0 - } - default: - err = fmt.Errorf("ToInt: unknown interface type %T", value) - res = 0 - } - - return -} - -// ToBoolean convert the input string to a boolean. -func ToBoolean(str string) (bool, error) { - return strconv.ParseBool(str) -} diff --git a/vendor/github.com/asaskevich/govalidator/doc.go b/vendor/github.com/asaskevich/govalidator/doc.go deleted file mode 100644 index 55dce62d..00000000 --- a/vendor/github.com/asaskevich/govalidator/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -package govalidator - -// A package of validators and sanitizers for strings, structures and collections. diff --git a/vendor/github.com/asaskevich/govalidator/error.go b/vendor/github.com/asaskevich/govalidator/error.go deleted file mode 100644 index 1da2336f..00000000 --- a/vendor/github.com/asaskevich/govalidator/error.go +++ /dev/null @@ -1,47 +0,0 @@ -package govalidator - -import ( - "sort" - "strings" -) - -// Errors is an array of multiple errors and conforms to the error interface. -type Errors []error - -// Errors returns itself. -func (es Errors) Errors() []error { - return es -} - -func (es Errors) Error() string { - var errs []string - for _, e := range es { - errs = append(errs, e.Error()) - } - sort.Strings(errs) - return strings.Join(errs, ";") -} - -// Error encapsulates a name, an error and whether there's a custom error message or not. -type Error struct { - Name string - Err error - CustomErrorMessageExists bool - - // Validator indicates the name of the validator that failed - Validator string - Path []string -} - -func (e Error) Error() string { - if e.CustomErrorMessageExists { - return e.Err.Error() - } - - errName := e.Name - if len(e.Path) > 0 { - errName = strings.Join(append(e.Path, e.Name), ".") - } - - return errName + ": " + e.Err.Error() -} diff --git a/vendor/github.com/asaskevich/govalidator/go.mod b/vendor/github.com/asaskevich/govalidator/go.mod deleted file mode 100644 index 42d5b1f6..00000000 --- a/vendor/github.com/asaskevich/govalidator/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/asaskevich/govalidator - -go 1.13 diff --git a/vendor/github.com/asaskevich/govalidator/numerics.go b/vendor/github.com/asaskevich/govalidator/numerics.go deleted file mode 100644 index 5041d9e8..00000000 --- a/vendor/github.com/asaskevich/govalidator/numerics.go +++ /dev/null @@ -1,100 +0,0 @@ -package govalidator - -import ( - "math" -) - -// Abs returns absolute value of number -func Abs(value float64) float64 { - return math.Abs(value) -} - -// Sign returns signum of number: 1 in case of value > 0, -1 in case of value < 0, 0 otherwise -func Sign(value float64) float64 { - if value > 0 { - return 1 - } else if value < 0 { - return -1 - } else { - return 0 - } -} - -// IsNegative returns true if value < 0 -func IsNegative(value float64) bool { - return value < 0 -} - -// IsPositive returns true if value > 0 -func IsPositive(value float64) bool { - return value > 0 -} - -// IsNonNegative returns true if value >= 0 -func IsNonNegative(value float64) bool { - return value >= 0 -} - -// IsNonPositive returns true if value <= 0 -func IsNonPositive(value float64) bool { - return value <= 0 -} - -// InRangeInt returns true if value lies between left and right border -func InRangeInt(value, left, right interface{}) bool { - value64, _ := ToInt(value) - left64, _ := ToInt(left) - right64, _ := ToInt(right) - if left64 > right64 { - left64, right64 = right64, left64 - } - return value64 >= left64 && value64 <= right64 -} - -// InRangeFloat32 returns true if value lies between left and right border -func InRangeFloat32(value, left, right float32) bool { - if left > right { - left, right = right, left - } - return value >= left && value <= right -} - -// InRangeFloat64 returns true if value lies between left and right border -func InRangeFloat64(value, left, right float64) bool { - if left > right { - left, right = right, left - } - return value >= left && value <= right -} - -// InRange returns true if value lies between left and right border, generic type to handle int, float32, float64 and string. -// All types must the same type. -// False if value doesn't lie in range or if it incompatible or not comparable -func InRange(value interface{}, left interface{}, right interface{}) bool { - switch value.(type) { - case int: - intValue, _ := ToInt(value) - intLeft, _ := ToInt(left) - intRight, _ := ToInt(right) - return InRangeInt(intValue, intLeft, intRight) - case float32, float64: - intValue, _ := ToFloat(value) - intLeft, _ := ToFloat(left) - intRight, _ := ToFloat(right) - return InRangeFloat64(intValue, intLeft, intRight) - case string: - return value.(string) >= left.(string) && value.(string) <= right.(string) - default: - return false - } -} - -// IsWhole returns true if value is whole number -func IsWhole(value float64) bool { - return math.Remainder(value, 1) == 0 -} - -// IsNatural returns true if value is natural number (positive and whole) -func IsNatural(value float64) bool { - return IsWhole(value) && IsPositive(value) -} diff --git a/vendor/github.com/asaskevich/govalidator/patterns.go b/vendor/github.com/asaskevich/govalidator/patterns.go deleted file mode 100644 index 106ed94f..00000000 --- a/vendor/github.com/asaskevich/govalidator/patterns.go +++ /dev/null @@ -1,107 +0,0 @@ -package govalidator - -import "regexp" - -// Basic regular expressions for validating strings -const ( - Email string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$" - CreditCard string = "^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$" - ISBN10 string = "^(?:[0-9]{9}X|[0-9]{10})$" - ISBN13 string = "^(?:[0-9]{13})$" - UUID3 string = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$" - UUID4 string = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" - UUID5 string = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" - UUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" - Alpha string = "^[a-zA-Z]+$" - Alphanumeric string = "^[a-zA-Z0-9]+$" - Numeric string = "^[0-9]+$" - Int string = "^(?:[-+]?(?:0|[1-9][0-9]*))$" - Float string = "^(?:[-+]?(?:[0-9]+))?(?:\\.[0-9]*)?(?:[eE][\\+\\-]?(?:[0-9]+))?$" - Hexadecimal string = "^[0-9a-fA-F]+$" - Hexcolor string = "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$" - RGBcolor string = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$" - ASCII string = "^[\x00-\x7F]+$" - Multibyte string = "[^\x00-\x7F]" - FullWidth string = "[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]" - HalfWidth string = "[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]" - Base64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$" - PrintableASCII string = "^[\x20-\x7E]+$" - DataURI string = "^data:.+\\/(.+);base64$" - MagnetURI string = "^magnet:\\?xt=urn:[a-zA-Z0-9]+:[a-zA-Z0-9]{32,40}&dn=.+&tr=.+$" - Latitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$" - Longitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$" - DNSName string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$` - IP string = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))` - URLSchema string = `((ftp|tcp|udp|wss?|https?):\/\/)` - URLUsername string = `(\S+(:\S*)?@)` - URLPath string = `((\/|\?|#)[^\s]*)` - URLPort string = `(:(\d{1,5}))` - URLIP string = `([1-9]\d?|1\d\d|2[01]\d|22[0-3]|24\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-5]))` - URLSubdomain string = `((www\.)|([a-zA-Z0-9]+([-_\.]?[a-zA-Z0-9])*[a-zA-Z0-9]\.[a-zA-Z0-9]+))` - URL = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$` - SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$` - WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$` - UnixPath string = `^(/[^/\x00]*)+/?$` - Semver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$" - tagName string = "valid" - hasLowerCase string = ".*[[:lower:]]" - hasUpperCase string = ".*[[:upper:]]" - hasWhitespace string = ".*[[:space:]]" - hasWhitespaceOnly string = "^[[:space:]]+$" - IMEI string = "^[0-9a-f]{14}$|^\\d{15}$|^\\d{18}$" - IMSI string = "^\\d{14,15}$" -) - -// Used by IsFilePath func -const ( - // Unknown is unresolved OS type - Unknown = iota - // Win is Windows type - Win - // Unix is *nix OS types - Unix -) - -var ( - userRegexp = regexp.MustCompile("^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+$") - hostRegexp = regexp.MustCompile("^[^\\s]+\\.[^\\s]+$") - userDotRegexp = regexp.MustCompile("(^[.]{1})|([.]{1}$)|([.]{2,})") - rxEmail = regexp.MustCompile(Email) - rxCreditCard = regexp.MustCompile(CreditCard) - rxISBN10 = regexp.MustCompile(ISBN10) - rxISBN13 = regexp.MustCompile(ISBN13) - rxUUID3 = regexp.MustCompile(UUID3) - rxUUID4 = regexp.MustCompile(UUID4) - rxUUID5 = regexp.MustCompile(UUID5) - rxUUID = regexp.MustCompile(UUID) - rxAlpha = regexp.MustCompile(Alpha) - rxAlphanumeric = regexp.MustCompile(Alphanumeric) - rxNumeric = regexp.MustCompile(Numeric) - rxInt = regexp.MustCompile(Int) - rxFloat = regexp.MustCompile(Float) - rxHexadecimal = regexp.MustCompile(Hexadecimal) - rxHexcolor = regexp.MustCompile(Hexcolor) - rxRGBcolor = regexp.MustCompile(RGBcolor) - rxASCII = regexp.MustCompile(ASCII) - rxPrintableASCII = regexp.MustCompile(PrintableASCII) - rxMultibyte = regexp.MustCompile(Multibyte) - rxFullWidth = regexp.MustCompile(FullWidth) - rxHalfWidth = regexp.MustCompile(HalfWidth) - rxBase64 = regexp.MustCompile(Base64) - rxDataURI = regexp.MustCompile(DataURI) - rxMagnetURI = regexp.MustCompile(MagnetURI) - rxLatitude = regexp.MustCompile(Latitude) - rxLongitude = regexp.MustCompile(Longitude) - rxDNSName = regexp.MustCompile(DNSName) - rxURL = regexp.MustCompile(URL) - rxSSN = regexp.MustCompile(SSN) - rxWinPath = regexp.MustCompile(WinPath) - rxUnixPath = regexp.MustCompile(UnixPath) - rxSemver = regexp.MustCompile(Semver) - rxHasLowerCase = regexp.MustCompile(hasLowerCase) - rxHasUpperCase = regexp.MustCompile(hasUpperCase) - rxHasWhitespace = regexp.MustCompile(hasWhitespace) - rxHasWhitespaceOnly = regexp.MustCompile(hasWhitespaceOnly) - rxIMEI = regexp.MustCompile(IMEI) - rxIMSI = regexp.MustCompile(IMSI) -) diff --git a/vendor/github.com/asaskevich/govalidator/types.go b/vendor/github.com/asaskevich/govalidator/types.go deleted file mode 100644 index 54218bf0..00000000 --- a/vendor/github.com/asaskevich/govalidator/types.go +++ /dev/null @@ -1,655 +0,0 @@ -package govalidator - -import ( - "reflect" - "regexp" - "sort" - "sync" -) - -// Validator is a wrapper for a validator function that returns bool and accepts string. -type Validator func(str string) bool - -// CustomTypeValidator is a wrapper for validator functions that returns bool and accepts any type. -// The second parameter should be the context (in the case of validating a struct: the whole object being validated). -type CustomTypeValidator func(i interface{}, o interface{}) bool - -// ParamValidator is a wrapper for validator functions that accept additional parameters. -type ParamValidator func(str string, params ...string) bool - -// InterfaceParamValidator is a wrapper for functions that accept variants parameters for an interface value -type InterfaceParamValidator func(in interface{}, params ...string) bool -type tagOptionsMap map[string]tagOption - -func (t tagOptionsMap) orderedKeys() []string { - var keys []string - for k := range t { - keys = append(keys, k) - } - - sort.Slice(keys, func(a, b int) bool { - return t[keys[a]].order < t[keys[b]].order - }) - - return keys -} - -type tagOption struct { - name string - customErrorMessage string - order int -} - -// UnsupportedTypeError is a wrapper for reflect.Type -type UnsupportedTypeError struct { - Type reflect.Type -} - -// stringValues is a slice of reflect.Value holding *reflect.StringValue. -// It implements the methods to sort by string. -type stringValues []reflect.Value - -// InterfaceParamTagMap is a map of functions accept variants parameters for an interface value -var InterfaceParamTagMap = map[string]InterfaceParamValidator{ - "type": IsType, -} - -// InterfaceParamTagRegexMap maps interface param tags to their respective regexes. -var InterfaceParamTagRegexMap = map[string]*regexp.Regexp{ - "type": regexp.MustCompile(`^type\((.*)\)$`), -} - -// ParamTagMap is a map of functions accept variants parameters -var ParamTagMap = map[string]ParamValidator{ - "length": ByteLength, - "range": Range, - "runelength": RuneLength, - "stringlength": StringLength, - "matches": StringMatches, - "in": IsInRaw, - "rsapub": IsRsaPub, - "minstringlength": MinStringLength, - "maxstringlength": MaxStringLength, -} - -// ParamTagRegexMap maps param tags to their respective regexes. -var ParamTagRegexMap = map[string]*regexp.Regexp{ - "range": regexp.MustCompile("^range\\((\\d+)\\|(\\d+)\\)$"), - "length": regexp.MustCompile("^length\\((\\d+)\\|(\\d+)\\)$"), - "runelength": regexp.MustCompile("^runelength\\((\\d+)\\|(\\d+)\\)$"), - "stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"), - "in": regexp.MustCompile(`^in\((.*)\)`), - "matches": regexp.MustCompile(`^matches\((.+)\)$`), - "rsapub": regexp.MustCompile("^rsapub\\((\\d+)\\)$"), - "minstringlength": regexp.MustCompile("^minstringlength\\((\\d+)\\)$"), - "maxstringlength": regexp.MustCompile("^maxstringlength\\((\\d+)\\)$"), -} - -type customTypeTagMap struct { - validators map[string]CustomTypeValidator - - sync.RWMutex -} - -func (tm *customTypeTagMap) Get(name string) (CustomTypeValidator, bool) { - tm.RLock() - defer tm.RUnlock() - v, ok := tm.validators[name] - return v, ok -} - -func (tm *customTypeTagMap) Set(name string, ctv CustomTypeValidator) { - tm.Lock() - defer tm.Unlock() - tm.validators[name] = ctv -} - -// CustomTypeTagMap is a map of functions that can be used as tags for ValidateStruct function. -// Use this to validate compound or custom types that need to be handled as a whole, e.g. -// `type UUID [16]byte` (this would be handled as an array of bytes). -var CustomTypeTagMap = &customTypeTagMap{validators: make(map[string]CustomTypeValidator)} - -// TagMap is a map of functions, that can be used as tags for ValidateStruct function. -var TagMap = map[string]Validator{ - "email": IsEmail, - "url": IsURL, - "dialstring": IsDialString, - "requrl": IsRequestURL, - "requri": IsRequestURI, - "alpha": IsAlpha, - "utfletter": IsUTFLetter, - "alphanum": IsAlphanumeric, - "utfletternum": IsUTFLetterNumeric, - "numeric": IsNumeric, - "utfnumeric": IsUTFNumeric, - "utfdigit": IsUTFDigit, - "hexadecimal": IsHexadecimal, - "hexcolor": IsHexcolor, - "rgbcolor": IsRGBcolor, - "lowercase": IsLowerCase, - "uppercase": IsUpperCase, - "int": IsInt, - "float": IsFloat, - "null": IsNull, - "notnull": IsNotNull, - "uuid": IsUUID, - "uuidv3": IsUUIDv3, - "uuidv4": IsUUIDv4, - "uuidv5": IsUUIDv5, - "creditcard": IsCreditCard, - "isbn10": IsISBN10, - "isbn13": IsISBN13, - "json": IsJSON, - "multibyte": IsMultibyte, - "ascii": IsASCII, - "printableascii": IsPrintableASCII, - "fullwidth": IsFullWidth, - "halfwidth": IsHalfWidth, - "variablewidth": IsVariableWidth, - "base64": IsBase64, - "datauri": IsDataURI, - "ip": IsIP, - "port": IsPort, - "ipv4": IsIPv4, - "ipv6": IsIPv6, - "dns": IsDNSName, - "host": IsHost, - "mac": IsMAC, - "latitude": IsLatitude, - "longitude": IsLongitude, - "ssn": IsSSN, - "semver": IsSemver, - "rfc3339": IsRFC3339, - "rfc3339WithoutZone": IsRFC3339WithoutZone, - "ISO3166Alpha2": IsISO3166Alpha2, - "ISO3166Alpha3": IsISO3166Alpha3, - "ISO4217": IsISO4217, - "IMEI": IsIMEI, -} - -// ISO3166Entry stores country codes -type ISO3166Entry struct { - EnglishShortName string - FrenchShortName string - Alpha2Code string - Alpha3Code string - Numeric string -} - -//ISO3166List based on https://www.iso.org/obp/ui/#search/code/ Code Type "Officially Assigned Codes" -var ISO3166List = []ISO3166Entry{ - {"Afghanistan", "Afghanistan (l')", "AF", "AFG", "004"}, - {"Albania", "Albanie (l')", "AL", "ALB", "008"}, - {"Antarctica", "Antarctique (l')", "AQ", "ATA", "010"}, - {"Algeria", "Algérie (l')", "DZ", "DZA", "012"}, - {"American Samoa", "Samoa américaines (les)", "AS", "ASM", "016"}, - {"Andorra", "Andorre (l')", "AD", "AND", "020"}, - {"Angola", "Angola (l')", "AO", "AGO", "024"}, - {"Antigua and Barbuda", "Antigua-et-Barbuda", "AG", "ATG", "028"}, - {"Azerbaijan", "Azerbaïdjan (l')", "AZ", "AZE", "031"}, - {"Argentina", "Argentine (l')", "AR", "ARG", "032"}, - {"Australia", "Australie (l')", "AU", "AUS", "036"}, - {"Austria", "Autriche (l')", "AT", "AUT", "040"}, - {"Bahamas (the)", "Bahamas (les)", "BS", "BHS", "044"}, - {"Bahrain", "Bahreïn", "BH", "BHR", "048"}, - {"Bangladesh", "Bangladesh (le)", "BD", "BGD", "050"}, - {"Armenia", "Arménie (l')", "AM", "ARM", "051"}, - {"Barbados", "Barbade (la)", "BB", "BRB", "052"}, - {"Belgium", "Belgique (la)", "BE", "BEL", "056"}, - {"Bermuda", "Bermudes (les)", "BM", "BMU", "060"}, - {"Bhutan", "Bhoutan (le)", "BT", "BTN", "064"}, - {"Bolivia (Plurinational State of)", "Bolivie (État plurinational de)", "BO", "BOL", "068"}, - {"Bosnia and Herzegovina", "Bosnie-Herzégovine (la)", "BA", "BIH", "070"}, - {"Botswana", "Botswana (le)", "BW", "BWA", "072"}, - {"Bouvet Island", "Bouvet (l'Île)", "BV", "BVT", "074"}, - {"Brazil", "Brésil (le)", "BR", "BRA", "076"}, - {"Belize", "Belize (le)", "BZ", "BLZ", "084"}, - {"British Indian Ocean Territory (the)", "Indien (le Territoire britannique de l'océan)", "IO", "IOT", "086"}, - {"Solomon Islands", "Salomon (Îles)", "SB", "SLB", "090"}, - {"Virgin Islands (British)", "Vierges britanniques (les Îles)", "VG", "VGB", "092"}, - {"Brunei Darussalam", "Brunéi Darussalam (le)", "BN", "BRN", "096"}, - {"Bulgaria", "Bulgarie (la)", "BG", "BGR", "100"}, - {"Myanmar", "Myanmar (le)", "MM", "MMR", "104"}, - {"Burundi", "Burundi (le)", "BI", "BDI", "108"}, - {"Belarus", "Bélarus (le)", "BY", "BLR", "112"}, - {"Cambodia", "Cambodge (le)", "KH", "KHM", "116"}, - {"Cameroon", "Cameroun (le)", "CM", "CMR", "120"}, - {"Canada", "Canada (le)", "CA", "CAN", "124"}, - {"Cabo Verde", "Cabo Verde", "CV", "CPV", "132"}, - {"Cayman Islands (the)", "Caïmans (les Îles)", "KY", "CYM", "136"}, - {"Central African Republic (the)", "République centrafricaine (la)", "CF", "CAF", "140"}, - {"Sri Lanka", "Sri Lanka", "LK", "LKA", "144"}, - {"Chad", "Tchad (le)", "TD", "TCD", "148"}, - {"Chile", "Chili (le)", "CL", "CHL", "152"}, - {"China", "Chine (la)", "CN", "CHN", "156"}, - {"Taiwan (Province of China)", "Taïwan (Province de Chine)", "TW", "TWN", "158"}, - {"Christmas Island", "Christmas (l'Île)", "CX", "CXR", "162"}, - {"Cocos (Keeling) Islands (the)", "Cocos (les Îles)/ Keeling (les Îles)", "CC", "CCK", "166"}, - {"Colombia", "Colombie (la)", "CO", "COL", "170"}, - {"Comoros (the)", "Comores (les)", "KM", "COM", "174"}, - {"Mayotte", "Mayotte", "YT", "MYT", "175"}, - {"Congo (the)", "Congo (le)", "CG", "COG", "178"}, - {"Congo (the Democratic Republic of the)", "Congo (la République démocratique du)", "CD", "COD", "180"}, - {"Cook Islands (the)", "Cook (les Îles)", "CK", "COK", "184"}, - {"Costa Rica", "Costa Rica (le)", "CR", "CRI", "188"}, - {"Croatia", "Croatie (la)", "HR", "HRV", "191"}, - {"Cuba", "Cuba", "CU", "CUB", "192"}, - {"Cyprus", "Chypre", "CY", "CYP", "196"}, - {"Czech Republic (the)", "tchèque (la République)", "CZ", "CZE", "203"}, - {"Benin", "Bénin (le)", "BJ", "BEN", "204"}, - {"Denmark", "Danemark (le)", "DK", "DNK", "208"}, - {"Dominica", "Dominique (la)", "DM", "DMA", "212"}, - {"Dominican Republic (the)", "dominicaine (la République)", "DO", "DOM", "214"}, - {"Ecuador", "Équateur (l')", "EC", "ECU", "218"}, - {"El Salvador", "El Salvador", "SV", "SLV", "222"}, - {"Equatorial Guinea", "Guinée équatoriale (la)", "GQ", "GNQ", "226"}, - {"Ethiopia", "Éthiopie (l')", "ET", "ETH", "231"}, - {"Eritrea", "Érythrée (l')", "ER", "ERI", "232"}, - {"Estonia", "Estonie (l')", "EE", "EST", "233"}, - {"Faroe Islands (the)", "Féroé (les Îles)", "FO", "FRO", "234"}, - {"Falkland Islands (the) [Malvinas]", "Falkland (les Îles)/Malouines (les Îles)", "FK", "FLK", "238"}, - {"South Georgia and the South Sandwich Islands", "Géorgie du Sud-et-les Îles Sandwich du Sud (la)", "GS", "SGS", "239"}, - {"Fiji", "Fidji (les)", "FJ", "FJI", "242"}, - {"Finland", "Finlande (la)", "FI", "FIN", "246"}, - {"Åland Islands", "Åland(les Îles)", "AX", "ALA", "248"}, - {"France", "France (la)", "FR", "FRA", "250"}, - {"French Guiana", "Guyane française (la )", "GF", "GUF", "254"}, - {"French Polynesia", "Polynésie française (la)", "PF", "PYF", "258"}, - {"French Southern Territories (the)", "Terres australes françaises (les)", "TF", "ATF", "260"}, - {"Djibouti", "Djibouti", "DJ", "DJI", "262"}, - {"Gabon", "Gabon (le)", "GA", "GAB", "266"}, - {"Georgia", "Géorgie (la)", "GE", "GEO", "268"}, - {"Gambia (the)", "Gambie (la)", "GM", "GMB", "270"}, - {"Palestine, State of", "Palestine, État de", "PS", "PSE", "275"}, - {"Germany", "Allemagne (l')", "DE", "DEU", "276"}, - {"Ghana", "Ghana (le)", "GH", "GHA", "288"}, - {"Gibraltar", "Gibraltar", "GI", "GIB", "292"}, - {"Kiribati", "Kiribati", "KI", "KIR", "296"}, - {"Greece", "Grèce (la)", "GR", "GRC", "300"}, - {"Greenland", "Groenland (le)", "GL", "GRL", "304"}, - {"Grenada", "Grenade (la)", "GD", "GRD", "308"}, - {"Guadeloupe", "Guadeloupe (la)", "GP", "GLP", "312"}, - {"Guam", "Guam", "GU", "GUM", "316"}, - {"Guatemala", "Guatemala (le)", "GT", "GTM", "320"}, - {"Guinea", "Guinée (la)", "GN", "GIN", "324"}, - {"Guyana", "Guyana (le)", "GY", "GUY", "328"}, - {"Haiti", "Haïti", "HT", "HTI", "332"}, - {"Heard Island and McDonald Islands", "Heard-et-Îles MacDonald (l'Île)", "HM", "HMD", "334"}, - {"Holy See (the)", "Saint-Siège (le)", "VA", "VAT", "336"}, - {"Honduras", "Honduras (le)", "HN", "HND", "340"}, - {"Hong Kong", "Hong Kong", "HK", "HKG", "344"}, - {"Hungary", "Hongrie (la)", "HU", "HUN", "348"}, - {"Iceland", "Islande (l')", "IS", "ISL", "352"}, - {"India", "Inde (l')", "IN", "IND", "356"}, - {"Indonesia", "Indonésie (l')", "ID", "IDN", "360"}, - {"Iran (Islamic Republic of)", "Iran (République Islamique d')", "IR", "IRN", "364"}, - {"Iraq", "Iraq (l')", "IQ", "IRQ", "368"}, - {"Ireland", "Irlande (l')", "IE", "IRL", "372"}, - {"Israel", "Israël", "IL", "ISR", "376"}, - {"Italy", "Italie (l')", "IT", "ITA", "380"}, - {"Côte d'Ivoire", "Côte d'Ivoire (la)", "CI", "CIV", "384"}, - {"Jamaica", "Jamaïque (la)", "JM", "JAM", "388"}, - {"Japan", "Japon (le)", "JP", "JPN", "392"}, - {"Kazakhstan", "Kazakhstan (le)", "KZ", "KAZ", "398"}, - {"Jordan", "Jordanie (la)", "JO", "JOR", "400"}, - {"Kenya", "Kenya (le)", "KE", "KEN", "404"}, - {"Korea (the Democratic People's Republic of)", "Corée (la République populaire démocratique de)", "KP", "PRK", "408"}, - {"Korea (the Republic of)", "Corée (la République de)", "KR", "KOR", "410"}, - {"Kuwait", "Koweït (le)", "KW", "KWT", "414"}, - {"Kyrgyzstan", "Kirghizistan (le)", "KG", "KGZ", "417"}, - {"Lao People's Democratic Republic (the)", "Lao, République démocratique populaire", "LA", "LAO", "418"}, - {"Lebanon", "Liban (le)", "LB", "LBN", "422"}, - {"Lesotho", "Lesotho (le)", "LS", "LSO", "426"}, - {"Latvia", "Lettonie (la)", "LV", "LVA", "428"}, - {"Liberia", "Libéria (le)", "LR", "LBR", "430"}, - {"Libya", "Libye (la)", "LY", "LBY", "434"}, - {"Liechtenstein", "Liechtenstein (le)", "LI", "LIE", "438"}, - {"Lithuania", "Lituanie (la)", "LT", "LTU", "440"}, - {"Luxembourg", "Luxembourg (le)", "LU", "LUX", "442"}, - {"Macao", "Macao", "MO", "MAC", "446"}, - {"Madagascar", "Madagascar", "MG", "MDG", "450"}, - {"Malawi", "Malawi (le)", "MW", "MWI", "454"}, - {"Malaysia", "Malaisie (la)", "MY", "MYS", "458"}, - {"Maldives", "Maldives (les)", "MV", "MDV", "462"}, - {"Mali", "Mali (le)", "ML", "MLI", "466"}, - {"Malta", "Malte", "MT", "MLT", "470"}, - {"Martinique", "Martinique (la)", "MQ", "MTQ", "474"}, - {"Mauritania", "Mauritanie (la)", "MR", "MRT", "478"}, - {"Mauritius", "Maurice", "MU", "MUS", "480"}, - {"Mexico", "Mexique (le)", "MX", "MEX", "484"}, - {"Monaco", "Monaco", "MC", "MCO", "492"}, - {"Mongolia", "Mongolie (la)", "MN", "MNG", "496"}, - {"Moldova (the Republic of)", "Moldova , République de", "MD", "MDA", "498"}, - {"Montenegro", "Monténégro (le)", "ME", "MNE", "499"}, - {"Montserrat", "Montserrat", "MS", "MSR", "500"}, - {"Morocco", "Maroc (le)", "MA", "MAR", "504"}, - {"Mozambique", "Mozambique (le)", "MZ", "MOZ", "508"}, - {"Oman", "Oman", "OM", "OMN", "512"}, - {"Namibia", "Namibie (la)", "NA", "NAM", "516"}, - {"Nauru", "Nauru", "NR", "NRU", "520"}, - {"Nepal", "Népal (le)", "NP", "NPL", "524"}, - {"Netherlands (the)", "Pays-Bas (les)", "NL", "NLD", "528"}, - {"Curaçao", "Curaçao", "CW", "CUW", "531"}, - {"Aruba", "Aruba", "AW", "ABW", "533"}, - {"Sint Maarten (Dutch part)", "Saint-Martin (partie néerlandaise)", "SX", "SXM", "534"}, - {"Bonaire, Sint Eustatius and Saba", "Bonaire, Saint-Eustache et Saba", "BQ", "BES", "535"}, - {"New Caledonia", "Nouvelle-Calédonie (la)", "NC", "NCL", "540"}, - {"Vanuatu", "Vanuatu (le)", "VU", "VUT", "548"}, - {"New Zealand", "Nouvelle-Zélande (la)", "NZ", "NZL", "554"}, - {"Nicaragua", "Nicaragua (le)", "NI", "NIC", "558"}, - {"Niger (the)", "Niger (le)", "NE", "NER", "562"}, - {"Nigeria", "Nigéria (le)", "NG", "NGA", "566"}, - {"Niue", "Niue", "NU", "NIU", "570"}, - {"Norfolk Island", "Norfolk (l'Île)", "NF", "NFK", "574"}, - {"Norway", "Norvège (la)", "NO", "NOR", "578"}, - {"Northern Mariana Islands (the)", "Mariannes du Nord (les Îles)", "MP", "MNP", "580"}, - {"United States Minor Outlying Islands (the)", "Îles mineures éloignées des États-Unis (les)", "UM", "UMI", "581"}, - {"Micronesia (Federated States of)", "Micronésie (États fédérés de)", "FM", "FSM", "583"}, - {"Marshall Islands (the)", "Marshall (Îles)", "MH", "MHL", "584"}, - {"Palau", "Palaos (les)", "PW", "PLW", "585"}, - {"Pakistan", "Pakistan (le)", "PK", "PAK", "586"}, - {"Panama", "Panama (le)", "PA", "PAN", "591"}, - {"Papua New Guinea", "Papouasie-Nouvelle-Guinée (la)", "PG", "PNG", "598"}, - {"Paraguay", "Paraguay (le)", "PY", "PRY", "600"}, - {"Peru", "Pérou (le)", "PE", "PER", "604"}, - {"Philippines (the)", "Philippines (les)", "PH", "PHL", "608"}, - {"Pitcairn", "Pitcairn", "PN", "PCN", "612"}, - {"Poland", "Pologne (la)", "PL", "POL", "616"}, - {"Portugal", "Portugal (le)", "PT", "PRT", "620"}, - {"Guinea-Bissau", "Guinée-Bissau (la)", "GW", "GNB", "624"}, - {"Timor-Leste", "Timor-Leste (le)", "TL", "TLS", "626"}, - {"Puerto Rico", "Porto Rico", "PR", "PRI", "630"}, - {"Qatar", "Qatar (le)", "QA", "QAT", "634"}, - {"Réunion", "Réunion (La)", "RE", "REU", "638"}, - {"Romania", "Roumanie (la)", "RO", "ROU", "642"}, - {"Russian Federation (the)", "Russie (la Fédération de)", "RU", "RUS", "643"}, - {"Rwanda", "Rwanda (le)", "RW", "RWA", "646"}, - {"Saint Barthélemy", "Saint-Barthélemy", "BL", "BLM", "652"}, - {"Saint Helena, Ascension and Tristan da Cunha", "Sainte-Hélène, Ascension et Tristan da Cunha", "SH", "SHN", "654"}, - {"Saint Kitts and Nevis", "Saint-Kitts-et-Nevis", "KN", "KNA", "659"}, - {"Anguilla", "Anguilla", "AI", "AIA", "660"}, - {"Saint Lucia", "Sainte-Lucie", "LC", "LCA", "662"}, - {"Saint Martin (French part)", "Saint-Martin (partie française)", "MF", "MAF", "663"}, - {"Saint Pierre and Miquelon", "Saint-Pierre-et-Miquelon", "PM", "SPM", "666"}, - {"Saint Vincent and the Grenadines", "Saint-Vincent-et-les Grenadines", "VC", "VCT", "670"}, - {"San Marino", "Saint-Marin", "SM", "SMR", "674"}, - {"Sao Tome and Principe", "Sao Tomé-et-Principe", "ST", "STP", "678"}, - {"Saudi Arabia", "Arabie saoudite (l')", "SA", "SAU", "682"}, - {"Senegal", "Sénégal (le)", "SN", "SEN", "686"}, - {"Serbia", "Serbie (la)", "RS", "SRB", "688"}, - {"Seychelles", "Seychelles (les)", "SC", "SYC", "690"}, - {"Sierra Leone", "Sierra Leone (la)", "SL", "SLE", "694"}, - {"Singapore", "Singapour", "SG", "SGP", "702"}, - {"Slovakia", "Slovaquie (la)", "SK", "SVK", "703"}, - {"Viet Nam", "Viet Nam (le)", "VN", "VNM", "704"}, - {"Slovenia", "Slovénie (la)", "SI", "SVN", "705"}, - {"Somalia", "Somalie (la)", "SO", "SOM", "706"}, - {"South Africa", "Afrique du Sud (l')", "ZA", "ZAF", "710"}, - {"Zimbabwe", "Zimbabwe (le)", "ZW", "ZWE", "716"}, - {"Spain", "Espagne (l')", "ES", "ESP", "724"}, - {"South Sudan", "Soudan du Sud (le)", "SS", "SSD", "728"}, - {"Sudan (the)", "Soudan (le)", "SD", "SDN", "729"}, - {"Western Sahara*", "Sahara occidental (le)*", "EH", "ESH", "732"}, - {"Suriname", "Suriname (le)", "SR", "SUR", "740"}, - {"Svalbard and Jan Mayen", "Svalbard et l'Île Jan Mayen (le)", "SJ", "SJM", "744"}, - {"Swaziland", "Swaziland (le)", "SZ", "SWZ", "748"}, - {"Sweden", "Suède (la)", "SE", "SWE", "752"}, - {"Switzerland", "Suisse (la)", "CH", "CHE", "756"}, - {"Syrian Arab Republic", "République arabe syrienne (la)", "SY", "SYR", "760"}, - {"Tajikistan", "Tadjikistan (le)", "TJ", "TJK", "762"}, - {"Thailand", "Thaïlande (la)", "TH", "THA", "764"}, - {"Togo", "Togo (le)", "TG", "TGO", "768"}, - {"Tokelau", "Tokelau (les)", "TK", "TKL", "772"}, - {"Tonga", "Tonga (les)", "TO", "TON", "776"}, - {"Trinidad and Tobago", "Trinité-et-Tobago (la)", "TT", "TTO", "780"}, - {"United Arab Emirates (the)", "Émirats arabes unis (les)", "AE", "ARE", "784"}, - {"Tunisia", "Tunisie (la)", "TN", "TUN", "788"}, - {"Turkey", "Turquie (la)", "TR", "TUR", "792"}, - {"Turkmenistan", "Turkménistan (le)", "TM", "TKM", "795"}, - {"Turks and Caicos Islands (the)", "Turks-et-Caïcos (les Îles)", "TC", "TCA", "796"}, - {"Tuvalu", "Tuvalu (les)", "TV", "TUV", "798"}, - {"Uganda", "Ouganda (l')", "UG", "UGA", "800"}, - {"Ukraine", "Ukraine (l')", "UA", "UKR", "804"}, - {"Macedonia (the former Yugoslav Republic of)", "Macédoine (l'ex‑République yougoslave de)", "MK", "MKD", "807"}, - {"Egypt", "Égypte (l')", "EG", "EGY", "818"}, - {"United Kingdom of Great Britain and Northern Ireland (the)", "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord (le)", "GB", "GBR", "826"}, - {"Guernsey", "Guernesey", "GG", "GGY", "831"}, - {"Jersey", "Jersey", "JE", "JEY", "832"}, - {"Isle of Man", "Île de Man", "IM", "IMN", "833"}, - {"Tanzania, United Republic of", "Tanzanie, République-Unie de", "TZ", "TZA", "834"}, - {"United States of America (the)", "États-Unis d'Amérique (les)", "US", "USA", "840"}, - {"Virgin Islands (U.S.)", "Vierges des États-Unis (les Îles)", "VI", "VIR", "850"}, - {"Burkina Faso", "Burkina Faso (le)", "BF", "BFA", "854"}, - {"Uruguay", "Uruguay (l')", "UY", "URY", "858"}, - {"Uzbekistan", "Ouzbékistan (l')", "UZ", "UZB", "860"}, - {"Venezuela (Bolivarian Republic of)", "Venezuela (République bolivarienne du)", "VE", "VEN", "862"}, - {"Wallis and Futuna", "Wallis-et-Futuna", "WF", "WLF", "876"}, - {"Samoa", "Samoa (le)", "WS", "WSM", "882"}, - {"Yemen", "Yémen (le)", "YE", "YEM", "887"}, - {"Zambia", "Zambie (la)", "ZM", "ZMB", "894"}, -} - -// ISO4217List is the list of ISO currency codes -var ISO4217List = []string{ - "AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN", - "BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BOV", "BRL", "BSD", "BTN", "BWP", "BYN", "BZD", - "CAD", "CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU", "CRC", "CUC", "CUP", "CVE", "CZK", - "DJF", "DKK", "DOP", "DZD", - "EGP", "ERN", "ETB", "EUR", - "FJD", "FKP", - "GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD", - "HKD", "HNL", "HRK", "HTG", "HUF", - "IDR", "ILS", "INR", "IQD", "IRR", "ISK", - "JMD", "JOD", "JPY", - "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT", - "LAK", "LBP", "LKR", "LRD", "LSL", "LYD", - "MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRO", "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZN", - "NAD", "NGN", "NIO", "NOK", "NPR", "NZD", - "OMR", - "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG", - "QAR", - "RON", "RSD", "RUB", "RWF", - "SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLL", "SOS", "SRD", "SSP", "STD", "STN", "SVC", "SYP", "SZL", - "THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS", - "UAH", "UGX", "USD", "USN", "UYI", "UYU", "UYW", "UZS", - "VEF", "VES", "VND", "VUV", - "WST", - "XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XOF", "XPD", "XPF", "XPT", "XSU", "XTS", "XUA", "XXX", - "YER", - "ZAR", "ZMW", "ZWL", -} - -// ISO693Entry stores ISO language codes -type ISO693Entry struct { - Alpha3bCode string - Alpha2Code string - English string -} - -//ISO693List based on http://data.okfn.org/data/core/language-codes/r/language-codes-3b2.json -var ISO693List = []ISO693Entry{ - {Alpha3bCode: "aar", Alpha2Code: "aa", English: "Afar"}, - {Alpha3bCode: "abk", Alpha2Code: "ab", English: "Abkhazian"}, - {Alpha3bCode: "afr", Alpha2Code: "af", English: "Afrikaans"}, - {Alpha3bCode: "aka", Alpha2Code: "ak", English: "Akan"}, - {Alpha3bCode: "alb", Alpha2Code: "sq", English: "Albanian"}, - {Alpha3bCode: "amh", Alpha2Code: "am", English: "Amharic"}, - {Alpha3bCode: "ara", Alpha2Code: "ar", English: "Arabic"}, - {Alpha3bCode: "arg", Alpha2Code: "an", English: "Aragonese"}, - {Alpha3bCode: "arm", Alpha2Code: "hy", English: "Armenian"}, - {Alpha3bCode: "asm", Alpha2Code: "as", English: "Assamese"}, - {Alpha3bCode: "ava", Alpha2Code: "av", English: "Avaric"}, - {Alpha3bCode: "ave", Alpha2Code: "ae", English: "Avestan"}, - {Alpha3bCode: "aym", Alpha2Code: "ay", English: "Aymara"}, - {Alpha3bCode: "aze", Alpha2Code: "az", English: "Azerbaijani"}, - {Alpha3bCode: "bak", Alpha2Code: "ba", English: "Bashkir"}, - {Alpha3bCode: "bam", Alpha2Code: "bm", English: "Bambara"}, - {Alpha3bCode: "baq", Alpha2Code: "eu", English: "Basque"}, - {Alpha3bCode: "bel", Alpha2Code: "be", English: "Belarusian"}, - {Alpha3bCode: "ben", Alpha2Code: "bn", English: "Bengali"}, - {Alpha3bCode: "bih", Alpha2Code: "bh", English: "Bihari languages"}, - {Alpha3bCode: "bis", Alpha2Code: "bi", English: "Bislama"}, - {Alpha3bCode: "bos", Alpha2Code: "bs", English: "Bosnian"}, - {Alpha3bCode: "bre", Alpha2Code: "br", English: "Breton"}, - {Alpha3bCode: "bul", Alpha2Code: "bg", English: "Bulgarian"}, - {Alpha3bCode: "bur", Alpha2Code: "my", English: "Burmese"}, - {Alpha3bCode: "cat", Alpha2Code: "ca", English: "Catalan; Valencian"}, - {Alpha3bCode: "cha", Alpha2Code: "ch", English: "Chamorro"}, - {Alpha3bCode: "che", Alpha2Code: "ce", English: "Chechen"}, - {Alpha3bCode: "chi", Alpha2Code: "zh", English: "Chinese"}, - {Alpha3bCode: "chu", Alpha2Code: "cu", English: "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic"}, - {Alpha3bCode: "chv", Alpha2Code: "cv", English: "Chuvash"}, - {Alpha3bCode: "cor", Alpha2Code: "kw", English: "Cornish"}, - {Alpha3bCode: "cos", Alpha2Code: "co", English: "Corsican"}, - {Alpha3bCode: "cre", Alpha2Code: "cr", English: "Cree"}, - {Alpha3bCode: "cze", Alpha2Code: "cs", English: "Czech"}, - {Alpha3bCode: "dan", Alpha2Code: "da", English: "Danish"}, - {Alpha3bCode: "div", Alpha2Code: "dv", English: "Divehi; Dhivehi; Maldivian"}, - {Alpha3bCode: "dut", Alpha2Code: "nl", English: "Dutch; Flemish"}, - {Alpha3bCode: "dzo", Alpha2Code: "dz", English: "Dzongkha"}, - {Alpha3bCode: "eng", Alpha2Code: "en", English: "English"}, - {Alpha3bCode: "epo", Alpha2Code: "eo", English: "Esperanto"}, - {Alpha3bCode: "est", Alpha2Code: "et", English: "Estonian"}, - {Alpha3bCode: "ewe", Alpha2Code: "ee", English: "Ewe"}, - {Alpha3bCode: "fao", Alpha2Code: "fo", English: "Faroese"}, - {Alpha3bCode: "fij", Alpha2Code: "fj", English: "Fijian"}, - {Alpha3bCode: "fin", Alpha2Code: "fi", English: "Finnish"}, - {Alpha3bCode: "fre", Alpha2Code: "fr", English: "French"}, - {Alpha3bCode: "fry", Alpha2Code: "fy", English: "Western Frisian"}, - {Alpha3bCode: "ful", Alpha2Code: "ff", English: "Fulah"}, - {Alpha3bCode: "geo", Alpha2Code: "ka", English: "Georgian"}, - {Alpha3bCode: "ger", Alpha2Code: "de", English: "German"}, - {Alpha3bCode: "gla", Alpha2Code: "gd", English: "Gaelic; Scottish Gaelic"}, - {Alpha3bCode: "gle", Alpha2Code: "ga", English: "Irish"}, - {Alpha3bCode: "glg", Alpha2Code: "gl", English: "Galician"}, - {Alpha3bCode: "glv", Alpha2Code: "gv", English: "Manx"}, - {Alpha3bCode: "gre", Alpha2Code: "el", English: "Greek, Modern (1453-)"}, - {Alpha3bCode: "grn", Alpha2Code: "gn", English: "Guarani"}, - {Alpha3bCode: "guj", Alpha2Code: "gu", English: "Gujarati"}, - {Alpha3bCode: "hat", Alpha2Code: "ht", English: "Haitian; Haitian Creole"}, - {Alpha3bCode: "hau", Alpha2Code: "ha", English: "Hausa"}, - {Alpha3bCode: "heb", Alpha2Code: "he", English: "Hebrew"}, - {Alpha3bCode: "her", Alpha2Code: "hz", English: "Herero"}, - {Alpha3bCode: "hin", Alpha2Code: "hi", English: "Hindi"}, - {Alpha3bCode: "hmo", Alpha2Code: "ho", English: "Hiri Motu"}, - {Alpha3bCode: "hrv", Alpha2Code: "hr", English: "Croatian"}, - {Alpha3bCode: "hun", Alpha2Code: "hu", English: "Hungarian"}, - {Alpha3bCode: "ibo", Alpha2Code: "ig", English: "Igbo"}, - {Alpha3bCode: "ice", Alpha2Code: "is", English: "Icelandic"}, - {Alpha3bCode: "ido", Alpha2Code: "io", English: "Ido"}, - {Alpha3bCode: "iii", Alpha2Code: "ii", English: "Sichuan Yi; Nuosu"}, - {Alpha3bCode: "iku", Alpha2Code: "iu", English: "Inuktitut"}, - {Alpha3bCode: "ile", Alpha2Code: "ie", English: "Interlingue; Occidental"}, - {Alpha3bCode: "ina", Alpha2Code: "ia", English: "Interlingua (International Auxiliary Language Association)"}, - {Alpha3bCode: "ind", Alpha2Code: "id", English: "Indonesian"}, - {Alpha3bCode: "ipk", Alpha2Code: "ik", English: "Inupiaq"}, - {Alpha3bCode: "ita", Alpha2Code: "it", English: "Italian"}, - {Alpha3bCode: "jav", Alpha2Code: "jv", English: "Javanese"}, - {Alpha3bCode: "jpn", Alpha2Code: "ja", English: "Japanese"}, - {Alpha3bCode: "kal", Alpha2Code: "kl", English: "Kalaallisut; Greenlandic"}, - {Alpha3bCode: "kan", Alpha2Code: "kn", English: "Kannada"}, - {Alpha3bCode: "kas", Alpha2Code: "ks", English: "Kashmiri"}, - {Alpha3bCode: "kau", Alpha2Code: "kr", English: "Kanuri"}, - {Alpha3bCode: "kaz", Alpha2Code: "kk", English: "Kazakh"}, - {Alpha3bCode: "khm", Alpha2Code: "km", English: "Central Khmer"}, - {Alpha3bCode: "kik", Alpha2Code: "ki", English: "Kikuyu; Gikuyu"}, - {Alpha3bCode: "kin", Alpha2Code: "rw", English: "Kinyarwanda"}, - {Alpha3bCode: "kir", Alpha2Code: "ky", English: "Kirghiz; Kyrgyz"}, - {Alpha3bCode: "kom", Alpha2Code: "kv", English: "Komi"}, - {Alpha3bCode: "kon", Alpha2Code: "kg", English: "Kongo"}, - {Alpha3bCode: "kor", Alpha2Code: "ko", English: "Korean"}, - {Alpha3bCode: "kua", Alpha2Code: "kj", English: "Kuanyama; Kwanyama"}, - {Alpha3bCode: "kur", Alpha2Code: "ku", English: "Kurdish"}, - {Alpha3bCode: "lao", Alpha2Code: "lo", English: "Lao"}, - {Alpha3bCode: "lat", Alpha2Code: "la", English: "Latin"}, - {Alpha3bCode: "lav", Alpha2Code: "lv", English: "Latvian"}, - {Alpha3bCode: "lim", Alpha2Code: "li", English: "Limburgan; Limburger; Limburgish"}, - {Alpha3bCode: "lin", Alpha2Code: "ln", English: "Lingala"}, - {Alpha3bCode: "lit", Alpha2Code: "lt", English: "Lithuanian"}, - {Alpha3bCode: "ltz", Alpha2Code: "lb", English: "Luxembourgish; Letzeburgesch"}, - {Alpha3bCode: "lub", Alpha2Code: "lu", English: "Luba-Katanga"}, - {Alpha3bCode: "lug", Alpha2Code: "lg", English: "Ganda"}, - {Alpha3bCode: "mac", Alpha2Code: "mk", English: "Macedonian"}, - {Alpha3bCode: "mah", Alpha2Code: "mh", English: "Marshallese"}, - {Alpha3bCode: "mal", Alpha2Code: "ml", English: "Malayalam"}, - {Alpha3bCode: "mao", Alpha2Code: "mi", English: "Maori"}, - {Alpha3bCode: "mar", Alpha2Code: "mr", English: "Marathi"}, - {Alpha3bCode: "may", Alpha2Code: "ms", English: "Malay"}, - {Alpha3bCode: "mlg", Alpha2Code: "mg", English: "Malagasy"}, - {Alpha3bCode: "mlt", Alpha2Code: "mt", English: "Maltese"}, - {Alpha3bCode: "mon", Alpha2Code: "mn", English: "Mongolian"}, - {Alpha3bCode: "nau", Alpha2Code: "na", English: "Nauru"}, - {Alpha3bCode: "nav", Alpha2Code: "nv", English: "Navajo; Navaho"}, - {Alpha3bCode: "nbl", Alpha2Code: "nr", English: "Ndebele, South; South Ndebele"}, - {Alpha3bCode: "nde", Alpha2Code: "nd", English: "Ndebele, North; North Ndebele"}, - {Alpha3bCode: "ndo", Alpha2Code: "ng", English: "Ndonga"}, - {Alpha3bCode: "nep", Alpha2Code: "ne", English: "Nepali"}, - {Alpha3bCode: "nno", Alpha2Code: "nn", English: "Norwegian Nynorsk; Nynorsk, Norwegian"}, - {Alpha3bCode: "nob", Alpha2Code: "nb", English: "Bokmål, Norwegian; Norwegian Bokmål"}, - {Alpha3bCode: "nor", Alpha2Code: "no", English: "Norwegian"}, - {Alpha3bCode: "nya", Alpha2Code: "ny", English: "Chichewa; Chewa; Nyanja"}, - {Alpha3bCode: "oci", Alpha2Code: "oc", English: "Occitan (post 1500); Provençal"}, - {Alpha3bCode: "oji", Alpha2Code: "oj", English: "Ojibwa"}, - {Alpha3bCode: "ori", Alpha2Code: "or", English: "Oriya"}, - {Alpha3bCode: "orm", Alpha2Code: "om", English: "Oromo"}, - {Alpha3bCode: "oss", Alpha2Code: "os", English: "Ossetian; Ossetic"}, - {Alpha3bCode: "pan", Alpha2Code: "pa", English: "Panjabi; Punjabi"}, - {Alpha3bCode: "per", Alpha2Code: "fa", English: "Persian"}, - {Alpha3bCode: "pli", Alpha2Code: "pi", English: "Pali"}, - {Alpha3bCode: "pol", Alpha2Code: "pl", English: "Polish"}, - {Alpha3bCode: "por", Alpha2Code: "pt", English: "Portuguese"}, - {Alpha3bCode: "pus", Alpha2Code: "ps", English: "Pushto; Pashto"}, - {Alpha3bCode: "que", Alpha2Code: "qu", English: "Quechua"}, - {Alpha3bCode: "roh", Alpha2Code: "rm", English: "Romansh"}, - {Alpha3bCode: "rum", Alpha2Code: "ro", English: "Romanian; Moldavian; Moldovan"}, - {Alpha3bCode: "run", Alpha2Code: "rn", English: "Rundi"}, - {Alpha3bCode: "rus", Alpha2Code: "ru", English: "Russian"}, - {Alpha3bCode: "sag", Alpha2Code: "sg", English: "Sango"}, - {Alpha3bCode: "san", Alpha2Code: "sa", English: "Sanskrit"}, - {Alpha3bCode: "sin", Alpha2Code: "si", English: "Sinhala; Sinhalese"}, - {Alpha3bCode: "slo", Alpha2Code: "sk", English: "Slovak"}, - {Alpha3bCode: "slv", Alpha2Code: "sl", English: "Slovenian"}, - {Alpha3bCode: "sme", Alpha2Code: "se", English: "Northern Sami"}, - {Alpha3bCode: "smo", Alpha2Code: "sm", English: "Samoan"}, - {Alpha3bCode: "sna", Alpha2Code: "sn", English: "Shona"}, - {Alpha3bCode: "snd", Alpha2Code: "sd", English: "Sindhi"}, - {Alpha3bCode: "som", Alpha2Code: "so", English: "Somali"}, - {Alpha3bCode: "sot", Alpha2Code: "st", English: "Sotho, Southern"}, - {Alpha3bCode: "spa", Alpha2Code: "es", English: "Spanish; Castilian"}, - {Alpha3bCode: "srd", Alpha2Code: "sc", English: "Sardinian"}, - {Alpha3bCode: "srp", Alpha2Code: "sr", English: "Serbian"}, - {Alpha3bCode: "ssw", Alpha2Code: "ss", English: "Swati"}, - {Alpha3bCode: "sun", Alpha2Code: "su", English: "Sundanese"}, - {Alpha3bCode: "swa", Alpha2Code: "sw", English: "Swahili"}, - {Alpha3bCode: "swe", Alpha2Code: "sv", English: "Swedish"}, - {Alpha3bCode: "tah", Alpha2Code: "ty", English: "Tahitian"}, - {Alpha3bCode: "tam", Alpha2Code: "ta", English: "Tamil"}, - {Alpha3bCode: "tat", Alpha2Code: "tt", English: "Tatar"}, - {Alpha3bCode: "tel", Alpha2Code: "te", English: "Telugu"}, - {Alpha3bCode: "tgk", Alpha2Code: "tg", English: "Tajik"}, - {Alpha3bCode: "tgl", Alpha2Code: "tl", English: "Tagalog"}, - {Alpha3bCode: "tha", Alpha2Code: "th", English: "Thai"}, - {Alpha3bCode: "tib", Alpha2Code: "bo", English: "Tibetan"}, - {Alpha3bCode: "tir", Alpha2Code: "ti", English: "Tigrinya"}, - {Alpha3bCode: "ton", Alpha2Code: "to", English: "Tonga (Tonga Islands)"}, - {Alpha3bCode: "tsn", Alpha2Code: "tn", English: "Tswana"}, - {Alpha3bCode: "tso", Alpha2Code: "ts", English: "Tsonga"}, - {Alpha3bCode: "tuk", Alpha2Code: "tk", English: "Turkmen"}, - {Alpha3bCode: "tur", Alpha2Code: "tr", English: "Turkish"}, - {Alpha3bCode: "twi", Alpha2Code: "tw", English: "Twi"}, - {Alpha3bCode: "uig", Alpha2Code: "ug", English: "Uighur; Uyghur"}, - {Alpha3bCode: "ukr", Alpha2Code: "uk", English: "Ukrainian"}, - {Alpha3bCode: "urd", Alpha2Code: "ur", English: "Urdu"}, - {Alpha3bCode: "uzb", Alpha2Code: "uz", English: "Uzbek"}, - {Alpha3bCode: "ven", Alpha2Code: "ve", English: "Venda"}, - {Alpha3bCode: "vie", Alpha2Code: "vi", English: "Vietnamese"}, - {Alpha3bCode: "vol", Alpha2Code: "vo", English: "Volapük"}, - {Alpha3bCode: "wel", Alpha2Code: "cy", English: "Welsh"}, - {Alpha3bCode: "wln", Alpha2Code: "wa", English: "Walloon"}, - {Alpha3bCode: "wol", Alpha2Code: "wo", English: "Wolof"}, - {Alpha3bCode: "xho", Alpha2Code: "xh", English: "Xhosa"}, - {Alpha3bCode: "yid", Alpha2Code: "yi", English: "Yiddish"}, - {Alpha3bCode: "yor", Alpha2Code: "yo", English: "Yoruba"}, - {Alpha3bCode: "zha", Alpha2Code: "za", English: "Zhuang; Chuang"}, - {Alpha3bCode: "zul", Alpha2Code: "zu", English: "Zulu"}, -} diff --git a/vendor/github.com/asaskevich/govalidator/utils.go b/vendor/github.com/asaskevich/govalidator/utils.go deleted file mode 100644 index f4c30f82..00000000 --- a/vendor/github.com/asaskevich/govalidator/utils.go +++ /dev/null @@ -1,270 +0,0 @@ -package govalidator - -import ( - "errors" - "fmt" - "html" - "math" - "path" - "regexp" - "strings" - "unicode" - "unicode/utf8" -) - -// Contains checks if the string contains the substring. -func Contains(str, substring string) bool { - return strings.Contains(str, substring) -} - -// Matches checks if string matches the pattern (pattern is regular expression) -// In case of error return false -func Matches(str, pattern string) bool { - match, _ := regexp.MatchString(pattern, str) - return match -} - -// LeftTrim trims characters from the left side of the input. -// If second argument is empty, it will remove leading spaces. -func LeftTrim(str, chars string) string { - if chars == "" { - return strings.TrimLeftFunc(str, unicode.IsSpace) - } - r, _ := regexp.Compile("^[" + chars + "]+") - return r.ReplaceAllString(str, "") -} - -// RightTrim trims characters from the right side of the input. -// If second argument is empty, it will remove trailing spaces. -func RightTrim(str, chars string) string { - if chars == "" { - return strings.TrimRightFunc(str, unicode.IsSpace) - } - r, _ := regexp.Compile("[" + chars + "]+$") - return r.ReplaceAllString(str, "") -} - -// Trim trims characters from both sides of the input. -// If second argument is empty, it will remove spaces. -func Trim(str, chars string) string { - return LeftTrim(RightTrim(str, chars), chars) -} - -// WhiteList removes characters that do not appear in the whitelist. -func WhiteList(str, chars string) string { - pattern := "[^" + chars + "]+" - r, _ := regexp.Compile(pattern) - return r.ReplaceAllString(str, "") -} - -// BlackList removes characters that appear in the blacklist. -func BlackList(str, chars string) string { - pattern := "[" + chars + "]+" - r, _ := regexp.Compile(pattern) - return r.ReplaceAllString(str, "") -} - -// StripLow removes characters with a numerical value < 32 and 127, mostly control characters. -// If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD). -func StripLow(str string, keepNewLines bool) string { - chars := "" - if keepNewLines { - chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F" - } else { - chars = "\x00-\x1F\x7F" - } - return BlackList(str, chars) -} - -// ReplacePattern replaces regular expression pattern in string -func ReplacePattern(str, pattern, replace string) string { - r, _ := regexp.Compile(pattern) - return r.ReplaceAllString(str, replace) -} - -// Escape replaces <, >, & and " with HTML entities. -var Escape = html.EscapeString - -func addSegment(inrune, segment []rune) []rune { - if len(segment) == 0 { - return inrune - } - if len(inrune) != 0 { - inrune = append(inrune, '_') - } - inrune = append(inrune, segment...) - return inrune -} - -// UnderscoreToCamelCase converts from underscore separated form to camel case form. -// Ex.: my_func => MyFunc -func UnderscoreToCamelCase(s string) string { - return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1) -} - -// CamelCaseToUnderscore converts from camel case form to underscore separated form. -// Ex.: MyFunc => my_func -func CamelCaseToUnderscore(str string) string { - var output []rune - var segment []rune - for _, r := range str { - - // not treat number as separate segment - if !unicode.IsLower(r) && string(r) != "_" && !unicode.IsNumber(r) { - output = addSegment(output, segment) - segment = nil - } - segment = append(segment, unicode.ToLower(r)) - } - output = addSegment(output, segment) - return string(output) -} - -// Reverse returns reversed string -func Reverse(s string) string { - r := []rune(s) - for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 { - r[i], r[j] = r[j], r[i] - } - return string(r) -} - -// GetLines splits string by "\n" and return array of lines -func GetLines(s string) []string { - return strings.Split(s, "\n") -} - -// GetLine returns specified line of multiline string -func GetLine(s string, index int) (string, error) { - lines := GetLines(s) - if index < 0 || index >= len(lines) { - return "", errors.New("line index out of bounds") - } - return lines[index], nil -} - -// RemoveTags removes all tags from HTML string -func RemoveTags(s string) string { - return ReplacePattern(s, "<[^>]*>", "") -} - -// SafeFileName returns safe string that can be used in file names -func SafeFileName(str string) string { - name := strings.ToLower(str) - name = path.Clean(path.Base(name)) - name = strings.Trim(name, " ") - separators, err := regexp.Compile(`[ &_=+:]`) - if err == nil { - name = separators.ReplaceAllString(name, "-") - } - legal, err := regexp.Compile(`[^[:alnum:]-.]`) - if err == nil { - name = legal.ReplaceAllString(name, "") - } - for strings.Contains(name, "--") { - name = strings.Replace(name, "--", "-", -1) - } - return name -} - -// NormalizeEmail canonicalize an email address. -// The local part of the email address is lowercased for all domains; the hostname is always lowercased and -// the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail). -// Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and -// are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are -// normalized to @gmail.com. -func NormalizeEmail(str string) (string, error) { - if !IsEmail(str) { - return "", fmt.Errorf("%s is not an email", str) - } - parts := strings.Split(str, "@") - parts[0] = strings.ToLower(parts[0]) - parts[1] = strings.ToLower(parts[1]) - if parts[1] == "gmail.com" || parts[1] == "googlemail.com" { - parts[1] = "gmail.com" - parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0] - } - return strings.Join(parts, "@"), nil -} - -// Truncate a string to the closest length without breaking words. -func Truncate(str string, length int, ending string) string { - var aftstr, befstr string - if len(str) > length { - words := strings.Fields(str) - before, present := 0, 0 - for i := range words { - befstr = aftstr - before = present - aftstr = aftstr + words[i] + " " - present = len(aftstr) - if present > length && i != 0 { - if (length - before) < (present - length) { - return Trim(befstr, " /\\.,\"'#!?&@+-") + ending - } - return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending - } - } - } - - return str -} - -// PadLeft pads left side of a string if size of string is less then indicated pad length -func PadLeft(str string, padStr string, padLen int) string { - return buildPadStr(str, padStr, padLen, true, false) -} - -// PadRight pads right side of a string if size of string is less then indicated pad length -func PadRight(str string, padStr string, padLen int) string { - return buildPadStr(str, padStr, padLen, false, true) -} - -// PadBoth pads both sides of a string if size of string is less then indicated pad length -func PadBoth(str string, padStr string, padLen int) string { - return buildPadStr(str, padStr, padLen, true, true) -} - -// PadString either left, right or both sides. -// Note that padding string can be unicode and more then one character -func buildPadStr(str string, padStr string, padLen int, padLeft bool, padRight bool) string { - - // When padded length is less then the current string size - if padLen < utf8.RuneCountInString(str) { - return str - } - - padLen -= utf8.RuneCountInString(str) - - targetLen := padLen - - targetLenLeft := targetLen - targetLenRight := targetLen - if padLeft && padRight { - targetLenLeft = padLen / 2 - targetLenRight = padLen - targetLenLeft - } - - strToRepeatLen := utf8.RuneCountInString(padStr) - - repeatTimes := int(math.Ceil(float64(targetLen) / float64(strToRepeatLen))) - repeatedString := strings.Repeat(padStr, repeatTimes) - - leftSide := "" - if padLeft { - leftSide = repeatedString[0:targetLenLeft] - } - - rightSide := "" - if padRight { - rightSide = repeatedString[0:targetLenRight] - } - - return leftSide + str + rightSide -} - -// TruncatingErrorf removes extra args from fmt.Errorf if not formatted in the str object -func TruncatingErrorf(str string, args ...interface{}) error { - n := strings.Count(str, "%s") - return fmt.Errorf(str, args[:n]...) -} diff --git a/vendor/github.com/asaskevich/govalidator/validator.go b/vendor/github.com/asaskevich/govalidator/validator.go deleted file mode 100644 index 5c918fc4..00000000 --- a/vendor/github.com/asaskevich/govalidator/validator.go +++ /dev/null @@ -1,1627 +0,0 @@ -// Package govalidator is package of validators and sanitizers for strings, structs and collections. -package govalidator - -import ( - "bytes" - "crypto/rsa" - "crypto/x509" - "encoding/base64" - "encoding/json" - "encoding/pem" - "fmt" - "io/ioutil" - "net" - "net/url" - "reflect" - "regexp" - "sort" - "strconv" - "strings" - "time" - "unicode" - "unicode/utf8" -) - -var ( - fieldsRequiredByDefault bool - nilPtrAllowedByRequired = false - notNumberRegexp = regexp.MustCompile("[^0-9]+") - whiteSpacesAndMinus = regexp.MustCompile(`[\s-]+`) - paramsRegexp = regexp.MustCompile(`\(.*\)$`) -) - -const maxURLRuneCount = 2083 -const minURLRuneCount = 3 -const rfc3339WithoutZone = "2006-01-02T15:04:05" - -// SetFieldsRequiredByDefault causes validation to fail when struct fields -// do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). -// This struct definition will fail govalidator.ValidateStruct() (and the field values do not matter): -// type exampleStruct struct { -// Name string `` -// Email string `valid:"email"` -// This, however, will only fail when Email is empty or an invalid email address: -// type exampleStruct2 struct { -// Name string `valid:"-"` -// Email string `valid:"email"` -// Lastly, this will only fail when Email is an invalid email address but not when it's empty: -// type exampleStruct2 struct { -// Name string `valid:"-"` -// Email string `valid:"email,optional"` -func SetFieldsRequiredByDefault(value bool) { - fieldsRequiredByDefault = value -} - -// SetNilPtrAllowedByRequired causes validation to pass for nil ptrs when a field is set to required. -// The validation will still reject ptr fields in their zero value state. Example with this enabled: -// type exampleStruct struct { -// Name *string `valid:"required"` -// With `Name` set to "", this will be considered invalid input and will cause a validation error. -// With `Name` set to nil, this will be considered valid by validation. -// By default this is disabled. -func SetNilPtrAllowedByRequired(value bool) { - nilPtrAllowedByRequired = value -} - -// IsEmail checks if the string is an email. -func IsEmail(str string) bool { - // TODO uppercase letters are not supported - return rxEmail.MatchString(str) -} - -// IsExistingEmail checks if the string is an email of existing domain -func IsExistingEmail(email string) bool { - - if len(email) < 6 || len(email) > 254 { - return false - } - at := strings.LastIndex(email, "@") - if at <= 0 || at > len(email)-3 { - return false - } - user := email[:at] - host := email[at+1:] - if len(user) > 64 { - return false - } - switch host { - case "localhost", "example.com": - return true - } - if userDotRegexp.MatchString(user) || !userRegexp.MatchString(user) || !hostRegexp.MatchString(host) { - return false - } - if _, err := net.LookupMX(host); err != nil { - if _, err := net.LookupIP(host); err != nil { - return false - } - } - - return true -} - -// IsURL checks if the string is an URL. -func IsURL(str string) bool { - if str == "" || utf8.RuneCountInString(str) >= maxURLRuneCount || len(str) <= minURLRuneCount || strings.HasPrefix(str, ".") { - return false - } - strTemp := str - if strings.Contains(str, ":") && !strings.Contains(str, "://") { - // support no indicated urlscheme but with colon for port number - // http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString - strTemp = "http://" + str - } - u, err := url.Parse(strTemp) - if err != nil { - return false - } - if strings.HasPrefix(u.Host, ".") { - return false - } - if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) { - return false - } - return rxURL.MatchString(str) -} - -// IsRequestURL checks if the string rawurl, assuming -// it was received in an HTTP request, is a valid -// URL confirm to RFC 3986 -func IsRequestURL(rawurl string) bool { - url, err := url.ParseRequestURI(rawurl) - if err != nil { - return false //Couldn't even parse the rawurl - } - if len(url.Scheme) == 0 { - return false //No Scheme found - } - return true -} - -// IsRequestURI checks if the string rawurl, assuming -// it was received in an HTTP request, is an -// absolute URI or an absolute path. -func IsRequestURI(rawurl string) bool { - _, err := url.ParseRequestURI(rawurl) - return err == nil -} - -// IsAlpha checks if the string contains only letters (a-zA-Z). Empty string is valid. -func IsAlpha(str string) bool { - if IsNull(str) { - return true - } - return rxAlpha.MatchString(str) -} - -//IsUTFLetter checks if the string contains only unicode letter characters. -//Similar to IsAlpha but for all languages. Empty string is valid. -func IsUTFLetter(str string) bool { - if IsNull(str) { - return true - } - - for _, c := range str { - if !unicode.IsLetter(c) { - return false - } - } - return true - -} - -// IsAlphanumeric checks if the string contains only letters and numbers. Empty string is valid. -func IsAlphanumeric(str string) bool { - if IsNull(str) { - return true - } - return rxAlphanumeric.MatchString(str) -} - -// IsUTFLetterNumeric checks if the string contains only unicode letters and numbers. Empty string is valid. -func IsUTFLetterNumeric(str string) bool { - if IsNull(str) { - return true - } - for _, c := range str { - if !unicode.IsLetter(c) && !unicode.IsNumber(c) { //letters && numbers are ok - return false - } - } - return true - -} - -// IsNumeric checks if the string contains only numbers. Empty string is valid. -func IsNumeric(str string) bool { - if IsNull(str) { - return true - } - return rxNumeric.MatchString(str) -} - -// IsUTFNumeric checks if the string contains only unicode numbers of any kind. -// Numbers can be 0-9 but also Fractions ¾,Roman Ⅸ and Hangzhou 〩. Empty string is valid. -func IsUTFNumeric(str string) bool { - if IsNull(str) { - return true - } - if strings.IndexAny(str, "+-") > 0 { - return false - } - if len(str) > 1 { - str = strings.TrimPrefix(str, "-") - str = strings.TrimPrefix(str, "+") - } - for _, c := range str { - if !unicode.IsNumber(c) { //numbers && minus sign are ok - return false - } - } - return true - -} - -// IsUTFDigit checks if the string contains only unicode radix-10 decimal digits. Empty string is valid. -func IsUTFDigit(str string) bool { - if IsNull(str) { - return true - } - if strings.IndexAny(str, "+-") > 0 { - return false - } - if len(str) > 1 { - str = strings.TrimPrefix(str, "-") - str = strings.TrimPrefix(str, "+") - } - for _, c := range str { - if !unicode.IsDigit(c) { //digits && minus sign are ok - return false - } - } - return true - -} - -// IsHexadecimal checks if the string is a hexadecimal number. -func IsHexadecimal(str string) bool { - return rxHexadecimal.MatchString(str) -} - -// IsHexcolor checks if the string is a hexadecimal color. -func IsHexcolor(str string) bool { - return rxHexcolor.MatchString(str) -} - -// IsRGBcolor checks if the string is a valid RGB color in form rgb(RRR, GGG, BBB). -func IsRGBcolor(str string) bool { - return rxRGBcolor.MatchString(str) -} - -// IsLowerCase checks if the string is lowercase. Empty string is valid. -func IsLowerCase(str string) bool { - if IsNull(str) { - return true - } - return str == strings.ToLower(str) -} - -// IsUpperCase checks if the string is uppercase. Empty string is valid. -func IsUpperCase(str string) bool { - if IsNull(str) { - return true - } - return str == strings.ToUpper(str) -} - -// HasLowerCase checks if the string contains at least 1 lowercase. Empty string is valid. -func HasLowerCase(str string) bool { - if IsNull(str) { - return true - } - return rxHasLowerCase.MatchString(str) -} - -// HasUpperCase checks if the string contains as least 1 uppercase. Empty string is valid. -func HasUpperCase(str string) bool { - if IsNull(str) { - return true - } - return rxHasUpperCase.MatchString(str) -} - -// IsInt checks if the string is an integer. Empty string is valid. -func IsInt(str string) bool { - if IsNull(str) { - return true - } - return rxInt.MatchString(str) -} - -// IsFloat checks if the string is a float. -func IsFloat(str string) bool { - return str != "" && rxFloat.MatchString(str) -} - -// IsDivisibleBy checks if the string is a number that's divisible by another. -// If second argument is not valid integer or zero, it's return false. -// Otherwise, if first argument is not valid integer or zero, it's return true (Invalid string converts to zero). -func IsDivisibleBy(str, num string) bool { - f, _ := ToFloat(str) - p := int64(f) - q, _ := ToInt(num) - if q == 0 { - return false - } - return (p == 0) || (p%q == 0) -} - -// IsNull checks if the string is null. -func IsNull(str string) bool { - return len(str) == 0 -} - -// IsNotNull checks if the string is not null. -func IsNotNull(str string) bool { - return !IsNull(str) -} - -// HasWhitespaceOnly checks the string only contains whitespace -func HasWhitespaceOnly(str string) bool { - return len(str) > 0 && rxHasWhitespaceOnly.MatchString(str) -} - -// HasWhitespace checks if the string contains any whitespace -func HasWhitespace(str string) bool { - return len(str) > 0 && rxHasWhitespace.MatchString(str) -} - -// IsByteLength checks if the string's length (in bytes) falls in a range. -func IsByteLength(str string, min, max int) bool { - return len(str) >= min && len(str) <= max -} - -// IsUUIDv3 checks if the string is a UUID version 3. -func IsUUIDv3(str string) bool { - return rxUUID3.MatchString(str) -} - -// IsUUIDv4 checks if the string is a UUID version 4. -func IsUUIDv4(str string) bool { - return rxUUID4.MatchString(str) -} - -// IsUUIDv5 checks if the string is a UUID version 5. -func IsUUIDv5(str string) bool { - return rxUUID5.MatchString(str) -} - -// IsUUID checks if the string is a UUID (version 3, 4 or 5). -func IsUUID(str string) bool { - return rxUUID.MatchString(str) -} - -// IsCreditCard checks if the string is a credit card. -func IsCreditCard(str string) bool { - sanitized := notNumberRegexp.ReplaceAllString(str, "") - if !rxCreditCard.MatchString(sanitized) { - return false - } - var sum int64 - var digit string - var tmpNum int64 - var shouldDouble bool - for i := len(sanitized) - 1; i >= 0; i-- { - digit = sanitized[i:(i + 1)] - tmpNum, _ = ToInt(digit) - if shouldDouble { - tmpNum *= 2 - if tmpNum >= 10 { - sum += (tmpNum % 10) + 1 - } else { - sum += tmpNum - } - } else { - sum += tmpNum - } - shouldDouble = !shouldDouble - } - - return sum%10 == 0 -} - -// IsISBN10 checks if the string is an ISBN version 10. -func IsISBN10(str string) bool { - return IsISBN(str, 10) -} - -// IsISBN13 checks if the string is an ISBN version 13. -func IsISBN13(str string) bool { - return IsISBN(str, 13) -} - -// IsISBN checks if the string is an ISBN (version 10 or 13). -// If version value is not equal to 10 or 13, it will be checks both variants. -func IsISBN(str string, version int) bool { - sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "") - var checksum int32 - var i int32 - if version == 10 { - if !rxISBN10.MatchString(sanitized) { - return false - } - for i = 0; i < 9; i++ { - checksum += (i + 1) * int32(sanitized[i]-'0') - } - if sanitized[9] == 'X' { - checksum += 10 * 10 - } else { - checksum += 10 * int32(sanitized[9]-'0') - } - if checksum%11 == 0 { - return true - } - return false - } else if version == 13 { - if !rxISBN13.MatchString(sanitized) { - return false - } - factor := []int32{1, 3} - for i = 0; i < 12; i++ { - checksum += factor[i%2] * int32(sanitized[i]-'0') - } - return (int32(sanitized[12]-'0'))-((10-(checksum%10))%10) == 0 - } - return IsISBN(str, 10) || IsISBN(str, 13) -} - -// IsJSON checks if the string is valid JSON (note: uses json.Unmarshal). -func IsJSON(str string) bool { - var js json.RawMessage - return json.Unmarshal([]byte(str), &js) == nil -} - -// IsMultibyte checks if the string contains one or more multibyte chars. Empty string is valid. -func IsMultibyte(str string) bool { - if IsNull(str) { - return true - } - return rxMultibyte.MatchString(str) -} - -// IsASCII checks if the string contains ASCII chars only. Empty string is valid. -func IsASCII(str string) bool { - if IsNull(str) { - return true - } - return rxASCII.MatchString(str) -} - -// IsPrintableASCII checks if the string contains printable ASCII chars only. Empty string is valid. -func IsPrintableASCII(str string) bool { - if IsNull(str) { - return true - } - return rxPrintableASCII.MatchString(str) -} - -// IsFullWidth checks if the string contains any full-width chars. Empty string is valid. -func IsFullWidth(str string) bool { - if IsNull(str) { - return true - } - return rxFullWidth.MatchString(str) -} - -// IsHalfWidth checks if the string contains any half-width chars. Empty string is valid. -func IsHalfWidth(str string) bool { - if IsNull(str) { - return true - } - return rxHalfWidth.MatchString(str) -} - -// IsVariableWidth checks if the string contains a mixture of full and half-width chars. Empty string is valid. -func IsVariableWidth(str string) bool { - if IsNull(str) { - return true - } - return rxHalfWidth.MatchString(str) && rxFullWidth.MatchString(str) -} - -// IsBase64 checks if a string is base64 encoded. -func IsBase64(str string) bool { - return rxBase64.MatchString(str) -} - -// IsFilePath checks is a string is Win or Unix file path and returns it's type. -func IsFilePath(str string) (bool, int) { - if rxWinPath.MatchString(str) { - //check windows path limit see: - // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath - if len(str[3:]) > 32767 { - return false, Win - } - return true, Win - } else if rxUnixPath.MatchString(str) { - return true, Unix - } - return false, Unknown -} - -// IsDataURI checks if a string is base64 encoded data URI such as an image -func IsDataURI(str string) bool { - dataURI := strings.Split(str, ",") - if !rxDataURI.MatchString(dataURI[0]) { - return false - } - return IsBase64(dataURI[1]) -} - -// IsMagnetURI checks if a string is valid magnet URI -func IsMagnetURI(str string) bool { - return rxMagnetURI.MatchString(str) -} - -// IsISO3166Alpha2 checks if a string is valid two-letter country code -func IsISO3166Alpha2(str string) bool { - for _, entry := range ISO3166List { - if str == entry.Alpha2Code { - return true - } - } - return false -} - -// IsISO3166Alpha3 checks if a string is valid three-letter country code -func IsISO3166Alpha3(str string) bool { - for _, entry := range ISO3166List { - if str == entry.Alpha3Code { - return true - } - } - return false -} - -// IsISO693Alpha2 checks if a string is valid two-letter language code -func IsISO693Alpha2(str string) bool { - for _, entry := range ISO693List { - if str == entry.Alpha2Code { - return true - } - } - return false -} - -// IsISO693Alpha3b checks if a string is valid three-letter language code -func IsISO693Alpha3b(str string) bool { - for _, entry := range ISO693List { - if str == entry.Alpha3bCode { - return true - } - } - return false -} - -// IsDNSName will validate the given string as a DNS name -func IsDNSName(str string) bool { - if str == "" || len(strings.Replace(str, ".", "", -1)) > 255 { - // constraints already violated - return false - } - return !IsIP(str) && rxDNSName.MatchString(str) -} - -// IsHash checks if a string is a hash of type algorithm. -// Algorithm is one of ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b'] -func IsHash(str string, algorithm string) bool { - var len string - algo := strings.ToLower(algorithm) - - if algo == "crc32" || algo == "crc32b" { - len = "8" - } else if algo == "md5" || algo == "md4" || algo == "ripemd128" || algo == "tiger128" { - len = "32" - } else if algo == "sha1" || algo == "ripemd160" || algo == "tiger160" { - len = "40" - } else if algo == "tiger192" { - len = "48" - } else if algo == "sha256" { - len = "64" - } else if algo == "sha384" { - len = "96" - } else if algo == "sha512" { - len = "128" - } else { - return false - } - - return Matches(str, "^[a-f0-9]{"+len+"}$") -} - -// IsSHA512 checks is a string is a SHA512 hash. Alias for `IsHash(str, "sha512")` -func IsSHA512(str string) bool { - return IsHash(str, "sha512") -} - -// IsSHA384 checks is a string is a SHA384 hash. Alias for `IsHash(str, "sha384")` -func IsSHA384(str string) bool { - return IsHash(str, "sha384") -} - -// IsSHA256 checks is a string is a SHA256 hash. Alias for `IsHash(str, "sha256")` -func IsSHA256(str string) bool { - return IsHash(str, "sha256") -} - -// IsTiger192 checks is a string is a Tiger192 hash. Alias for `IsHash(str, "tiger192")` -func IsTiger192(str string) bool { - return IsHash(str, "tiger192") -} - -// IsTiger160 checks is a string is a Tiger160 hash. Alias for `IsHash(str, "tiger160")` -func IsTiger160(str string) bool { - return IsHash(str, "tiger160") -} - -// IsRipeMD160 checks is a string is a RipeMD160 hash. Alias for `IsHash(str, "ripemd160")` -func IsRipeMD160(str string) bool { - return IsHash(str, "ripemd160") -} - -// IsSHA1 checks is a string is a SHA-1 hash. Alias for `IsHash(str, "sha1")` -func IsSHA1(str string) bool { - return IsHash(str, "sha1") -} - -// IsTiger128 checks is a string is a Tiger128 hash. Alias for `IsHash(str, "tiger128")` -func IsTiger128(str string) bool { - return IsHash(str, "tiger128") -} - -// IsRipeMD128 checks is a string is a RipeMD128 hash. Alias for `IsHash(str, "ripemd128")` -func IsRipeMD128(str string) bool { - return IsHash(str, "ripemd128") -} - -// IsCRC32 checks is a string is a CRC32 hash. Alias for `IsHash(str, "crc32")` -func IsCRC32(str string) bool { - return IsHash(str, "crc32") -} - -// IsCRC32b checks is a string is a CRC32b hash. Alias for `IsHash(str, "crc32b")` -func IsCRC32b(str string) bool { - return IsHash(str, "crc32b") -} - -// IsMD5 checks is a string is a MD5 hash. Alias for `IsHash(str, "md5")` -func IsMD5(str string) bool { - return IsHash(str, "md5") -} - -// IsMD4 checks is a string is a MD4 hash. Alias for `IsHash(str, "md4")` -func IsMD4(str string) bool { - return IsHash(str, "md4") -} - -// IsDialString validates the given string for usage with the various Dial() functions -func IsDialString(str string) bool { - if h, p, err := net.SplitHostPort(str); err == nil && h != "" && p != "" && (IsDNSName(h) || IsIP(h)) && IsPort(p) { - return true - } - - return false -} - -// IsIP checks if a string is either IP version 4 or 6. Alias for `net.ParseIP` -func IsIP(str string) bool { - return net.ParseIP(str) != nil -} - -// IsPort checks if a string represents a valid port -func IsPort(str string) bool { - if i, err := strconv.Atoi(str); err == nil && i > 0 && i < 65536 { - return true - } - return false -} - -// IsIPv4 checks if the string is an IP version 4. -func IsIPv4(str string) bool { - ip := net.ParseIP(str) - return ip != nil && strings.Contains(str, ".") -} - -// IsIPv6 checks if the string is an IP version 6. -func IsIPv6(str string) bool { - ip := net.ParseIP(str) - return ip != nil && strings.Contains(str, ":") -} - -// IsCIDR checks if the string is an valid CIDR notiation (IPV4 & IPV6) -func IsCIDR(str string) bool { - _, _, err := net.ParseCIDR(str) - return err == nil -} - -// IsMAC checks if a string is valid MAC address. -// Possible MAC formats: -// 01:23:45:67:89:ab -// 01:23:45:67:89:ab:cd:ef -// 01-23-45-67-89-ab -// 01-23-45-67-89-ab-cd-ef -// 0123.4567.89ab -// 0123.4567.89ab.cdef -func IsMAC(str string) bool { - _, err := net.ParseMAC(str) - return err == nil -} - -// IsHost checks if the string is a valid IP (both v4 and v6) or a valid DNS name -func IsHost(str string) bool { - return IsIP(str) || IsDNSName(str) -} - -// IsMongoID checks if the string is a valid hex-encoded representation of a MongoDB ObjectId. -func IsMongoID(str string) bool { - return rxHexadecimal.MatchString(str) && (len(str) == 24) -} - -// IsLatitude checks if a string is valid latitude. -func IsLatitude(str string) bool { - return rxLatitude.MatchString(str) -} - -// IsLongitude checks if a string is valid longitude. -func IsLongitude(str string) bool { - return rxLongitude.MatchString(str) -} - -// IsIMEI checks if a string is valid IMEI -func IsIMEI(str string) bool { - return rxIMEI.MatchString(str) -} - -// IsIMSI checks if a string is valid IMSI -func IsIMSI(str string) bool { - if !rxIMSI.MatchString(str) { - return false - } - - mcc, err := strconv.ParseInt(str[0:3], 10, 32) - if err != nil { - return false - } - - switch mcc { - case 202, 204, 206, 208, 212, 213, 214, 216, 218, 219: - case 220, 221, 222, 226, 228, 230, 231, 232, 234, 235: - case 238, 240, 242, 244, 246, 247, 248, 250, 255, 257: - case 259, 260, 262, 266, 268, 270, 272, 274, 276, 278: - case 280, 282, 283, 284, 286, 288, 289, 290, 292, 293: - case 294, 295, 297, 302, 308, 310, 311, 312, 313, 314: - case 315, 316, 330, 332, 334, 338, 340, 342, 344, 346: - case 348, 350, 352, 354, 356, 358, 360, 362, 363, 364: - case 365, 366, 368, 370, 372, 374, 376, 400, 401, 402: - case 404, 405, 406, 410, 412, 413, 414, 415, 416, 417: - case 418, 419, 420, 421, 422, 424, 425, 426, 427, 428: - case 429, 430, 431, 432, 434, 436, 437, 438, 440, 441: - case 450, 452, 454, 455, 456, 457, 460, 461, 466, 467: - case 470, 472, 502, 505, 510, 514, 515, 520, 525, 528: - case 530, 536, 537, 539, 540, 541, 542, 543, 544, 545: - case 546, 547, 548, 549, 550, 551, 552, 553, 554, 555: - case 602, 603, 604, 605, 606, 607, 608, 609, 610, 611: - case 612, 613, 614, 615, 616, 617, 618, 619, 620, 621: - case 622, 623, 624, 625, 626, 627, 628, 629, 630, 631: - case 632, 633, 634, 635, 636, 637, 638, 639, 640, 641: - case 642, 643, 645, 646, 647, 648, 649, 650, 651, 652: - case 653, 654, 655, 657, 658, 659, 702, 704, 706, 708: - case 710, 712, 714, 716, 722, 724, 730, 732, 734, 736: - case 738, 740, 742, 744, 746, 748, 750, 995: - return true - default: - return false - } - return true -} - -// IsRsaPublicKey checks if a string is valid public key with provided length -func IsRsaPublicKey(str string, keylen int) bool { - bb := bytes.NewBufferString(str) - pemBytes, err := ioutil.ReadAll(bb) - if err != nil { - return false - } - block, _ := pem.Decode(pemBytes) - if block != nil && block.Type != "PUBLIC KEY" { - return false - } - var der []byte - - if block != nil { - der = block.Bytes - } else { - der, err = base64.StdEncoding.DecodeString(str) - if err != nil { - return false - } - } - - key, err := x509.ParsePKIXPublicKey(der) - if err != nil { - return false - } - pubkey, ok := key.(*rsa.PublicKey) - if !ok { - return false - } - bitlen := len(pubkey.N.Bytes()) * 8 - return bitlen == int(keylen) -} - -func toJSONName(tag string) string { - if tag == "" { - return "" - } - - // JSON name always comes first. If there's no options then split[0] is - // JSON name, if JSON name is not set, then split[0] is an empty string. - split := strings.SplitN(tag, ",", 2) - - name := split[0] - - // However it is possible that the field is skipped when - // (de-)serializing from/to JSON, in which case assume that there is no - // tag name to use - if name == "-" { - return "" - } - return name -} - -func prependPathToErrors(err error, path string) error { - switch err2 := err.(type) { - case Error: - err2.Path = append([]string{path}, err2.Path...) - return err2 - case Errors: - errors := err2.Errors() - for i, err3 := range errors { - errors[i] = prependPathToErrors(err3, path) - } - return err2 - } - return err -} - -// ValidateArray performs validation according to condition iterator that validates every element of the array -func ValidateArray(array []interface{}, iterator ConditionIterator) bool { - return Every(array, iterator) -} - -// ValidateMap use validation map for fields. -// result will be equal to `false` if there are any errors. -// s is the map containing the data to be validated. -// m is the validation map in the form: -// map[string]interface{}{"name":"required,alpha","address":map[string]interface{}{"line1":"required,alphanum"}} -func ValidateMap(s map[string]interface{}, m map[string]interface{}) (bool, error) { - if s == nil { - return true, nil - } - result := true - var err error - var errs Errors - var index int - val := reflect.ValueOf(s) - for key, value := range s { - presentResult := true - validator, ok := m[key] - if !ok { - presentResult = false - var err error - err = fmt.Errorf("all map keys has to be present in the validation map; got %s", key) - err = prependPathToErrors(err, key) - errs = append(errs, err) - } - valueField := reflect.ValueOf(value) - mapResult := true - typeResult := true - structResult := true - resultField := true - switch subValidator := validator.(type) { - case map[string]interface{}: - var err error - if v, ok := value.(map[string]interface{}); !ok { - mapResult = false - err = fmt.Errorf("map validator has to be for the map type only; got %s", valueField.Type().String()) - err = prependPathToErrors(err, key) - errs = append(errs, err) - } else { - mapResult, err = ValidateMap(v, subValidator) - if err != nil { - mapResult = false - err = prependPathToErrors(err, key) - errs = append(errs, err) - } - } - case string: - if (valueField.Kind() == reflect.Struct || - (valueField.Kind() == reflect.Ptr && valueField.Elem().Kind() == reflect.Struct)) && - subValidator != "-" { - var err error - structResult, err = ValidateStruct(valueField.Interface()) - if err != nil { - err = prependPathToErrors(err, key) - errs = append(errs, err) - } - } - resultField, err = typeCheck(valueField, reflect.StructField{ - Name: key, - PkgPath: "", - Type: val.Type(), - Tag: reflect.StructTag(fmt.Sprintf("%s:%q", tagName, subValidator)), - Offset: 0, - Index: []int{index}, - Anonymous: false, - }, val, nil) - if err != nil { - errs = append(errs, err) - } - case nil: - // already handlerd when checked before - default: - typeResult = false - err = fmt.Errorf("map validator has to be either map[string]interface{} or string; got %s", valueField.Type().String()) - err = prependPathToErrors(err, key) - errs = append(errs, err) - } - result = result && presentResult && typeResult && resultField && structResult && mapResult - index++ - } - // checks required keys - requiredResult := true - for key, value := range m { - if schema, ok := value.(string); ok { - tags := parseTagIntoMap(schema) - if required, ok := tags["required"]; ok { - if _, ok := s[key]; !ok { - requiredResult = false - if required.customErrorMessage != "" { - err = Error{key, fmt.Errorf(required.customErrorMessage), true, "required", []string{}} - } else { - err = Error{key, fmt.Errorf("required field missing"), false, "required", []string{}} - } - errs = append(errs, err) - } - } - } - } - - if len(errs) > 0 { - err = errs - } - return result && requiredResult, err -} - -// ValidateStruct use tags for fields. -// result will be equal to `false` if there are any errors. -// todo currently there is no guarantee that errors will be returned in predictable order (tests may to fail) -func ValidateStruct(s interface{}) (bool, error) { - if s == nil { - return true, nil - } - result := true - var err error - val := reflect.ValueOf(s) - if val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr { - val = val.Elem() - } - // we only accept structs - if val.Kind() != reflect.Struct { - return false, fmt.Errorf("function only accepts structs; got %s", val.Kind()) - } - var errs Errors - for i := 0; i < val.NumField(); i++ { - valueField := val.Field(i) - typeField := val.Type().Field(i) - if typeField.PkgPath != "" { - continue // Private field - } - structResult := true - if valueField.Kind() == reflect.Interface { - valueField = valueField.Elem() - } - if (valueField.Kind() == reflect.Struct || - (valueField.Kind() == reflect.Ptr && valueField.Elem().Kind() == reflect.Struct)) && - typeField.Tag.Get(tagName) != "-" { - var err error - structResult, err = ValidateStruct(valueField.Interface()) - if err != nil { - err = prependPathToErrors(err, typeField.Name) - errs = append(errs, err) - } - } - resultField, err2 := typeCheck(valueField, typeField, val, nil) - if err2 != nil { - - // Replace structure name with JSON name if there is a tag on the variable - jsonTag := toJSONName(typeField.Tag.Get("json")) - if jsonTag != "" { - switch jsonError := err2.(type) { - case Error: - jsonError.Name = jsonTag - err2 = jsonError - case Errors: - for i2, err3 := range jsonError { - switch customErr := err3.(type) { - case Error: - customErr.Name = jsonTag - jsonError[i2] = customErr - } - } - - err2 = jsonError - } - } - - errs = append(errs, err2) - } - result = result && resultField && structResult - } - if len(errs) > 0 { - err = errs - } - return result, err -} - -// ValidateStructAsync performs async validation of the struct and returns results through the channels -func ValidateStructAsync(s interface{}) (<-chan bool, <-chan error) { - res := make(chan bool) - errors := make(chan error) - - go func() { - defer close(res) - defer close(errors) - - isValid, isFailed := ValidateStruct(s) - - res <- isValid - errors <- isFailed - }() - - return res, errors -} - -// ValidateMapAsync performs async validation of the map and returns results through the channels -func ValidateMapAsync(s map[string]interface{}, m map[string]interface{}) (<-chan bool, <-chan error) { - res := make(chan bool) - errors := make(chan error) - - go func() { - defer close(res) - defer close(errors) - - isValid, isFailed := ValidateMap(s, m) - - res <- isValid - errors <- isFailed - }() - - return res, errors -} - -// parseTagIntoMap parses a struct tag `valid:required~Some error message,length(2|3)` into map[string]string{"required": "Some error message", "length(2|3)": ""} -func parseTagIntoMap(tag string) tagOptionsMap { - optionsMap := make(tagOptionsMap) - options := strings.Split(tag, ",") - - for i, option := range options { - option = strings.TrimSpace(option) - - validationOptions := strings.Split(option, "~") - if !isValidTag(validationOptions[0]) { - continue - } - if len(validationOptions) == 2 { - optionsMap[validationOptions[0]] = tagOption{validationOptions[0], validationOptions[1], i} - } else { - optionsMap[validationOptions[0]] = tagOption{validationOptions[0], "", i} - } - } - return optionsMap -} - -func isValidTag(s string) bool { - if s == "" { - return false - } - for _, c := range s { - switch { - case strings.ContainsRune("\\'\"!#$%&()*+-./:<=>?@[]^_{|}~ ", c): - // Backslash and quote chars are reserved, but - // otherwise any punctuation chars are allowed - // in a tag name. - default: - if !unicode.IsLetter(c) && !unicode.IsDigit(c) { - return false - } - } - } - return true -} - -// IsSSN will validate the given string as a U.S. Social Security Number -func IsSSN(str string) bool { - if str == "" || len(str) != 11 { - return false - } - return rxSSN.MatchString(str) -} - -// IsSemver checks if string is valid semantic version -func IsSemver(str string) bool { - return rxSemver.MatchString(str) -} - -// IsType checks if interface is of some type -func IsType(v interface{}, params ...string) bool { - if len(params) == 1 { - typ := params[0] - return strings.Replace(reflect.TypeOf(v).String(), " ", "", -1) == strings.Replace(typ, " ", "", -1) - } - return false -} - -// IsTime checks if string is valid according to given format -func IsTime(str string, format string) bool { - _, err := time.Parse(format, str) - return err == nil -} - -// IsUnixTime checks if string is valid unix timestamp value -func IsUnixTime(str string) bool { - if _, err := strconv.Atoi(str); err == nil { - return true - } - return false -} - -// IsRFC3339 checks if string is valid timestamp value according to RFC3339 -func IsRFC3339(str string) bool { - return IsTime(str, time.RFC3339) -} - -// IsRFC3339WithoutZone checks if string is valid timestamp value according to RFC3339 which excludes the timezone. -func IsRFC3339WithoutZone(str string) bool { - return IsTime(str, rfc3339WithoutZone) -} - -// IsISO4217 checks if string is valid ISO currency code -func IsISO4217(str string) bool { - for _, currency := range ISO4217List { - if str == currency { - return true - } - } - - return false -} - -// ByteLength checks string's length -func ByteLength(str string, params ...string) bool { - if len(params) == 2 { - min, _ := ToInt(params[0]) - max, _ := ToInt(params[1]) - return len(str) >= int(min) && len(str) <= int(max) - } - - return false -} - -// RuneLength checks string's length -// Alias for StringLength -func RuneLength(str string, params ...string) bool { - return StringLength(str, params...) -} - -// IsRsaPub checks whether string is valid RSA key -// Alias for IsRsaPublicKey -func IsRsaPub(str string, params ...string) bool { - if len(params) == 1 { - len, _ := ToInt(params[0]) - return IsRsaPublicKey(str, int(len)) - } - - return false -} - -// StringMatches checks if a string matches a given pattern. -func StringMatches(s string, params ...string) bool { - if len(params) == 1 { - pattern := params[0] - return Matches(s, pattern) - } - return false -} - -// StringLength checks string's length (including multi byte strings) -func StringLength(str string, params ...string) bool { - - if len(params) == 2 { - strLength := utf8.RuneCountInString(str) - min, _ := ToInt(params[0]) - max, _ := ToInt(params[1]) - return strLength >= int(min) && strLength <= int(max) - } - - return false -} - -// MinStringLength checks string's minimum length (including multi byte strings) -func MinStringLength(str string, params ...string) bool { - - if len(params) == 1 { - strLength := utf8.RuneCountInString(str) - min, _ := ToInt(params[0]) - return strLength >= int(min) - } - - return false -} - -// MaxStringLength checks string's maximum length (including multi byte strings) -func MaxStringLength(str string, params ...string) bool { - - if len(params) == 1 { - strLength := utf8.RuneCountInString(str) - max, _ := ToInt(params[0]) - return strLength <= int(max) - } - - return false -} - -// Range checks string's length -func Range(str string, params ...string) bool { - if len(params) == 2 { - value, _ := ToFloat(str) - min, _ := ToFloat(params[0]) - max, _ := ToFloat(params[1]) - return InRange(value, min, max) - } - - return false -} - -// IsInRaw checks if string is in list of allowed values -func IsInRaw(str string, params ...string) bool { - if len(params) == 1 { - rawParams := params[0] - - parsedParams := strings.Split(rawParams, "|") - - return IsIn(str, parsedParams...) - } - - return false -} - -// IsIn checks if string str is a member of the set of strings params -func IsIn(str string, params ...string) bool { - for _, param := range params { - if str == param { - return true - } - } - - return false -} - -func checkRequired(v reflect.Value, t reflect.StructField, options tagOptionsMap) (bool, error) { - if nilPtrAllowedByRequired { - k := v.Kind() - if (k == reflect.Ptr || k == reflect.Interface) && v.IsNil() { - return true, nil - } - } - - if requiredOption, isRequired := options["required"]; isRequired { - if len(requiredOption.customErrorMessage) > 0 { - return false, Error{t.Name, fmt.Errorf(requiredOption.customErrorMessage), true, "required", []string{}} - } - return false, Error{t.Name, fmt.Errorf("non zero value required"), false, "required", []string{}} - } else if _, isOptional := options["optional"]; fieldsRequiredByDefault && !isOptional { - return false, Error{t.Name, fmt.Errorf("Missing required field"), false, "required", []string{}} - } - // not required and empty is valid - return true, nil -} - -func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options tagOptionsMap) (isValid bool, resultErr error) { - if !v.IsValid() { - return false, nil - } - - tag := t.Tag.Get(tagName) - - // checks if the field should be ignored - switch tag { - case "": - if v.Kind() != reflect.Slice && v.Kind() != reflect.Map { - if !fieldsRequiredByDefault { - return true, nil - } - return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false, "required", []string{}} - } - case "-": - return true, nil - } - - isRootType := false - if options == nil { - isRootType = true - options = parseTagIntoMap(tag) - } - - if isEmptyValue(v) { - // an empty value is not validated, checks only required - isValid, resultErr = checkRequired(v, t, options) - for key := range options { - delete(options, key) - } - return isValid, resultErr - } - - var customTypeErrors Errors - optionsOrder := options.orderedKeys() - for _, validatorName := range optionsOrder { - validatorStruct := options[validatorName] - if validatefunc, ok := CustomTypeTagMap.Get(validatorName); ok { - delete(options, validatorName) - - if result := validatefunc(v.Interface(), o.Interface()); !result { - if len(validatorStruct.customErrorMessage) > 0 { - customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: TruncatingErrorf(validatorStruct.customErrorMessage, fmt.Sprint(v), validatorName), CustomErrorMessageExists: true, Validator: stripParams(validatorName)}) - continue - } - customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), validatorName), CustomErrorMessageExists: false, Validator: stripParams(validatorName)}) - } - } - } - - if len(customTypeErrors.Errors()) > 0 { - return false, customTypeErrors - } - - if isRootType { - // Ensure that we've checked the value by all specified validators before report that the value is valid - defer func() { - delete(options, "optional") - delete(options, "required") - - if isValid && resultErr == nil && len(options) != 0 { - optionsOrder := options.orderedKeys() - for _, validator := range optionsOrder { - isValid = false - resultErr = Error{t.Name, fmt.Errorf( - "The following validator is invalid or can't be applied to the field: %q", validator), false, stripParams(validator), []string{}} - return - } - } - }() - } - - for _, validatorSpec := range optionsOrder { - validatorStruct := options[validatorSpec] - var negate bool - validator := validatorSpec - customMsgExists := len(validatorStruct.customErrorMessage) > 0 - - // checks whether the tag looks like '!something' or 'something' - if validator[0] == '!' { - validator = validator[1:] - negate = true - } - - // checks for interface param validators - for key, value := range InterfaceParamTagRegexMap { - ps := value.FindStringSubmatch(validator) - if len(ps) == 0 { - continue - } - - validatefunc, ok := InterfaceParamTagMap[key] - if !ok { - continue - } - - delete(options, validatorSpec) - - field := fmt.Sprint(v) - if result := validatefunc(v.Interface(), ps[1:]...); (!result && !negate) || (result && negate) { - if customMsgExists { - return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}} - } - if negate { - return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}} - } - return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}} - } - } - } - - switch v.Kind() { - case reflect.Bool, - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, - reflect.Float32, reflect.Float64, - reflect.String: - // for each tag option checks the map of validator functions - for _, validatorSpec := range optionsOrder { - validatorStruct := options[validatorSpec] - var negate bool - validator := validatorSpec - customMsgExists := len(validatorStruct.customErrorMessage) > 0 - - // checks whether the tag looks like '!something' or 'something' - if validator[0] == '!' { - validator = validator[1:] - negate = true - } - - // checks for param validators - for key, value := range ParamTagRegexMap { - ps := value.FindStringSubmatch(validator) - if len(ps) == 0 { - continue - } - - validatefunc, ok := ParamTagMap[key] - if !ok { - continue - } - - delete(options, validatorSpec) - - switch v.Kind() { - case reflect.String, - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, - reflect.Float32, reflect.Float64: - - field := fmt.Sprint(v) // make value into string, then validate with regex - if result := validatefunc(field, ps[1:]...); (!result && !negate) || (result && negate) { - if customMsgExists { - return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}} - } - if negate { - return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}} - } - return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}} - } - default: - // type not yet supported, fail - return false, Error{t.Name, fmt.Errorf("Validator %s doesn't support kind %s", validator, v.Kind()), false, stripParams(validatorSpec), []string{}} - } - } - - if validatefunc, ok := TagMap[validator]; ok { - delete(options, validatorSpec) - - switch v.Kind() { - case reflect.String, - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, - reflect.Float32, reflect.Float64: - field := fmt.Sprint(v) // make value into string, then validate with regex - if result := validatefunc(field); !result && !negate || result && negate { - if customMsgExists { - return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}} - } - if negate { - return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}} - } - return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}} - } - default: - //Not Yet Supported Types (Fail here!) - err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", validator, v.Kind(), v) - return false, Error{t.Name, err, false, stripParams(validatorSpec), []string{}} - } - } - } - return true, nil - case reflect.Map: - if v.Type().Key().Kind() != reflect.String { - return false, &UnsupportedTypeError{v.Type()} - } - var sv stringValues - sv = v.MapKeys() - sort.Sort(sv) - result := true - for i, k := range sv { - var resultItem bool - var err error - if v.MapIndex(k).Kind() != reflect.Struct { - resultItem, err = typeCheck(v.MapIndex(k), t, o, options) - if err != nil { - return false, err - } - } else { - resultItem, err = ValidateStruct(v.MapIndex(k).Interface()) - if err != nil { - err = prependPathToErrors(err, t.Name+"."+sv[i].Interface().(string)) - return false, err - } - } - result = result && resultItem - } - return result, nil - case reflect.Slice, reflect.Array: - result := true - for i := 0; i < v.Len(); i++ { - var resultItem bool - var err error - if v.Index(i).Kind() != reflect.Struct { - resultItem, err = typeCheck(v.Index(i), t, o, options) - if err != nil { - return false, err - } - } else { - resultItem, err = ValidateStruct(v.Index(i).Interface()) - if err != nil { - err = prependPathToErrors(err, t.Name+"."+strconv.Itoa(i)) - return false, err - } - } - result = result && resultItem - } - return result, nil - case reflect.Interface: - // If the value is an interface then encode its element - if v.IsNil() { - return true, nil - } - return ValidateStruct(v.Interface()) - case reflect.Ptr: - // If the value is a pointer then checks its element - if v.IsNil() { - return true, nil - } - return typeCheck(v.Elem(), t, o, options) - case reflect.Struct: - return true, nil - default: - return false, &UnsupportedTypeError{v.Type()} - } -} - -func stripParams(validatorString string) string { - return paramsRegexp.ReplaceAllString(validatorString, "") -} - -// isEmptyValue checks whether value empty or not -func isEmptyValue(v reflect.Value) bool { - switch v.Kind() { - case reflect.String, reflect.Array: - return v.Len() == 0 - case reflect.Map, reflect.Slice: - return v.Len() == 0 || v.IsNil() - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - } - - return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) -} - -// ErrorByField returns error for specified field of the struct -// validated by ValidateStruct or empty string if there are no errors -// or this field doesn't exists or doesn't have any errors. -func ErrorByField(e error, field string) string { - if e == nil { - return "" - } - return ErrorsByField(e)[field] -} - -// ErrorsByField returns map of errors of the struct validated -// by ValidateStruct or empty map if there are no errors. -func ErrorsByField(e error) map[string]string { - m := make(map[string]string) - if e == nil { - return m - } - // prototype for ValidateStruct - - switch e := e.(type) { - case Error: - m[e.Name] = e.Err.Error() - case Errors: - for _, item := range e.Errors() { - n := ErrorsByField(item) - for k, v := range n { - m[k] = v - } - } - } - - return m -} - -// Error returns string equivalent for reflect.Type -func (e *UnsupportedTypeError) Error() string { - return "validator: unsupported type: " + e.Type.String() -} - -func (sv stringValues) Len() int { return len(sv) } -func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } -func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) } -func (sv stringValues) get(i int) string { return sv[i].String() } diff --git a/vendor/github.com/asaskevich/govalidator/wercker.yml b/vendor/github.com/asaskevich/govalidator/wercker.yml deleted file mode 100644 index bc5f7b08..00000000 --- a/vendor/github.com/asaskevich/govalidator/wercker.yml +++ /dev/null @@ -1,15 +0,0 @@ -box: golang -build: - steps: - - setup-go-workspace - - - script: - name: go get - code: | - go version - go get -t ./... - - - script: - name: go test - code: | - go test -race -v ./... diff --git a/vendor/modules.txt b/vendor/modules.txt index 3d7a282e..3f9b92de 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -44,9 +44,6 @@ github.com/Microsoft/hcsshim/pkg/ociwclayer # github.com/Sabayon/pkgs-checker v0.8.4 ## explicit github.com/Sabayon/pkgs-checker/pkg/gentoo -# github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef -## explicit -github.com/asaskevich/govalidator # github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154 ## explicit github.com/asdine/storm