mirror of
https://github.com/mudler/luet.git
synced 2025-09-02 07:45:02 +00:00
Compare commits
130 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
498edc95c8 | ||
|
b81ce66914 | ||
|
68030baf98 | ||
|
9e868b69fc | ||
|
f871111e50 | ||
|
981fe5b04a | ||
|
8371d7aa7b | ||
|
736c9470cf | ||
|
e52bc4f2b2 | ||
|
96e877fc0b | ||
|
1331c3551a | ||
|
bfb2bdc230 | ||
|
525bfb5ebf | ||
|
f4e2f32aff | ||
|
7cf650a8f6 | ||
|
2b6fe2baa1 | ||
|
34bba0319b | ||
|
71c06913aa | ||
|
f0fae82ad9 | ||
|
93f5f5d0b2 | ||
|
1c9b821058 | ||
|
0e21548bc0 | ||
|
39c8895f80 | ||
|
720441be4c | ||
|
5082749e90 | ||
|
ce169f49af | ||
|
921869d04c | ||
|
8e1a457bf1 | ||
|
d5cfadfded | ||
|
193f6872a0 | ||
|
0b9b3c0488 | ||
|
70f05f41e8 | ||
|
ef034d87b0 | ||
|
6a86bf3f04 | ||
|
265e2371b4 | ||
|
78442c91fc | ||
|
d97e606a31 | ||
|
95da20e366 | ||
|
797a34ba49 | ||
|
fdba8dea71 | ||
|
a1453b7242 | ||
|
7d4b612173 | ||
|
9eef7e5c6d | ||
|
332824fd42 | ||
|
737fbdbdc1 | ||
|
f109bab2b4 | ||
|
d472dee19b | ||
|
b5990b5333 | ||
|
767488327b | ||
|
be3933998b | ||
|
fa9dc9da53 | ||
|
9911888d18 | ||
|
2906180c43 | ||
|
cf5e4e1305 | ||
|
519586f6bc | ||
|
6dbc422b8f | ||
|
a3cfebf438 | ||
|
24201b25ef | ||
|
7c53296530 | ||
|
a3cb0ed17f | ||
|
9ca5d24856 | ||
|
9a34296be0 | ||
|
ebd18ae22c | ||
|
7f10a19be5 | ||
|
6bf7368993 | ||
|
338f310d67 | ||
|
3fd1bdbfc8 | ||
|
59d78c3f5c | ||
|
86c256a062 | ||
|
876e3659fb | ||
|
3c0dd2b71d | ||
|
e9b4d66a3e | ||
|
5047316b70 | ||
|
02edc10c58 | ||
|
d479ada402 | ||
|
7b800c9a20 | ||
|
18e6e085d5 | ||
|
6d19f8d2cc | ||
|
67c43eb936 | ||
|
cf80e5fc09 | ||
|
d668d8344b | ||
|
b17ac447f1 | ||
|
c8bcd88f1f | ||
|
034fb54c25 | ||
|
6dbf19f085 | ||
|
43db64c089 | ||
|
9423b7c1e3 | ||
|
75dbc2dcb4 | ||
|
f3e2e0a184 | ||
|
8237506bd3 | ||
|
9784d6192a | ||
|
87004c8e78 | ||
|
0fe30ddcfd | ||
|
44d33eceba | ||
|
ca994b07ab | ||
|
8ce135fe12 | ||
|
18d9366bca | ||
|
c0206e5849 | ||
|
9fab46aa9e | ||
|
5b54aeb822 | ||
|
7a10ff2742 | ||
|
db1b190fb5 | ||
|
b349665ff2 | ||
|
3959cfd623 | ||
|
53ab0e0dd2 | ||
|
651ea17548 | ||
|
60d5c9dfd5 | ||
|
1f807f369a | ||
|
4e1b006a08 | ||
|
47f0049efa | ||
|
0cc2b72831 | ||
|
f2df3faee5 | ||
|
287098f101 | ||
|
f9a7113ab9 | ||
|
c3559d952c | ||
|
fc863fc8e5 | ||
|
ac149e9336 | ||
|
b9c8e50e42 | ||
|
cf7df00a65 | ||
|
83f924da35 | ||
|
c82d23f9f2 | ||
|
0e46e763d5 | ||
|
a793b44e83 | ||
|
19e6054574 | ||
|
a8624fe451 | ||
|
14c1d6ef24 | ||
|
36c58307e2 | ||
|
665261e526 | ||
|
794c5984a2 | ||
|
a765147c1d |
39
README.md
39
README.md
@@ -1,13 +1,14 @@
|
||||
# luet - Container-based Package manager
|
||||
|
||||
[](https://quay.io/repository/luet/base)
|
||||
[](https://goreportcard.com/report/github.com/mudler/luet)
|
||||
[](https://travis-ci.org/mudler/luet)
|
||||
[](https://godoc.org/github.com/mudler/luet)
|
||||
[](https://codecov.io/gh/mudler/luet)
|
||||
|
||||
Luet is a multi-platform Package Manager based off from containers - it uses Docker (and other tech) to sandbox your builds and generate packages from them. It has zero dependencies and it is well suitable for "from scratch" environments. It can also version entire rootfs and enables delivery of OTA-alike updates, making it a perfect fit for the Edge computing era and IoT embedded devices.
|
||||
Luet is a multi-platform Package Manager based off from containers - it uses Docker (and others) to build packages. It has zero dependencies and it is well suitable for "from scratch" environments. It can also version entire rootfs and enables delivery of OTA-alike updates, making it a perfect fit for the Edge computing era and IoT embedded devices.
|
||||
|
||||
It offers a simple [specfile format](https://luet-lab.github.io/docs/docs/concepts/specfile/) in YAML notation to define both packages and rootfs. As it is based on containers, it can be used to build seed stages for Linux From Scratch installations and it can build and track updates for those systems.
|
||||
It offers a simple [specfile format](https://luet-lab.github.io/docs/docs/concepts/packages/specfile/) in YAML notation to define both [packages](https://luet-lab.github.io/docs/docs/concepts/packages/) and [rootfs](https://luet-lab.github.io/docs/docs/concepts/packages/#package-layers). As it is based on containers, it can be also used to build stages for Linux From Scratch installations and it can build and track updates for those systems.
|
||||
|
||||
It is written entirely in Golang and where used as package manager, it can run in from scratch environment, with zero dependencies.
|
||||
|
||||
@@ -16,20 +17,36 @@ It is written entirely in Golang and where used as package manager, it can run i
|
||||
- Luet can reuse Gentoo's portage tree hierarchy, and it is heavily inspired from it.
|
||||
- It builds, installs, uninstalls and perform upgrades on machines
|
||||
- Installer doesn't depend on anything ( 0 dep installer !), statically built
|
||||
- You can install it aside also with your current distro package manager, and start building and distributing your packages
|
||||
- Support for packages as "layers"
|
||||
- It uses SAT solving techniques to solve the deptree ( Inspired by [OPIUM](https://ranjitjhala.github.io/static/opium.pdf) )
|
||||
- [It uses SAT solving techniques to solve the deptree](https://luet-lab.github.io/docs/docs/concepts/constraints/) ( Inspired by [OPIUM](https://ranjitjhala.github.io/static/opium.pdf) )
|
||||
- Support for [collections](https://luet-lab.github.io/docs/docs/concepts/packages/collections/) and [templated package definitions](https://luet-lab.github.io/docs/docs/concepts/packages/templates/)
|
||||
- [Can be extended with Plugins and Extensions](https://luet-lab.github.io/docs/docs/concepts/plugins-and-extensions/)
|
||||
- [Can build packages in Kubernetes (experimental)](https://github.com/mudler/luet-k8s)
|
||||
|
||||
## Install
|
||||
|
||||
To install luet, you can grab a release on the [Release page](https://github.com/mudler/luet/releases) or compile it in your machine (requires Golang installed):
|
||||
To install luet, you can grab a release on the [Release page](https://github.com/mudler/luet/releases) or to install it in your system:
|
||||
|
||||
$ git clone https://github.com/mudler/luet.git
|
||||
$ cd luet
|
||||
$ make build
|
||||
```bash
|
||||
$ curl https://get.mocaccino.org/luet/get_luet_root.sh | sudo sh
|
||||
$ luet search ...
|
||||
$ luet install ..
|
||||
$ luet --help
|
||||
```
|
||||
|
||||
## Status
|
||||
## Build from source
|
||||
|
||||
Luet is not feature-complete yet, it can build, install/uninstall/upgrade packages - but it doesn't support yet all the features you would normally expect from a Package Manager nowadays.
|
||||
```bash
|
||||
$ git clone https://github.com/mudler/luet.git
|
||||
$ cd luet
|
||||
$ make build
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
[Documentation](https://luet-lab.github.io/docs) is available, or
|
||||
run `luet --help`, any subcommand is documented as well, try e.g.: `luet build --help`.
|
||||
|
||||
# Dependency solving
|
||||
|
||||
@@ -48,10 +65,6 @@ when they arises while trying to validate your queries against the system model.
|
||||
|
||||
To leverage it, simply pass ```--solver-type qlearning``` to the subcommands that supports it ( you can check out by invoking ```--help``` ).
|
||||
|
||||
## Documentation
|
||||
|
||||
[Documentation](https://luet-lab.github.io/docs) is available, or
|
||||
run `luet --help`, any subcommand is documented as well, try e.g.: `luet build --help`.
|
||||
|
||||
## Authors
|
||||
|
||||
|
44
cmd/build.go
44
cmd/build.go
@@ -36,9 +36,30 @@ import (
|
||||
var buildCmd = &cobra.Command{
|
||||
Use: "build <package name> <package name> <package name> ...",
|
||||
Short: "build a package or a tree",
|
||||
Long: `build packages or trees from luet tree definitions. Packages are in [category]/[name]-[version] form`,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
viper.BindPFlag("clean", cmd.Flags().Lookup("clean"))
|
||||
Long: `Builds one or more packages from a tree (current directory is implied):
|
||||
|
||||
$ luet build utils/busybox utils/yq ...
|
||||
|
||||
Builds all packages
|
||||
|
||||
$ luet build --all
|
||||
|
||||
Builds only the leaf packages:
|
||||
|
||||
$ luet build --full
|
||||
|
||||
Build package revdeps:
|
||||
|
||||
$ luet build --revdeps utils/yq
|
||||
|
||||
Build package without dependencies (needs the images already in the host, or either need to be available online):
|
||||
|
||||
$ luet build --nodeps utils/yq ...
|
||||
|
||||
Build packages specifying multiple definition trees:
|
||||
|
||||
$ luet build --tree overlay/path --tree overlay/path2 utils/yq ...
|
||||
`, PreRun: func(cmd *cobra.Command, args []string) {
|
||||
viper.BindPFlag("tree", cmd.Flags().Lookup("tree"))
|
||||
viper.BindPFlag("destination", cmd.Flags().Lookup("destination"))
|
||||
viper.BindPFlag("backend", cmd.Flags().Lookup("backend"))
|
||||
@@ -49,10 +70,12 @@ var buildCmd = &cobra.Command{
|
||||
viper.BindPFlag("compression", cmd.Flags().Lookup("compression"))
|
||||
viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
|
||||
viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
|
||||
viper.BindPFlag("values", cmd.Flags().Lookup("values"))
|
||||
|
||||
viper.BindPFlag("image-repository", cmd.Flags().Lookup("image-repository"))
|
||||
viper.BindPFlag("push", cmd.Flags().Lookup("push"))
|
||||
viper.BindPFlag("pull", cmd.Flags().Lookup("pull"))
|
||||
viper.BindPFlag("wait", cmd.Flags().Lookup("wait"))
|
||||
viper.BindPFlag("keep-images", cmd.Flags().Lookup("keep-images"))
|
||||
|
||||
LuetCfg.Viper.BindPFlag("keep-exported-images", cmd.Flags().Lookup("keep-exported-images"))
|
||||
@@ -64,7 +87,6 @@ var buildCmd = &cobra.Command{
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
clean := viper.GetBool("clean")
|
||||
treePaths := viper.GetStringSlice("tree")
|
||||
dst := viper.GetString("destination")
|
||||
concurrency := LuetCfg.GetGeneral().Concurrency
|
||||
@@ -75,6 +97,8 @@ var buildCmd = &cobra.Command{
|
||||
databaseType := viper.GetString("database")
|
||||
compressionType := viper.GetString("compression")
|
||||
imageRepository := viper.GetString("image-repository")
|
||||
values := viper.GetString("values")
|
||||
wait := viper.GetBool("wait")
|
||||
push := viper.GetBool("push")
|
||||
pull := viper.GetBool("pull")
|
||||
keepImages := viper.GetBool("keep-images")
|
||||
@@ -83,7 +107,6 @@ var buildCmd = &cobra.Command{
|
||||
keepExportedImages := viper.GetBool("keep-exported-images")
|
||||
onlyTarget, _ := cmd.Flags().GetBool("only-target-package")
|
||||
full, _ := cmd.Flags().GetBool("full")
|
||||
skip, _ := cmd.Flags().GetBool("skip-if-metadata-exists")
|
||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||
var results Results
|
||||
|
||||
@@ -148,16 +171,15 @@ var buildCmd = &cobra.Command{
|
||||
opts := compiler.NewDefaultCompilerOptions()
|
||||
opts.SolverOptions = *LuetCfg.GetSolverOptions()
|
||||
opts.ImageRepository = imageRepository
|
||||
opts.Clean = clean
|
||||
opts.PullFirst = pull
|
||||
opts.KeepImg = keepImages
|
||||
opts.Push = push
|
||||
opts.OnlyDeps = onlydeps
|
||||
opts.NoDeps = nodeps
|
||||
opts.Wait = wait
|
||||
opts.KeepImageExport = keepExportedImages
|
||||
opts.SkipIfMetadataExists = skip
|
||||
opts.PackageTargetOnly = onlyTarget
|
||||
|
||||
opts.BuildValuesFile = values
|
||||
var solverOpts solver.Options
|
||||
if concurrent {
|
||||
solverOpts = solver.Options{Type: solver.ParallelSimple, Concurrency: concurrency}
|
||||
@@ -283,7 +305,6 @@ func init() {
|
||||
if err != nil {
|
||||
Fatal(err)
|
||||
}
|
||||
buildCmd.Flags().Bool("clean", true, "Build all packages without considering the packages present in the build directory")
|
||||
buildCmd.Flags().StringSliceP("tree", "t", []string{}, "Path of the tree to use.")
|
||||
buildCmd.Flags().String("backend", "docker", "backend used (docker,img)")
|
||||
buildCmd.Flags().Bool("privileged", false, "Privileged (Keep permissions)")
|
||||
@@ -291,17 +312,18 @@ func init() {
|
||||
buildCmd.Flags().Bool("revdeps", false, "Build with revdeps")
|
||||
buildCmd.Flags().Bool("all", false, "Build all specfiles in the tree")
|
||||
buildCmd.Flags().Bool("full", false, "Build all packages (optimized)")
|
||||
buildCmd.Flags().String("values", "", "Build values file to interpolate with each package")
|
||||
|
||||
buildCmd.Flags().String("destination", path, "Destination folder")
|
||||
buildCmd.Flags().String("compression", "none", "Compression alg: none, gzip")
|
||||
buildCmd.Flags().String("compression", "none", "Compression alg: none, gzip, zstd")
|
||||
buildCmd.Flags().String("image-repository", "luet/cache", "Default base image string for generated image")
|
||||
buildCmd.Flags().Bool("push", false, "Push images to a hub")
|
||||
buildCmd.Flags().Bool("pull", false, "Pull images from a hub")
|
||||
buildCmd.Flags().Bool("wait", false, "Don't build all intermediate images, but wait for them until they are available")
|
||||
buildCmd.Flags().Bool("keep-images", true, "Keep built docker images in the host")
|
||||
buildCmd.Flags().Bool("nodeps", false, "Build only the target packages, skipping deps (it works only if you already built the deps locally, or by using --pull) ")
|
||||
buildCmd.Flags().Bool("onlydeps", false, "Build only package dependencies")
|
||||
buildCmd.Flags().Bool("keep-exported-images", false, "Keep exported images used during building")
|
||||
buildCmd.Flags().Bool("skip-if-metadata-exists", false, "Skip package if metadata exists")
|
||||
buildCmd.Flags().Bool("only-target-package", false, "Build packages of only the required target. Otherwise builds all the necessary ones not present in the destination")
|
||||
buildCmd.Flags().String("solver-type", "", "Solver strategy")
|
||||
buildCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
||||
|
101
cmd/convert.go
101
cmd/convert.go
@@ -1,101 +0,0 @@
|
||||
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
tree "github.com/mudler/luet/pkg/tree"
|
||||
|
||||
"github.com/mudler/luet/pkg/tree/builder/gentoo"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var convertCmd = &cobra.Command{
|
||||
Use: "convert [portage-tree] [luet-tree]",
|
||||
Short: "convert other package manager tree into luet",
|
||||
Long: `Parses external PM and produces a luet parsable tree`,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
viper.BindPFlag("type", cmd.Flags().Lookup("type"))
|
||||
viper.BindPFlag("database", cmd.Flags().Lookup("database"))
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
t := viper.GetString("type")
|
||||
databaseType := viper.GetString("database")
|
||||
var db pkg.PackageDatabase
|
||||
|
||||
if len(args) != 2 {
|
||||
Fatal("Incorrect number of arguments")
|
||||
}
|
||||
|
||||
input := args[0]
|
||||
output := args[1]
|
||||
Info("Converting trees from " + input + " [" + t + "]")
|
||||
|
||||
var builder tree.Parser
|
||||
switch t {
|
||||
case "gentoo":
|
||||
builder = gentoo.NewGentooBuilder(
|
||||
&gentoo.SimpleEbuildParser{},
|
||||
LuetCfg.GetGeneral().Concurrency,
|
||||
gentoo.InMemory)
|
||||
default: // dup
|
||||
builder = gentoo.NewGentooBuilder(
|
||||
&gentoo.SimpleEbuildParser{},
|
||||
LuetCfg.GetGeneral().Concurrency,
|
||||
gentoo.InMemory)
|
||||
}
|
||||
|
||||
switch databaseType {
|
||||
case "memory":
|
||||
db = pkg.NewInMemoryDatabase(false)
|
||||
case "boltdb":
|
||||
tmpdir, err := ioutil.TempDir("", "package")
|
||||
if err != nil {
|
||||
Fatal(err)
|
||||
}
|
||||
db = pkg.NewBoltDatabase(tmpdir)
|
||||
}
|
||||
defer db.Clean()
|
||||
|
||||
packageTree, err := builder.Generate(input)
|
||||
if err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
}
|
||||
|
||||
defer packageTree.Clean()
|
||||
Info("Tree generated")
|
||||
|
||||
generalRecipe := tree.NewGeneralRecipe(packageTree)
|
||||
Info("Saving generated tree to " + output)
|
||||
|
||||
err = generalRecipe.Save(output)
|
||||
if err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
convertCmd.Flags().String("type", "gentoo", "source type")
|
||||
convertCmd.Flags().String("database", "memory", "database used for solving (memory,boltdb)")
|
||||
|
||||
RootCmd.AddCommand(convertCmd)
|
||||
}
|
@@ -30,7 +30,26 @@ import (
|
||||
var createrepoCmd = &cobra.Command{
|
||||
Use: "create-repo",
|
||||
Short: "Create a luet repository from a build",
|
||||
Long: `Generate and renew repository metadata`,
|
||||
Long: `Builds tree metadata from a set of packages and a tree definition:
|
||||
|
||||
$ luet create-repo
|
||||
|
||||
Provide specific paths for packages, tree, and metadata output which is generated:
|
||||
|
||||
$ luet create-repo --packages my/packages/path --tree my/tree/path --output my/packages/path ...
|
||||
|
||||
Provide name and description of the repository:
|
||||
|
||||
$ luet create-repo --name "foo" --description "bar" ...
|
||||
|
||||
Change compression method:
|
||||
|
||||
$ luet create-repo --tree-compression gzip --meta-compression gzip
|
||||
|
||||
Create a repository from the metadata description defined in the luet.yaml config file:
|
||||
|
||||
$ luet create-repo --repo repository1
|
||||
`,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
viper.BindPFlag("packages", cmd.Flags().Lookup("packages"))
|
||||
viper.BindPFlag("tree", cmd.Flags().Lookup("tree"))
|
||||
@@ -140,9 +159,9 @@ func init() {
|
||||
createrepoCmd.Flags().Bool("reset-revision", false, "Reset repository revision.")
|
||||
createrepoCmd.Flags().String("repo", "", "Use repository defined in configuration.")
|
||||
|
||||
createrepoCmd.Flags().String("tree-compression", "gzip", "Compression alg: none, gzip")
|
||||
createrepoCmd.Flags().String("tree-compression", "gzip", "Compression alg: none, gzip, zstd")
|
||||
createrepoCmd.Flags().String("tree-filename", installer.TREE_TARBALL, "Repository tree filename")
|
||||
createrepoCmd.Flags().String("meta-compression", "none", "Compression alg: none, gzip")
|
||||
createrepoCmd.Flags().String("meta-compression", "none", "Compression alg: none, gzip, zstd")
|
||||
createrepoCmd.Flags().String("meta-filename", installer.REPOSITORY_METAFILE+".tar", "Repository metadata filename")
|
||||
|
||||
RootCmd.AddCommand(createrepoCmd)
|
||||
|
@@ -25,6 +25,10 @@ import (
|
||||
var databaseGroupCmd = &cobra.Command{
|
||||
Use: "database [command] [OPTIONS]",
|
||||
Short: "Manage system database (dangerous commands ahead!)",
|
||||
Long: `Allows to manipulate Luet internal database of installed packages. Use with caution!
|
||||
|
||||
Removing packages by hand from the database can result in a broken system, and thus it's not reccomended.
|
||||
`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@@ -17,7 +17,6 @@ package cmd_database
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/mudler/luet/pkg/compiler"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
@@ -32,7 +31,18 @@ func NewDatabaseCreateCommand() *cobra.Command {
|
||||
var ans = &cobra.Command{
|
||||
Use: "create <artifact_metadata1.yaml> <artifact_metadata1.yaml>",
|
||||
Short: "Insert a package in the system DB",
|
||||
Args: cobra.OnlyValidArgs,
|
||||
Long: `Inserts a package in the system database:
|
||||
|
||||
$ luet database create foo.yaml
|
||||
|
||||
"luet database create" injects a package in the system database without actually installing it, use it with caution.
|
||||
|
||||
This commands takes multiple yaml input file representing package artifacts, that are usually generated while building packages.
|
||||
|
||||
The yaml must contain the package definition, and the file list at least.
|
||||
|
||||
For reference, inspect a "metadata.yaml" file generated while running "luet build"`,
|
||||
Args: cobra.OnlyValidArgs,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||
@@ -40,7 +50,7 @@ func NewDatabaseCreateCommand() *cobra.Command {
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
var systemDB pkg.PackageDatabase
|
||||
systemDB := LuetCfg.GetSystemDB()
|
||||
|
||||
for _, a := range args {
|
||||
dat, err := ioutil.ReadFile(a)
|
||||
@@ -52,13 +62,6 @@ func NewDatabaseCreateCommand() *cobra.Command {
|
||||
Fatal("Failed reading yaml ", a, ": ", err.Error())
|
||||
}
|
||||
|
||||
if LuetCfg.GetSystem().DatabaseEngine == "boltdb" {
|
||||
systemDB = pkg.NewBoltDatabase(
|
||||
filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
|
||||
} else {
|
||||
systemDB = pkg.NewInMemoryDatabase(true)
|
||||
}
|
||||
|
||||
files := art.GetFiles()
|
||||
|
||||
if _, err := systemDB.CreatePackage(art.GetCompileSpec().GetPackage()); err != nil {
|
||||
|
@@ -16,13 +16,10 @@
|
||||
package cmd_database
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
|
||||
helpers "github.com/mudler/luet/cmd/helpers"
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -31,14 +28,20 @@ func NewDatabaseRemoveCommand() *cobra.Command {
|
||||
var ans = &cobra.Command{
|
||||
Use: "remove [package1] [package2] ...",
|
||||
Short: "Remove a package from the system DB (forcefully - you normally don't want to do that)",
|
||||
Args: cobra.OnlyValidArgs,
|
||||
Long: `Removes a package in the system database without actually uninstalling it:
|
||||
|
||||
$ luet database remove foo/bar
|
||||
|
||||
This commands takes multiple packages as arguments and prunes their entries from the system database.
|
||||
`,
|
||||
Args: cobra.OnlyValidArgs,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var systemDB pkg.PackageDatabase
|
||||
systemDB := LuetCfg.GetSystemDB()
|
||||
|
||||
for _, a := range args {
|
||||
pack, err := helpers.ParsePackageStr(a)
|
||||
@@ -46,13 +49,6 @@ func NewDatabaseRemoveCommand() *cobra.Command {
|
||||
Fatal("Invalid package string ", a, ": ", err.Error())
|
||||
}
|
||||
|
||||
if LuetCfg.GetSystem().DatabaseEngine == "boltdb" {
|
||||
systemDB = pkg.NewBoltDatabase(
|
||||
filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
|
||||
} else {
|
||||
systemDB = pkg.NewInMemoryDatabase(true)
|
||||
}
|
||||
|
||||
if err := systemDB.RemovePackage(pack); err != nil {
|
||||
Fatal("Failed removing ", a, ": ", err.Error())
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
_gentoo "github.com/Sabayon/pkgs-checker/pkg/gentoo"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
@@ -41,7 +42,41 @@ func CreateRegexArray(rgx []string) ([]*regexp.Regexp, error) {
|
||||
return ans, nil
|
||||
}
|
||||
|
||||
func packageData(p string) (string, string) {
|
||||
cat := ""
|
||||
name := ""
|
||||
if strings.Contains(p, "/") {
|
||||
packagedata := strings.Split(p, "/")
|
||||
cat = packagedata[0]
|
||||
name = packagedata[1]
|
||||
} else {
|
||||
name = p
|
||||
}
|
||||
return cat, name
|
||||
}
|
||||
func ParsePackageStr(p string) (*pkg.DefaultPackage, error) {
|
||||
|
||||
if !strings.HasPrefix(p, "=") {
|
||||
ver := ">=0"
|
||||
cat := ""
|
||||
name := ""
|
||||
|
||||
if strings.Contains(p, "@") {
|
||||
packageinfo := strings.Split(p, "@")
|
||||
ver = packageinfo[1]
|
||||
cat, name = packageData(packageinfo[0])
|
||||
} else {
|
||||
cat, name = packageData(p)
|
||||
}
|
||||
|
||||
return &pkg.DefaultPackage{
|
||||
Name: name,
|
||||
Category: cat,
|
||||
Version: ver,
|
||||
Uri: make([]string, 0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
gp, err := _gentoo.ParsePackageStr(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -13,7 +13,7 @@
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package gentoo_test
|
||||
package cmd_helpers_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -25,8 +25,8 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestGentooBuilder(t *testing.T) {
|
||||
func TestSolver(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
LoadConfig(config.LuetCfg)
|
||||
RunSpecs(t, "Gentoo Suite")
|
||||
RunSpecs(t, "CLI helpers test Suite")
|
||||
}
|
70
cmd/helpers/cli_test.go
Normal file
70
cmd/helpers/cli_test.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd_helpers_test
|
||||
|
||||
import (
|
||||
. "github.com/mudler/luet/cmd/helpers"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("CLI Helpers", func() {
|
||||
Context("Can parse package strings correctly", func() {
|
||||
It("accept single package names", func() {
|
||||
pack, err := ParsePackageStr("foo")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(pack.GetName()).To(Equal("foo"))
|
||||
Expect(pack.GetCategory()).To(Equal(""))
|
||||
Expect(pack.GetVersion()).To(Equal(">=0"))
|
||||
})
|
||||
It("accept unversioned packages with category", func() {
|
||||
pack, err := ParsePackageStr("cat/foo")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(pack.GetName()).To(Equal("foo"))
|
||||
Expect(pack.GetCategory()).To(Equal("cat"))
|
||||
Expect(pack.GetVersion()).To(Equal(">=0"))
|
||||
})
|
||||
It("accept versioned packages with category", func() {
|
||||
pack, err := ParsePackageStr("cat/foo@1.1")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(pack.GetName()).To(Equal("foo"))
|
||||
Expect(pack.GetCategory()).To(Equal("cat"))
|
||||
Expect(pack.GetVersion()).To(Equal("1.1"))
|
||||
})
|
||||
It("accept versioned ranges with category", func() {
|
||||
pack, err := ParsePackageStr("cat/foo@>=1.1")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(pack.GetName()).To(Equal("foo"))
|
||||
Expect(pack.GetCategory()).To(Equal("cat"))
|
||||
Expect(pack.GetVersion()).To(Equal(">=1.1"))
|
||||
})
|
||||
It("accept gentoo regex parsing without versions", func() {
|
||||
pack, err := ParsePackageStr("=cat/foo")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(pack.GetName()).To(Equal("foo"))
|
||||
Expect(pack.GetCategory()).To(Equal("cat"))
|
||||
Expect(pack.GetVersion()).To(Equal(">=0"))
|
||||
})
|
||||
It("accept gentoo regex parsing with versions", func() {
|
||||
pack, err := ParsePackageStr("=cat/foo-1.2")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(pack.GetName()).To(Equal("foo"))
|
||||
Expect(pack.GetCategory()).To(Equal("cat"))
|
||||
Expect(pack.GetVersion()).To(Equal("1.2"))
|
||||
})
|
||||
})
|
||||
})
|
@@ -16,7 +16,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
installer "github.com/mudler/luet/pkg/installer"
|
||||
"github.com/mudler/luet/pkg/solver"
|
||||
@@ -30,8 +29,24 @@ import (
|
||||
)
|
||||
|
||||
var installCmd = &cobra.Command{
|
||||
Use: "install <pkg1> <pkg2> ...",
|
||||
Short: "Install a package",
|
||||
Use: "install <pkg1> <pkg2> ...",
|
||||
Short: "Install a package",
|
||||
Long: `Installs one or more packages without asking questions:
|
||||
|
||||
$ luet install -y utils/busybox utils/yq ...
|
||||
|
||||
To install only deps of a package:
|
||||
|
||||
$ luet install --onlydeps utils/busybox ...
|
||||
|
||||
To not install deps of a package:
|
||||
|
||||
$ luet install --nodeps utils/busybox ...
|
||||
|
||||
To force install a package:
|
||||
|
||||
$ luet install --force utils/busybox ...
|
||||
`,
|
||||
Aliases: []string{"i"},
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||
@@ -43,11 +58,10 @@ var installCmd = &cobra.Command{
|
||||
LuetCfg.Viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
|
||||
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
|
||||
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
||||
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
|
||||
},
|
||||
Long: `Install packages in parallel`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var toInstall pkg.Packages
|
||||
var systemDB pkg.PackageDatabase
|
||||
|
||||
for _, a := range args {
|
||||
pack, err := helpers.ParsePackageStr(a)
|
||||
@@ -75,6 +89,7 @@ var installCmd = &cobra.Command{
|
||||
nodeps := LuetCfg.Viper.GetBool("nodeps")
|
||||
onlydeps := LuetCfg.Viper.GetBool("onlydeps")
|
||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||
yes := LuetCfg.Viper.GetBool("yes")
|
||||
|
||||
LuetCfg.GetSolverOptions().Type = stype
|
||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||
@@ -99,16 +114,11 @@ var installCmd = &cobra.Command{
|
||||
Force: force,
|
||||
OnlyDeps: onlydeps,
|
||||
PreserveSystemEssentialData: true,
|
||||
Ask: !yes,
|
||||
})
|
||||
inst.Repositories(repos)
|
||||
|
||||
if LuetCfg.GetSystem().DatabaseEngine == "boltdb" {
|
||||
systemDB = pkg.NewBoltDatabase(
|
||||
filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
|
||||
} else {
|
||||
systemDB = pkg.NewInMemoryDatabase(true)
|
||||
}
|
||||
system := &installer.System{Database: systemDB, Target: LuetCfg.GetSystem().Rootfs}
|
||||
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs}
|
||||
err := inst.Install(toInstall, system)
|
||||
if err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
@@ -131,6 +141,7 @@ func init() {
|
||||
installCmd.Flags().Bool("onlydeps", false, "Consider **only** package dependencies")
|
||||
installCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
|
||||
installCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
|
||||
installCmd.Flags().BoolP("yes", "y", false, "Don't ask questions")
|
||||
|
||||
RootCmd.AddCommand(installCmd)
|
||||
}
|
||||
|
98
cmd/pack.go
Normal file
98
cmd/pack.go
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
helpers "github.com/mudler/luet/cmd/helpers"
|
||||
"github.com/mudler/luet/pkg/compiler"
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var packCmd = &cobra.Command{
|
||||
Use: "pack <package name>",
|
||||
Short: "pack a custom package",
|
||||
Long: `Pack creates a package from a directory, generating the metadata required from a tree to generate a repository.
|
||||
|
||||
Pack can be used to manually replace what "luet build" does automatically by reading the packages build.yaml files.
|
||||
|
||||
$ mkdir -p output/etc/foo
|
||||
$ echo "my config" > output/etc/foo
|
||||
$ luet pack foo/bar@1.1 --source output
|
||||
|
||||
Afterwards, you can use the content generated and associate it with a tree and a corresponding definition.yaml file with "luet create-repo".
|
||||
`,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
viper.BindPFlag("destination", cmd.Flags().Lookup("destination"))
|
||||
viper.BindPFlag("compression", cmd.Flags().Lookup("compression"))
|
||||
viper.BindPFlag("source", cmd.Flags().Lookup("source"))
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
sourcePath := viper.GetString("source")
|
||||
|
||||
dst := viper.GetString("destination")
|
||||
compressionType := viper.GetString("compression")
|
||||
concurrency := LuetCfg.GetGeneral().Concurrency
|
||||
|
||||
if len(args) != 1 {
|
||||
Fatal("You must specify a package name")
|
||||
}
|
||||
|
||||
packageName := args[0]
|
||||
|
||||
p, err := helpers.ParsePackageStr(packageName)
|
||||
if err != nil {
|
||||
Fatal("Invalid package string ", packageName, ": ", err.Error())
|
||||
}
|
||||
|
||||
spec := &compiler.LuetCompilationSpec{Package: p}
|
||||
artifact := compiler.NewPackageArtifact(filepath.Join(dst, p.GetFingerPrint()+".package.tar"))
|
||||
artifact.SetCompressionType(compiler.CompressionImplementation(compressionType))
|
||||
err = artifact.Compress(sourcePath, concurrency)
|
||||
if err != nil {
|
||||
Fatal("failed compressing ", packageName, ": ", err.Error())
|
||||
}
|
||||
artifact.SetCompileSpec(spec)
|
||||
filelist, err := artifact.FileList()
|
||||
if err != nil {
|
||||
Fatal("failed generating file list for ", packageName, ": ", err.Error())
|
||||
}
|
||||
artifact.SetFiles(filelist)
|
||||
artifact.GetCompileSpec().GetPackage().SetBuildTimestamp(time.Now().String())
|
||||
err = artifact.WriteYaml(dst)
|
||||
if err != nil {
|
||||
Fatal("failed writing metadata yaml file for ", packageName, ": ", err.Error())
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
path, err := os.Getwd()
|
||||
if err != nil {
|
||||
Fatal(err)
|
||||
}
|
||||
packCmd.Flags().String("source", path, "Source folder")
|
||||
packCmd.Flags().String("destination", path, "Destination folder")
|
||||
packCmd.Flags().String("compression", "gzip", "Compression alg: none, gzip")
|
||||
|
||||
RootCmd.AddCommand(packCmd)
|
||||
}
|
@@ -16,13 +16,11 @@ package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
installer "github.com/mudler/luet/pkg/installer"
|
||||
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -35,10 +33,13 @@ var reclaimCmd = &cobra.Command{
|
||||
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
||||
},
|
||||
Long: `Add packages to the systemdb if files belonging to packages
|
||||
in available repositories exists in the target root.`,
|
||||
Long: `Reclaim tries to find association between packages in the online repositories and the system one.
|
||||
|
||||
$ luet reclaim
|
||||
|
||||
It scans the target file system, and if finds a match with a package available in the repositories, it marks as installed in the system database.
|
||||
`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var systemDB pkg.PackageDatabase
|
||||
|
||||
// This shouldn't be necessary, but we need to unmarshal the repositories to a concrete struct, thus we need to port them back to the Repositories type
|
||||
repos := installer.Repositories{}
|
||||
@@ -61,13 +62,7 @@ in available repositories exists in the target root.`,
|
||||
})
|
||||
inst.Repositories(repos)
|
||||
|
||||
if LuetCfg.GetSystem().DatabaseEngine == "boltdb" {
|
||||
systemDB = pkg.NewBoltDatabase(
|
||||
filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
|
||||
} else {
|
||||
systemDB = pkg.NewInMemoryDatabase(true)
|
||||
}
|
||||
system := &installer.System{Database: systemDB, Target: LuetCfg.GetSystem().Rootfs}
|
||||
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs}
|
||||
err := inst.Reclaim(system)
|
||||
if err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
|
148
cmd/replace.go
Normal file
148
cmd/replace.go
Normal file
@@ -0,0 +1,148 @@
|
||||
// Copyright © 2020 Ettore Di Giacinto <mudler@mocaccino.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
installer "github.com/mudler/luet/pkg/installer"
|
||||
"github.com/mudler/luet/pkg/solver"
|
||||
|
||||
helpers "github.com/mudler/luet/cmd/helpers"
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var replaceCmd = &cobra.Command{
|
||||
Use: "replace <pkg1> <pkg2> --for <pkg3> --for <pkg4> ...",
|
||||
Short: "replace a set of packages",
|
||||
Aliases: []string{"r"},
|
||||
Long: `Replaces one or a group of packages without asking questions:
|
||||
|
||||
$ luet replace -y system/busybox ... --for shells/bash --for system/coreutils ...
|
||||
`,
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||
LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target"))
|
||||
LuetCfg.Viper.BindPFlag("solver.type", cmd.Flags().Lookup("solver-type"))
|
||||
LuetCfg.Viper.BindPFlag("solver.discount", cmd.Flags().Lookup("solver-discount"))
|
||||
LuetCfg.Viper.BindPFlag("solver.rate", cmd.Flags().Lookup("solver-rate"))
|
||||
LuetCfg.Viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
|
||||
LuetCfg.Viper.BindPFlag("onlydeps", cmd.Flags().Lookup("onlydeps"))
|
||||
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
|
||||
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
||||
LuetCfg.Viper.BindPFlag("for", cmd.Flags().Lookup("for"))
|
||||
|
||||
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var toUninstall pkg.Packages
|
||||
var toAdd pkg.Packages
|
||||
|
||||
f := LuetCfg.Viper.GetStringSlice("for")
|
||||
stype := LuetCfg.Viper.GetString("solver.type")
|
||||
discount := LuetCfg.Viper.GetFloat64("solver.discount")
|
||||
rate := LuetCfg.Viper.GetFloat64("solver.rate")
|
||||
attempts := LuetCfg.Viper.GetInt("solver.max_attempts")
|
||||
force := LuetCfg.Viper.GetBool("force")
|
||||
nodeps := LuetCfg.Viper.GetBool("nodeps")
|
||||
onlydeps := LuetCfg.Viper.GetBool("onlydeps")
|
||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||
yes := LuetCfg.Viper.GetBool("yes")
|
||||
|
||||
for _, a := range args {
|
||||
pack, err := helpers.ParsePackageStr(a)
|
||||
if err != nil {
|
||||
Fatal("Invalid package string ", a, ": ", err.Error())
|
||||
}
|
||||
toUninstall = append(toUninstall, pack)
|
||||
}
|
||||
|
||||
for _, a := range f {
|
||||
pack, err := helpers.ParsePackageStr(a)
|
||||
if err != nil {
|
||||
Fatal("Invalid package string ", a, ": ", err.Error())
|
||||
}
|
||||
toAdd = append(toAdd, pack)
|
||||
}
|
||||
|
||||
// This shouldn't be necessary, but we need to unmarshal the repositories to a concrete struct, thus we need to port them back to the Repositories type
|
||||
repos := installer.Repositories{}
|
||||
for _, repo := range LuetCfg.SystemRepositories {
|
||||
if !repo.Enable {
|
||||
continue
|
||||
}
|
||||
r := installer.NewSystemRepository(repo)
|
||||
repos = append(repos, r)
|
||||
}
|
||||
|
||||
LuetCfg.GetSolverOptions().Type = stype
|
||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
||||
LuetCfg.GetSolverOptions().MaxAttempts = attempts
|
||||
|
||||
if concurrent {
|
||||
LuetCfg.GetSolverOptions().Implementation = solver.ParallelSimple
|
||||
} else {
|
||||
LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple
|
||||
}
|
||||
|
||||
Debug("Solver", LuetCfg.GetSolverOptions().CompactString())
|
||||
|
||||
// Load config protect configs
|
||||
installer.LoadConfigProtectConfs(LuetCfg)
|
||||
|
||||
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
|
||||
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
||||
SolverOptions: *LuetCfg.GetSolverOptions(),
|
||||
NoDeps: nodeps,
|
||||
Force: force,
|
||||
OnlyDeps: onlydeps,
|
||||
PreserveSystemEssentialData: true,
|
||||
Ask: !yes,
|
||||
})
|
||||
inst.Repositories(repos)
|
||||
|
||||
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs}
|
||||
err := inst.Swap(toUninstall, toAdd, system)
|
||||
if err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
path, err := os.Getwd()
|
||||
if err != nil {
|
||||
Fatal(err)
|
||||
}
|
||||
replaceCmd.Flags().String("system-dbpath", path, "System db path")
|
||||
replaceCmd.Flags().String("system-target", path, "System rootpath")
|
||||
replaceCmd.Flags().String("solver-type", "", "Solver strategy ( Defaults none, available: "+AvailableResolvers+" )")
|
||||
replaceCmd.Flags().Float32("solver-rate", 0.7, "Solver learning rate")
|
||||
replaceCmd.Flags().Float32("solver-discount", 1.0, "Solver discount rate")
|
||||
replaceCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
|
||||
replaceCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful!)")
|
||||
replaceCmd.Flags().Bool("onlydeps", false, "Consider **only** package dependencies")
|
||||
replaceCmd.Flags().Bool("force", false, "Skip errors and keep going (potentially harmful)")
|
||||
replaceCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
|
||||
replaceCmd.Flags().BoolP("yes", "y", false, "Don't ask questions")
|
||||
replaceCmd.Flags().StringSlice("for", []string{}, "Packages that has to be installed in place of others")
|
||||
|
||||
RootCmd.AddCommand(replaceCmd)
|
||||
}
|
47
cmd/root.go
47
cmd/root.go
@@ -24,6 +24,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/marcsauter/single"
|
||||
bus "github.com/mudler/luet/pkg/bus"
|
||||
|
||||
extensions "github.com/mudler/cobra-extensions"
|
||||
config "github.com/mudler/luet/pkg/config"
|
||||
helpers "github.com/mudler/luet/pkg/helpers"
|
||||
@@ -38,7 +40,7 @@ var Verbose bool
|
||||
var LockedCommands = []string{"install", "uninstall", "upgrade"}
|
||||
|
||||
const (
|
||||
LuetCLIVersion = "0.9"
|
||||
LuetCLIVersion = "0.9.22"
|
||||
LuetEnvPrefix = "LUET"
|
||||
)
|
||||
|
||||
@@ -52,9 +54,31 @@ var (
|
||||
|
||||
// RootCmd represents the base command when called without any subcommands
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "luet",
|
||||
Short: "Package manager for the XXth century!",
|
||||
Long: `Package manager which uses containers to build packages`,
|
||||
Use: "luet",
|
||||
Short: "Container based package manager",
|
||||
Long: `Luet is a single-binary package manager based on containers to build packages.
|
||||
|
||||
To install a package:
|
||||
|
||||
$ luet install package
|
||||
|
||||
To search for a package in the repositories:
|
||||
|
||||
$ luet search package
|
||||
|
||||
To list all packages installed in the system:
|
||||
|
||||
$ luet search --installed .
|
||||
|
||||
To show hidden packages:
|
||||
|
||||
$ luet search --hidden package
|
||||
|
||||
To build a package, from a tree definition:
|
||||
|
||||
$ luet build --tree tree/path package
|
||||
|
||||
`,
|
||||
Version: fmt.Sprintf("%s-g%s %s", LuetCLIVersion, BuildCommit, BuildTime),
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
err := LoadConfig(config.LuetCfg)
|
||||
@@ -68,6 +92,18 @@ var RootCmd = &cobra.Command{
|
||||
if err != nil {
|
||||
Fatal("failed on init tmp basedir:", err.Error())
|
||||
}
|
||||
|
||||
viper.BindPFlag("plugin", cmd.Flags().Lookup("plugin"))
|
||||
|
||||
plugin := viper.GetStringSlice("plugin")
|
||||
|
||||
bus.Manager.Load(plugin...).Register()
|
||||
if len(bus.Manager.Plugins) != 0 {
|
||||
Info(":lollipop:Enabled plugins:")
|
||||
for _, p := range bus.Manager.Plugins {
|
||||
Info("\t:arrow_right:", p.Name)
|
||||
}
|
||||
}
|
||||
},
|
||||
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
||||
// Cleanup all tmp directories used by luet
|
||||
@@ -156,6 +192,7 @@ func init() {
|
||||
"Disable config protect analysis.")
|
||||
pflags.StringP("logfile", "l", config.LuetCfg.GetLogging().Path,
|
||||
"Logfile path. Empty value disable log to file.")
|
||||
pflags.StringSlice("plugin", []string{}, "A list of runtime plugins to load")
|
||||
|
||||
// os/user doesn't work in from scratch environments.
|
||||
// Check if i can retrieve user informations.
|
||||
@@ -175,6 +212,8 @@ func init() {
|
||||
config.LuetCfg.Viper.BindPFlag("general.debug", pflags.Lookup("debug"))
|
||||
config.LuetCfg.Viper.BindPFlag("general.fatal_warnings", pflags.Lookup("fatal"))
|
||||
config.LuetCfg.Viper.BindPFlag("general.same_owner", pflags.Lookup("same-owner"))
|
||||
config.LuetCfg.Viper.BindPFlag("plugin", pflags.Lookup("plugin"))
|
||||
|
||||
// Currently I maintain this only from cli.
|
||||
config.LuetCfg.Viper.BindPFlag("no_spinner", pflags.Lookup("no-spinner"))
|
||||
config.LuetCfg.Viper.BindPFlag("config_protect_skip", pflags.Lookup("skip-config-protect"))
|
||||
|
110
cmd/search.go
110
cmd/search.go
@@ -17,9 +17,11 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/jedib0t/go-pretty/table"
|
||||
"github.com/jedib0t/go-pretty/v6/list"
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
installer "github.com/mudler/luet/pkg/installer"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
@@ -44,10 +46,60 @@ func (r PackageResult) String() string {
|
||||
return fmt.Sprintf("%s/%s-%s required for %s", r.Category, r.Name, r.Version, r.Target)
|
||||
}
|
||||
|
||||
var rows table.Row = table.Row{"Package", "Category", "Name", "Version", "Repository", "Description", "License", "URI"}
|
||||
|
||||
func packageToRow(repo string, p pkg.Package) table.Row {
|
||||
return table.Row{p.HumanReadableString(), p.GetCategory(), p.GetName(), p.GetVersion(), repo, p.GetDescription(), p.GetLicense(), strings.Join(p.GetURI(), "\n")}
|
||||
}
|
||||
|
||||
func packageToList(l list.Writer, repo string, p pkg.Package) {
|
||||
l.AppendItem(p.HumanReadableString())
|
||||
l.Indent()
|
||||
l.AppendItem(fmt.Sprintf("Category: %s", p.GetCategory()))
|
||||
l.AppendItem(fmt.Sprintf("Name: %s", p.GetName()))
|
||||
l.AppendItem(fmt.Sprintf("Version: %s", p.GetVersion()))
|
||||
l.AppendItem(fmt.Sprintf("Description: %s", p.GetDescription()))
|
||||
l.AppendItem(fmt.Sprintf("Repository: %s ", repo))
|
||||
l.AppendItem(fmt.Sprintf("Uri: %s ", strings.Join(p.GetURI(), "\n")))
|
||||
l.UnIndent()
|
||||
}
|
||||
|
||||
var searchCmd = &cobra.Command{
|
||||
Use: "search <term>",
|
||||
Short: "Search packages",
|
||||
Long: `Search for installed and available packages`,
|
||||
Use: "search <term>",
|
||||
Short: "Search packages",
|
||||
Long: `Search for installed and available packages
|
||||
|
||||
To search a package in the repositories:
|
||||
|
||||
$ luet search <regex>
|
||||
|
||||
To search a package and display results in a table (wide screens):
|
||||
|
||||
$ luet search --table <regex>
|
||||
|
||||
To look into the installed packages:
|
||||
|
||||
$ luet search --installed <regex>
|
||||
|
||||
Note: the regex argument is optional, if omitted implies "all"
|
||||
|
||||
To search a package by label:
|
||||
|
||||
$ luet search --by-label <label>
|
||||
|
||||
or by regex against the label:
|
||||
|
||||
$ luet search --by-label-regex <label>
|
||||
|
||||
It can also show a package revdeps by:
|
||||
|
||||
$ luet search --revdeps <regex>
|
||||
|
||||
Search can also return results in the terminal in different ways: as terminal output, as json or as yaml.
|
||||
|
||||
$ luet search --json <regex> # JSON output
|
||||
$ luet search --yaml <regex> # YAML output
|
||||
`,
|
||||
Aliases: []string{"s"},
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath"))
|
||||
@@ -59,12 +111,12 @@ var searchCmd = &cobra.Command{
|
||||
LuetCfg.Viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var systemDB pkg.PackageDatabase
|
||||
var results Results
|
||||
if len(args) != 1 {
|
||||
if len(args) > 1 {
|
||||
Fatal("Wrong number of arguments (expected 1)")
|
||||
} else if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
|
||||
hidden, _ := cmd.Flags().GetBool("hidden")
|
||||
|
||||
installed := LuetCfg.Viper.GetBool("installed")
|
||||
@@ -75,6 +127,7 @@ var searchCmd = &cobra.Command{
|
||||
searchWithLabel, _ := cmd.Flags().GetBool("by-label")
|
||||
searchWithLabelMatch, _ := cmd.Flags().GetBool("by-label-regex")
|
||||
revdeps, _ := cmd.Flags().GetBool("revdeps")
|
||||
tableMode, _ := cmd.Flags().GetBool("table")
|
||||
|
||||
out, _ := cmd.Flags().GetString("output")
|
||||
if out != "terminal" {
|
||||
@@ -86,6 +139,9 @@ var searchCmd = &cobra.Command{
|
||||
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
||||
LuetCfg.GetSolverOptions().MaxAttempts = attempts
|
||||
|
||||
l := list.NewWriter()
|
||||
t := table.NewWriter()
|
||||
t.AppendHeader(rows)
|
||||
Debug("Solver", LuetCfg.GetSolverOptions().CompactString())
|
||||
|
||||
if !installed {
|
||||
@@ -124,7 +180,8 @@ var searchCmd = &cobra.Command{
|
||||
for _, m := range matches {
|
||||
if !revdeps {
|
||||
if !m.Package.IsHidden() || m.Package.IsHidden() && hidden {
|
||||
Info(fmt.Sprintf(":file_folder:%s", m.Repo.GetName()), fmt.Sprintf(":package:%s", m.Package.HumanReadableString()))
|
||||
t.AppendRow(packageToRow(m.Repo.GetName(), m.Package))
|
||||
packageToList(l, m.Repo.GetName(), m.Package)
|
||||
results.Packages = append(results.Packages,
|
||||
PackageResult{
|
||||
Name: m.Package.GetName(),
|
||||
@@ -135,10 +192,11 @@ var searchCmd = &cobra.Command{
|
||||
})
|
||||
}
|
||||
} else {
|
||||
visited := make(map[string]interface{})
|
||||
for _, revdep := range m.Package.ExpandedRevdeps(m.Repo.GetTree().GetDatabase(), visited) {
|
||||
packs, _ := m.Repo.GetTree().GetDatabase().GetRevdeps(m.Package)
|
||||
for _, revdep := range packs {
|
||||
if !revdep.IsHidden() || revdep.IsHidden() && hidden {
|
||||
Info(fmt.Sprintf(":file_folder:%s", m.Repo.GetName()), fmt.Sprintf(":package:%s", revdep.HumanReadableString()))
|
||||
t.AppendRow(packageToRow(m.Repo.GetName(), revdep))
|
||||
packageToList(l, m.Repo.GetName(), revdep)
|
||||
results.Packages = append(results.Packages,
|
||||
PackageResult{
|
||||
Name: revdep.GetName(),
|
||||
@@ -153,13 +211,7 @@ var searchCmd = &cobra.Command{
|
||||
}
|
||||
} else {
|
||||
|
||||
if LuetCfg.GetSystem().DatabaseEngine == "boltdb" {
|
||||
systemDB = pkg.NewBoltDatabase(
|
||||
filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
|
||||
} else {
|
||||
systemDB = pkg.NewInMemoryDatabase(true)
|
||||
}
|
||||
system := &installer.System{Database: systemDB, Target: LuetCfg.GetSystem().Rootfs}
|
||||
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs}
|
||||
|
||||
var err error
|
||||
iMatches := pkg.Packages{}
|
||||
@@ -178,7 +230,8 @@ var searchCmd = &cobra.Command{
|
||||
for _, pack := range iMatches {
|
||||
if !revdeps {
|
||||
if !pack.IsHidden() || pack.IsHidden() && hidden {
|
||||
Info(fmt.Sprintf(":package:%s", pack.HumanReadableString()))
|
||||
t.AppendRow(packageToRow("system", pack))
|
||||
packageToList(l, "system", pack)
|
||||
results.Packages = append(results.Packages,
|
||||
PackageResult{
|
||||
Name: pack.GetName(),
|
||||
@@ -189,11 +242,11 @@ var searchCmd = &cobra.Command{
|
||||
})
|
||||
}
|
||||
} else {
|
||||
visited := make(map[string]interface{})
|
||||
|
||||
for _, revdep := range pack.ExpandedRevdeps(system.Database, visited) {
|
||||
packs, _ := system.Database.GetRevdeps(pack)
|
||||
for _, revdep := range packs {
|
||||
if !revdep.IsHidden() || revdep.IsHidden() && hidden {
|
||||
Info(fmt.Sprintf(":package:%s", pack.HumanReadableString()))
|
||||
t.AppendRow(packageToRow("system", pack))
|
||||
packageToList(l, "system", pack)
|
||||
results.Packages = append(results.Packages,
|
||||
PackageResult{
|
||||
Name: revdep.GetName(),
|
||||
@@ -208,6 +261,16 @@ var searchCmd = &cobra.Command{
|
||||
}
|
||||
}
|
||||
|
||||
t.AppendFooter(rows)
|
||||
t.SetStyle(table.StyleColoredBright)
|
||||
|
||||
l.SetStyle(list.StyleConnectedRounded)
|
||||
if tableMode {
|
||||
Info(t.Render())
|
||||
} else {
|
||||
Info(l.Render())
|
||||
}
|
||||
|
||||
y, err := yaml.Marshal(results)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
@@ -245,6 +308,7 @@ func init() {
|
||||
searchCmd.Flags().Bool("by-label-regex", false, "Search packages through label regex")
|
||||
searchCmd.Flags().Bool("revdeps", false, "Search package reverse dependencies")
|
||||
searchCmd.Flags().Bool("hidden", false, "Include hidden packages")
|
||||
searchCmd.Flags().Bool("table", false, "show output in a table (wider screens)")
|
||||
|
||||
RootCmd.AddCommand(searchCmd)
|
||||
}
|
||||
|
@@ -34,5 +34,6 @@ func init() {
|
||||
NewTreePkglistCommand(),
|
||||
NewTreeValidateCommand(),
|
||||
NewTreeBumpCommand(),
|
||||
NewTreeImageCommand(),
|
||||
)
|
||||
}
|
||||
|
136
cmd/tree/images.go
Normal file
136
cmd/tree/images.go
Normal file
@@ -0,0 +1,136 @@
|
||||
// Copyright © 2020 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
// Daniele Rondina <geaaru@sabayonlinux.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd_tree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
//. "github.com/mudler/luet/pkg/config"
|
||||
"github.com/ghodss/yaml"
|
||||
helpers "github.com/mudler/luet/cmd/helpers"
|
||||
"github.com/mudler/luet/pkg/compiler"
|
||||
"github.com/mudler/luet/pkg/compiler/backend"
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
"github.com/mudler/luet/pkg/solver"
|
||||
tree "github.com/mudler/luet/pkg/tree"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func NewTreeImageCommand() *cobra.Command {
|
||||
|
||||
var ans = &cobra.Command{
|
||||
Use: "images [OPTIONS]",
|
||||
Short: "List of the images of a package",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
t, _ := cmd.Flags().GetStringArray("tree")
|
||||
if len(t) == 0 {
|
||||
Fatal("Mandatory tree param missing.")
|
||||
}
|
||||
|
||||
if len(args) != 1 {
|
||||
Fatal("Expects one package as parameter")
|
||||
}
|
||||
viper.BindPFlag("image-repository", cmd.Flags().Lookup("image-repository"))
|
||||
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var results TreeResults
|
||||
|
||||
treePath, _ := cmd.Flags().GetStringArray("tree")
|
||||
imageRepository := viper.GetString("image-repository")
|
||||
|
||||
out, _ := cmd.Flags().GetString("output")
|
||||
if out != "terminal" {
|
||||
LuetCfg.GetLogging().SetLogLevel("error")
|
||||
}
|
||||
|
||||
reciper := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))
|
||||
|
||||
for _, t := range treePath {
|
||||
err := reciper.Load(t)
|
||||
if err != nil {
|
||||
Fatal("Error on load tree ", err)
|
||||
}
|
||||
}
|
||||
compilerBackend := backend.NewSimpleDockerBackend()
|
||||
|
||||
opts := compiler.NewDefaultCompilerOptions()
|
||||
opts.SolverOptions = *LuetCfg.GetSolverOptions()
|
||||
opts.ImageRepository = imageRepository
|
||||
|
||||
solverOpts := solver.Options{Type: solver.SingleCoreSimple, Concurrency: 1}
|
||||
luetCompiler := compiler.NewLuetCompiler(compilerBackend, reciper.GetDatabase(), opts, solverOpts)
|
||||
|
||||
a := args[0]
|
||||
|
||||
pack, err := helpers.ParsePackageStr(a)
|
||||
if err != nil {
|
||||
Fatal("Invalid package string ", a, ": ", err.Error())
|
||||
}
|
||||
|
||||
spec, err := luetCompiler.FromPackage(pack)
|
||||
if err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
}
|
||||
asserts, err := luetCompiler.ComputeDepTree(spec)
|
||||
|
||||
for _, assertion := range asserts { //highly dependent on the order
|
||||
|
||||
//buildImageHash := imageRepository + ":" + assertion.Hash.BuildHash
|
||||
currentPackageImageHash := imageRepository + ":" + assertion.Hash.PackageHash
|
||||
|
||||
results.Packages = append(results.Packages, TreePackageResult{
|
||||
Name: assertion.Package.GetName(),
|
||||
Version: assertion.Package.GetVersion(),
|
||||
Category: assertion.Package.GetCategory(),
|
||||
Image: currentPackageImageHash,
|
||||
})
|
||||
}
|
||||
|
||||
y, err := yaml.Marshal(results)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
switch out {
|
||||
case "yaml":
|
||||
fmt.Println(string(y))
|
||||
case "json":
|
||||
j2, err := yaml.YAMLToJSON(y)
|
||||
if err != nil {
|
||||
fmt.Printf("err: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(j2))
|
||||
default:
|
||||
for _, p := range results.Packages {
|
||||
fmt.Println(fmt.Sprintf("%s/%s-%s: %s", p.Category, p.Name, p.Version, p.Image))
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
ans.Flags().StringP("output", "o", "terminal", "Output format ( Defaults: terminal, available: json,yaml )")
|
||||
ans.Flags().StringArrayP("tree", "t", []string{}, "Path of the tree to use.")
|
||||
ans.Flags().String("image-repository", "luet/cache", "Default base image string for generated image")
|
||||
|
||||
return ans
|
||||
}
|
@@ -37,6 +37,7 @@ type TreePackageResult struct {
|
||||
Category string `json:"category"`
|
||||
Version string `json:"version"`
|
||||
Path string `json:"path"`
|
||||
Image string `json:"image"`
|
||||
}
|
||||
|
||||
type TreeResults struct {
|
||||
@@ -167,9 +168,8 @@ func NewTreePkglistCommand() *cobra.Command {
|
||||
|
||||
if addPkg {
|
||||
if revdeps {
|
||||
|
||||
visited := make(map[string]interface{})
|
||||
for _, revdep := range p.ExpandedRevdeps(reciper.GetDatabase(), visited) {
|
||||
packs, _ := reciper.GetDatabase().GetRevdeps(p)
|
||||
for _, revdep := range packs {
|
||||
if full {
|
||||
pkgstr = pkgDetail(revdep)
|
||||
} else if verbose {
|
||||
|
@@ -16,7 +16,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
helpers "github.com/mudler/luet/cmd/helpers"
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
@@ -42,63 +41,61 @@ var uninstallCmd = &cobra.Command{
|
||||
LuetCfg.Viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
|
||||
LuetCfg.Viper.BindPFlag("nodeps", cmd.Flags().Lookup("nodeps"))
|
||||
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
||||
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var systemDB pkg.PackageDatabase
|
||||
|
||||
toRemove := []pkg.Package{}
|
||||
for _, a := range args {
|
||||
|
||||
pack, err := helpers.ParsePackageStr(a)
|
||||
if err != nil {
|
||||
Fatal("Invalid package string ", a, ": ", err.Error())
|
||||
}
|
||||
toRemove = append(toRemove, pack)
|
||||
}
|
||||
|
||||
stype := LuetCfg.Viper.GetString("solver.type")
|
||||
discount := LuetCfg.Viper.GetFloat64("solver.discount")
|
||||
rate := LuetCfg.Viper.GetFloat64("solver.rate")
|
||||
attempts := LuetCfg.Viper.GetInt("solver.max_attempts")
|
||||
force := LuetCfg.Viper.GetBool("force")
|
||||
nodeps, _ := cmd.Flags().GetBool("nodeps")
|
||||
full, _ := cmd.Flags().GetBool("full")
|
||||
checkconflicts, _ := cmd.Flags().GetBool("conflictscheck")
|
||||
fullClean, _ := cmd.Flags().GetBool("full-clean")
|
||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||
stype := LuetCfg.Viper.GetString("solver.type")
|
||||
discount := LuetCfg.Viper.GetFloat64("solver.discount")
|
||||
rate := LuetCfg.Viper.GetFloat64("solver.rate")
|
||||
attempts := LuetCfg.Viper.GetInt("solver.max_attempts")
|
||||
force := LuetCfg.Viper.GetBool("force")
|
||||
nodeps, _ := cmd.Flags().GetBool("nodeps")
|
||||
full, _ := cmd.Flags().GetBool("full")
|
||||
checkconflicts, _ := cmd.Flags().GetBool("conflictscheck")
|
||||
fullClean, _ := cmd.Flags().GetBool("full-clean")
|
||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||
yes := LuetCfg.Viper.GetBool("yes")
|
||||
|
||||
LuetCfg.GetSolverOptions().Type = stype
|
||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
||||
LuetCfg.GetSolverOptions().MaxAttempts = attempts
|
||||
if concurrent {
|
||||
LuetCfg.GetSolverOptions().Implementation = solver.ParallelSimple
|
||||
} else {
|
||||
LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple
|
||||
}
|
||||
Debug("Solver", LuetCfg.GetSolverOptions().CompactString())
|
||||
LuetCfg.GetSolverOptions().Type = stype
|
||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||
LuetCfg.GetSolverOptions().Discount = float32(discount)
|
||||
LuetCfg.GetSolverOptions().MaxAttempts = attempts
|
||||
if concurrent {
|
||||
LuetCfg.GetSolverOptions().Implementation = solver.ParallelSimple
|
||||
} else {
|
||||
LuetCfg.GetSolverOptions().Implementation = solver.SingleCoreSimple
|
||||
}
|
||||
Debug("Solver", LuetCfg.GetSolverOptions().CompactString())
|
||||
|
||||
// Load config protect configs
|
||||
installer.LoadConfigProtectConfs(LuetCfg)
|
||||
// Load config protect configs
|
||||
installer.LoadConfigProtectConfs(LuetCfg)
|
||||
|
||||
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
|
||||
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
||||
SolverOptions: *LuetCfg.GetSolverOptions(),
|
||||
NoDeps: nodeps,
|
||||
Force: force,
|
||||
FullUninstall: full,
|
||||
FullCleanUninstall: fullClean,
|
||||
CheckConflicts: checkconflicts,
|
||||
})
|
||||
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
|
||||
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
||||
SolverOptions: *LuetCfg.GetSolverOptions(),
|
||||
NoDeps: nodeps,
|
||||
Force: force,
|
||||
FullUninstall: full,
|
||||
FullCleanUninstall: fullClean,
|
||||
CheckConflicts: checkconflicts,
|
||||
Ask: !yes,
|
||||
PreserveSystemEssentialData: true,
|
||||
})
|
||||
|
||||
if LuetCfg.GetSystem().DatabaseEngine == "boltdb" {
|
||||
systemDB = pkg.NewBoltDatabase(
|
||||
filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
|
||||
} else {
|
||||
systemDB = pkg.NewInMemoryDatabase(true)
|
||||
}
|
||||
system := &installer.System{Database: systemDB, Target: LuetCfg.GetSystem().Rootfs}
|
||||
err = inst.Uninstall(pack, system)
|
||||
if err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
}
|
||||
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs}
|
||||
|
||||
if err := inst.Uninstall(system, toRemove...); err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -120,6 +117,7 @@ func init() {
|
||||
uninstallCmd.Flags().Bool("conflictscheck", true, "Check if the package marked for deletion is required by other packages")
|
||||
uninstallCmd.Flags().Bool("full-clean", false, "(experimental) Uninstall packages and all the other deps/revdeps of it.")
|
||||
uninstallCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
|
||||
uninstallCmd.Flags().BoolP("yes", "y", false, "Don't ask questions")
|
||||
|
||||
RootCmd.AddCommand(uninstallCmd)
|
||||
}
|
||||
|
@@ -16,12 +16,10 @@ package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
installer "github.com/mudler/luet/pkg/installer"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
"github.com/mudler/luet/pkg/solver"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -39,10 +37,10 @@ var upgradeCmd = &cobra.Command{
|
||||
LuetCfg.Viper.BindPFlag("solver.rate", cmd.Flags().Lookup("solver-rate"))
|
||||
LuetCfg.Viper.BindPFlag("solver.max_attempts", cmd.Flags().Lookup("solver-attempts"))
|
||||
LuetCfg.Viper.BindPFlag("force", cmd.Flags().Lookup("force"))
|
||||
LuetCfg.Viper.BindPFlag("yes", cmd.Flags().Lookup("yes"))
|
||||
},
|
||||
Long: `Upgrades packages in parallel`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var systemDB pkg.PackageDatabase
|
||||
|
||||
repos := installer.Repositories{}
|
||||
for _, repo := range LuetCfg.SystemRepositories {
|
||||
@@ -65,6 +63,7 @@ var upgradeCmd = &cobra.Command{
|
||||
clean, _ := cmd.Flags().GetBool("clean")
|
||||
sync, _ := cmd.Flags().GetBool("sync")
|
||||
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
|
||||
yes := LuetCfg.Viper.GetBool("yes")
|
||||
|
||||
LuetCfg.GetSolverOptions().Type = stype
|
||||
LuetCfg.GetSolverOptions().LearnRate = float32(rate)
|
||||
@@ -82,30 +81,21 @@ var upgradeCmd = &cobra.Command{
|
||||
installer.LoadConfigProtectConfs(LuetCfg)
|
||||
|
||||
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
|
||||
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
||||
SolverOptions: *LuetCfg.GetSolverOptions(),
|
||||
Force: force,
|
||||
FullUninstall: full,
|
||||
NoDeps: nodeps,
|
||||
SolverUpgrade: universe,
|
||||
RemoveUnavailableOnUpgrade: clean,
|
||||
UpgradeNewRevisions: sync,
|
||||
Concurrency: LuetCfg.GetGeneral().Concurrency,
|
||||
SolverOptions: *LuetCfg.GetSolverOptions(),
|
||||
Force: force,
|
||||
FullUninstall: full,
|
||||
NoDeps: nodeps,
|
||||
SolverUpgrade: universe,
|
||||
RemoveUnavailableOnUpgrade: clean,
|
||||
UpgradeNewRevisions: sync,
|
||||
PreserveSystemEssentialData: true,
|
||||
Ask: !yes,
|
||||
})
|
||||
inst.Repositories(repos)
|
||||
_, err := inst.SyncRepositories(false)
|
||||
if err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
}
|
||||
|
||||
if LuetCfg.GetSystem().DatabaseEngine == "boltdb" {
|
||||
systemDB = pkg.NewBoltDatabase(
|
||||
filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
|
||||
} else {
|
||||
systemDB = pkg.NewInMemoryDatabase(true)
|
||||
}
|
||||
system := &installer.System{Database: systemDB, Target: LuetCfg.GetSystem().Rootfs}
|
||||
err = inst.Upgrade(system)
|
||||
if err != nil {
|
||||
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs}
|
||||
if err := inst.Upgrade(system); err != nil {
|
||||
Fatal("Error: " + err.Error())
|
||||
}
|
||||
},
|
||||
@@ -124,11 +114,12 @@ func init() {
|
||||
upgradeCmd.Flags().Int("solver-attempts", 9000, "Solver maximum attempts")
|
||||
upgradeCmd.Flags().Bool("force", false, "Force upgrade by ignoring errors")
|
||||
upgradeCmd.Flags().Bool("nodeps", false, "Don't consider package dependencies (harmful! overrides checkconflicts and full!)")
|
||||
upgradeCmd.Flags().Bool("full", true, "Attempts to remove as much packages as possible which aren't required (slow)")
|
||||
upgradeCmd.Flags().Bool("full", false, "Attempts to remove as much packages as possible which aren't required (slow)")
|
||||
upgradeCmd.Flags().Bool("universe", false, "Use ONLY the SAT solver to compute upgrades (experimental)")
|
||||
upgradeCmd.Flags().Bool("clean", false, "Try to drop removed packages (experimental, only when --universe is enabled)")
|
||||
upgradeCmd.Flags().Bool("sync", false, "Upgrade packages with new revisions (experimental)")
|
||||
upgradeCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
|
||||
upgradeCmd.Flags().BoolP("yes", "y", false, "Don't ask questions")
|
||||
|
||||
RootCmd.AddCommand(upgradeCmd)
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ if [ "${LUET_CONFIG_PROTECT}" = "1" ] ; then
|
||||
mkdir -p /etc/luet/config.protect.d || true
|
||||
wget -q https://raw.githubusercontent.com/mudler/luet/master/contrib/config/config.protect.d/01_etc.yml.example -O /etc/luet/config.protect.d/01_etc.yml
|
||||
fi
|
||||
wget -q https://raw.githubusercontent.com/mocaccinoOS/repository-index/master/packages/mocaccino-repository-index/mocaccino-repository-index.yml -O /etc/luet/repos.conf.d/mocaccino-repository-index.yml
|
||||
wget -q https://raw.githubusercontent.com/mocaccinoOS/repository-index/master/packages/mocaccino-repository-index.yml -O /etc/luet/repos.conf.d/mocaccino-repository-index.yml
|
||||
|
||||
cat > /etc/luet/luet.yaml <<EOF
|
||||
general:
|
||||
|
21
go.mod
21
go.mod
@@ -7,43 +7,46 @@ require (
|
||||
github.com/Sabayon/pkgs-checker v0.7.2
|
||||
github.com/asdine/storm v0.0.0-20190418133842-e0f77eada154
|
||||
github.com/briandowns/spinner v1.7.0
|
||||
github.com/cavaliercoder/grab v2.0.0+incompatible
|
||||
github.com/cavaliercoder/grab v1.0.1-0.20201108051000-98a5bfe305ec
|
||||
github.com/crillab/gophersat v1.3.2-0.20201023142334-3fc2ac466765
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200417035958-130b0bc6032c+incompatible
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
github.com/ecooper/qlearning v0.0.0-20160612200101-3075011a69fd
|
||||
github.com/fsouza/go-dockerclient v1.6.4
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/google/go-containerregistry v0.2.1
|
||||
github.com/hashicorp/go-multierror v1.0.0
|
||||
github.com/hashicorp/go-version v1.2.0
|
||||
github.com/jedib0t/go-pretty v4.3.0+incompatible
|
||||
github.com/jedib0t/go-pretty/v6 v6.0.5
|
||||
github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3
|
||||
github.com/klauspost/compress v1.8.3
|
||||
github.com/klauspost/pgzip v1.2.1
|
||||
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
|
||||
github.com/kr/pretty v0.2.0 // indirect
|
||||
github.com/kyokomi/emoji v2.1.0+incompatible
|
||||
github.com/logrusorgru/aurora v0.0.0-20190417123914-21d75270181e
|
||||
github.com/marcsauter/single v0.0.0-20181104081128-f8bf46f26ec0
|
||||
github.com/mattn/go-isatty v0.0.10 // indirect
|
||||
github.com/moby/sys/mount v0.1.1-0.20200320164225-6154f11e6840 // indirect
|
||||
github.com/mudler/cobra-extensions v0.0.0-20200612154940-31a47105fe3d
|
||||
github.com/mudler/docker-companion v0.4.6-0.20200418093252-41846f112d87
|
||||
github.com/mudler/go-pluggable v0.0.0-20201113184918-d36448fc8f82
|
||||
github.com/mudler/topsort v0.0.0-20201103161459-db5c7901c290
|
||||
github.com/onsi/ginkgo v1.12.1
|
||||
github.com/onsi/gomega v1.10.0
|
||||
github.com/onsi/ginkgo v1.14.2
|
||||
github.com/onsi/gomega v1.10.3
|
||||
github.com/otiai10/copy v1.2.1-0.20200916181228-26f84a0b1578
|
||||
github.com/pelletier/go-toml v1.6.0 // indirect
|
||||
github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/schollz/progressbar/v3 v3.7.1
|
||||
github.com/spf13/cobra v1.0.0
|
||||
github.com/spf13/viper v1.6.3
|
||||
go.etcd.io/bbolt v1.3.4
|
||||
go.uber.org/atomic v1.5.1 // indirect
|
||||
go.uber.org/multierr v1.4.0 // indirect
|
||||
go.uber.org/zap v1.13.0
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f // indirect
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
gotest.tools/v3 v3.0.2 // indirect
|
||||
helm.sh/helm/v3 v3.3.4
|
||||
mvdan.cc/sh/v3 v3.0.0-beta1
|
||||
)
|
||||
|
||||
replace github.com/docker/docker => github.com/Luet-lab/moby v17.12.0-ce-rc1.0.20200605210607-749178b8f80d+incompatible
|
||||
|
339
go.sum
339
go.sum
@@ -2,22 +2,62 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxo
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v42.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
|
||||
github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
|
||||
github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/DataDog/zstd v1.4.4 h1:+IawcoXhCBylN7ccwdwf8LOH2jKq7NavGpEPanrlTzE=
|
||||
github.com/DataDog/zstd v1.4.4/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Luet-lab/moby v17.12.0-ce-rc1.0.20200605210607-749178b8f80d+incompatible h1:YddBuPhhRLoz7uhSJ3Zm//e62jQeTW/qXEZrk5I4qsk=
|
||||
github.com/Luet-lab/moby v17.12.0-ce-rc1.0.20200605210607-749178b8f80d+incompatible/go.mod h1:/XyFFC7lL96pE2kKmar2jd4LKxWzy1MmbiDHV0nK3bU=
|
||||
@@ -30,6 +70,7 @@ github.com/Masterminds/sprig/v3 v3.1.0 h1:j7GpgZ7PdFqNsmncycTHsLmVPf5/3wJtlgW9TN
|
||||
github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA=
|
||||
github.com/Masterminds/squirrel v1.4.0/go.mod h1:yaPeOnPG5ZRwL9oKdTsO/prlkPbXWZlRVMQ/gGlzIuA=
|
||||
github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20200113171025-3fe6c5262873 h1:93nQ7k53GjoMQ07HVP8g6Zj1fQZDDj7Xy2VkNNtvX8o=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20200113171025-3fe6c5262873/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
@@ -71,6 +112,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
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 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
|
||||
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=
|
||||
@@ -79,6 +121,8 @@ github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZo
|
||||
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.23.21/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.28.2/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.31.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
@@ -97,17 +141,25 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8n
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cavaliercoder/grab v2.0.0+incompatible h1:wZHbBQx56+Yxjx2TCGDcenhh3cJn7cCLMfkEPmySTSE=
|
||||
github.com/cavaliercoder/grab v2.0.0+incompatible/go.mod h1:tTBkfNqSBfuMmMBFaO2phgyhdYhiZQ/+iXCZDzcDsMI=
|
||||
github.com/cavaliercoder/grab v1.0.1-0.20201108051000-98a5bfe305ec h1:4XvMn0XuV7qxCH22gbnR79r+xTUaLOSA0GW/egpO3SQ=
|
||||
github.com/cavaliercoder/grab v1.0.1-0.20201108051000-98a5bfe305ec/go.mod h1:NbXoa59CCAGqtRm7kRrcZIk2dTCJMRVF8QI3BOD7isY=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
|
||||
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9 h1:xz6Nv3zcwO2Lila35hcb0QloCQsc38Al13RNEzWRpX4=
|
||||
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9/go.mod h1:2wSM9zJkl1UQEFZgSd68NfCgRz1VL1jzy/RjCg+ULrs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s=
|
||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||
@@ -146,10 +198,12 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/crillab/gophersat v1.3.2-0.20201023142334-3fc2ac466765 h1:EO5Dm7O50aaEwv1GTFWNLAj7vNQ1OjW3+DeJCy1vTMk=
|
||||
github.com/crillab/gophersat v1.3.2-0.20201023142334-3fc2ac466765/go.mod h1:S91tHga1PCZzYhCkStwZAhvp1rCc+zqtSi55I+vDWGc=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -161,10 +215,13 @@ github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492 h1:FwssHbCDJD025h+BchanCwE1Q8fyMgqDr2mOQAWOLGw=
|
||||
github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
|
||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
@@ -190,17 +247,22 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkg
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsouza/go-dockerclient v1.6.4 h1:B+L+1lz1LUrNgEUUh8PSG76s70EYC49ssv2xvTefTMM=
|
||||
github.com/fsouza/go-dockerclient v1.6.4/go.mod h1:GOdftxWLWIbIWKbIMDroKFJzPdg6Iw7r+jX1DDZdVsA=
|
||||
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||
@@ -209,6 +271,9 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
@@ -224,6 +289,7 @@ github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9sn
|
||||
github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
|
||||
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
|
||||
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
|
||||
github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY=
|
||||
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
|
||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
@@ -251,6 +317,7 @@ github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8
|
||||
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
|
||||
github.com/go-openapi/strfmt v0.19.3 h1:eRfyY5SkaNJCAwmmMcADjY31ow9+N7MCLW7oRkbsINA=
|
||||
github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
@@ -262,6 +329,8 @@ github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2K
|
||||
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w=
|
||||
@@ -278,6 +347,7 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
@@ -287,13 +357,28 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
|
||||
@@ -308,19 +393,31 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-containerregistry v0.2.1 h1:LLZgLTDguTVJ9eEHh/zTtr347CpFhH6MSYculNas5bY=
|
||||
github.com/google/go-containerregistry v0.2.1/go.mod h1:Ts3Wioz1r5ayWx8sS6vLcWltWcM1aqFjd/eVrkFhrWM=
|
||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
|
||||
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.2.2 h1:DcFegQ7+ECdmkJMfVwWlC+89I4esJ7p8nkGt9ainGDk=
|
||||
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
@@ -343,11 +440,13 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
@@ -360,6 +459,7 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
@@ -373,31 +473,41 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
||||
github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs=
|
||||
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo=
|
||||
github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
|
||||
github.com/jedib0t/go-pretty/v6 v6.0.5 h1:oOo0/jSb3NEYKT6l1hhFXoX2UZnkanMuCE2DVT1mqnE=
|
||||
github.com/jedib0t/go-pretty/v6 v6.0.5/go.mod h1:MTr6FgcfNdnN5wPVBzJ6mhJeDyiF0yBvS2TMXEV/XSU=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3 h1:sHsPfNMAG70QAvKbddQ0uScZCHQoZsT5NykGRCeeeIs=
|
||||
github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
||||
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
@@ -417,13 +527,13 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kyokomi/emoji v2.1.0+incompatible h1:+DYU2RgpI6OHG4oQkM5KlqD3Wd3UPEsX8jamTo1Mp6o=
|
||||
github.com/kyokomi/emoji v2.1.0+incompatible/go.mod h1:mZ6aGCD7yk8j6QY6KICwnZ2pxoszVseX1DNoGtU2tBA=
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
|
||||
@@ -459,19 +569,24 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.12.0 h1:u/x3mp++qUxvYfulZ4HKOvVO0JWhk7HtE8lWhbGz/Do=
|
||||
github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
@@ -493,6 +608,7 @@ github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+S
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
@@ -504,6 +620,8 @@ github.com/mudler/cobra-extensions v0.0.0-20200612154940-31a47105fe3d h1:fKh+rvw
|
||||
github.com/mudler/cobra-extensions v0.0.0-20200612154940-31a47105fe3d/go.mod h1:puRUWSwyecW2V355tKncwPVPRAjQBduPsFjG0mrV/Nw=
|
||||
github.com/mudler/docker-companion v0.4.6-0.20200418093252-41846f112d87 h1:mGz7T8KvmHH0gLWPI5tQne8xl2cO3T8wrrb6Aa16Jxo=
|
||||
github.com/mudler/docker-companion v0.4.6-0.20200418093252-41846f112d87/go.mod h1:1w4zI1LYXDeiUXqedPcrT5eQJnmKR6dbg5iJMgSIP/Y=
|
||||
github.com/mudler/go-pluggable v0.0.0-20201113184918-d36448fc8f82 h1:Hkefw2tzoKATVUTFsCtDlUnY180+OE851qGbq45ATxk=
|
||||
github.com/mudler/go-pluggable v0.0.0-20201113184918-d36448fc8f82/go.mod h1:4P/ULate+2QxoAQtojaRjyO5VGMhV0KLnSdAS8nuBbo=
|
||||
github.com/mudler/topsort v0.0.0-20201103161459-db5c7901c290 h1:426hFyXMpXeqIeGJn2cGAW9ogvM2Jf+Jv23gtVPvBLM=
|
||||
github.com/mudler/topsort v0.0.0-20201103161459-db5c7901c290/go.mod h1:uP5BBgFxq2wNWo7n1vnY5SSbgL0WDshVJrOO12tZ/lA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
@@ -518,6 +636,8 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
@@ -529,19 +649,27 @@ github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2f
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||
github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/onsi/gomega v1.10.0 h1:Gwkk+PTu/nfOwNMtUB/mRUv0X7ewW5dO4AERT1ThVKo=
|
||||
github.com/onsi/gomega v1.10.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/openSUSE/umoci v0.1.1-0.20191030112807-c0dd46ae078f h1:G9hyzNrFbTgp9KEoGRcNYxAT41lo7hDy9oxXT1Y7WHI=
|
||||
github.com/openSUSE/umoci v0.1.1-0.20191030112807-c0dd46ae078f/go.mod h1:3p4KA5nwyY65lVmQZxv7tm0YEylJ+t1fY91ORsVXv58=
|
||||
@@ -592,7 +720,6 @@ github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f h1:WyCn68lTiy
|
||||
github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f/go.mod h1:/iRjX3DdSK956SzsUdV55J+wIsQ+2IBWmBrB4RvZfk4=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/diff v0.0.0-20190930165518-531926345625/go.mod h1:kFj35MyHn14a6pIgWhm46KVjJr5CHys3eEYxkuKD1EI=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
@@ -600,6 +727,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
@@ -634,6 +762,7 @@ github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLk
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
@@ -641,10 +770,10 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rootless-containers/proto v0.1.0 h1:gS1JOMEtk1YDYHCzBAf/url+olMJbac7MTrgSeP6zh4=
|
||||
github.com/rootless-containers/proto v0.1.0/go.mod h1:vgkUFZbQd0gcE/K/ZwtE4MYjZPu0UNHLXIQxhyqAFh8=
|
||||
github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351/go.mod h1:DCgfY80j8GYL7MLEfvcpSFvjD0L5yZq/aZUJmhZklyg=
|
||||
github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
@@ -652,6 +781,9 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/schollz/progressbar/v3 v3.7.1 h1:aQR/t6d+1nURSdoMn6c7n0vJi5xQ3KndpF0n7R5wrik=
|
||||
github.com/schollz/progressbar/v3 v3.7.1/go.mod h1:CG/f0JmacksUc6TkZToO7tVq4t03zIQSQUtTd7F9GR4=
|
||||
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
@@ -707,6 +839,7 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
@@ -717,6 +850,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
|
||||
github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0=
|
||||
@@ -732,9 +866,11 @@ github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/vbatts/go-mtree v0.4.4 h1:+CncqETnSpxBCCUhRnNQBvxhsjWXNuc+ExZsLSNaj5o=
|
||||
github.com/vbatts/go-mtree v0.4.4/go.mod h1:3sazBqLG4bZYmgRTgdh9X3iKTzwBpp5CrREJDzrNSXY=
|
||||
github.com/vdemeester/k8s-pkg-credentialprovider v1.18.1-0.20201019120933-f1d16962a4db/go.mod h1:grWy0bkr1XO6hqbaaCKaPXqkBVlMGHYG6PGykktwbJc=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
github.com/vmihailenco/msgpack v4.0.1+incompatible h1:RMF1enSPeKTlXrXdOcqjFUElywVZjjC6pqse21bKbEU=
|
||||
github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
@@ -745,6 +881,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
@@ -757,6 +895,7 @@ go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA=
|
||||
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
@@ -765,6 +904,8 @@ go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
@@ -789,29 +930,58 @@ golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
|
||||
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -828,22 +998,36 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc=
|
||||
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -851,7 +1035,11 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -864,38 +1052,62 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201113135734-0a15ea8d9b02 h1:5Ftd3YbC/kANXWCBjvppvUmv1BMakgFcBKA7MpYYp4M=
|
||||
golang.org/x/sys v0.0.0-20201113135734-0a15ea8d9b02/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -903,48 +1115,108 @@ golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190913181337-0240832f5c3d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3 h1:DywqrEscRX7O2phNjkT0L6lhHKGBoMLCNX+XcAe7t6s=
|
||||
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
|
||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
|
||||
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece h1:1YM0uhfumvoDu9sx8+RyWwTI63zoCQvI23IYFRlvte0=
|
||||
google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
@@ -952,13 +1224,28 @@ google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLD
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -966,10 +1253,13 @@ gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw=
|
||||
@@ -982,6 +1272,7 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -991,6 +1282,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
@@ -1002,9 +1295,12 @@ helm.sh/helm/v3 v3.3.4/go.mod h1:CyCGQa53/k1JFxXvXveGwtfJ4cuB9zkaBSGa5rnAiHU=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.18.8 h1:aIKUzJPb96f3fKec2lxtY7acZC9gQNDLVhfSGpxBAC4=
|
||||
k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY=
|
||||
k8s.io/apiextensions-apiserver v0.18.8 h1:pkqYPKTHa0/3lYwH7201RpF9eFm0lmZDFBNzhN+k/sA=
|
||||
@@ -1015,25 +1311,38 @@ k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM=
|
||||
k8s.io/cli-runtime v0.18.8/go.mod h1:7EzWiDbS9PFd0hamHHVoCY4GrokSTPSL32MA4rzIu0M=
|
||||
k8s.io/client-go v0.18.8 h1:SdbLpIxk5j5YbFr1b7fq8S7mDgDjYmUxSbszyoesoDM=
|
||||
k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU=
|
||||
k8s.io/cloud-provider v0.18.8/go.mod h1:cn9AlzMPVIXA4HHLVbgGUigaQlZyHSZ7WAwDEFNrQSs=
|
||||
k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
|
||||
k8s.io/code-generator v0.18.8/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
|
||||
k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
|
||||
k8s.io/csi-translation-lib v0.18.8/go.mod h1:6cA6Btlzxy9s3QrS4BCZzQqclIWnTLr6Jx3H2ctAzY4=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
||||
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||
k8s.io/kubectl v0.18.8/go.mod h1:PlEgIAjOMua4hDFTEkVf+W5M0asHUKfE4y7VDZkpLHM=
|
||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||
k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGPF4on0IyICQE=
|
||||
k8s.io/metrics v0.18.8/go.mod h1:j7JzZdiyhLP2BsJm/Fzjs+j5Lb1Y7TySjhPWqBPwRXA=
|
||||
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
|
||||
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
mvdan.cc/editorconfig v0.1.1-0.20191109213504-890940e3f00e/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8=
|
||||
mvdan.cc/sh/v3 v3.0.0-beta1 h1:UqiwBEXEPzelaGxuvixaOtzc7WzKtrElePJ8HqvW7K8=
|
||||
mvdan.cc/sh/v3 v3.0.0-beta1/go.mod h1:rBIndNJFYPp8xSppiZcGIk6B5d1g3OEARxEaXjPxwVI=
|
||||
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
||||
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
||||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
|
||||
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
|
||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||
|
67
pkg/bus/events.go
Normal file
67
pkg/bus/events.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package bus
|
||||
|
||||
import (
|
||||
"github.com/mudler/go-pluggable"
|
||||
)
|
||||
|
||||
var (
|
||||
// Package events
|
||||
|
||||
// EventPackageInstall is the event fired when a new package is being installed
|
||||
EventPackageInstall pluggable.EventType = "package.install"
|
||||
// EventPackageUnInstall is the event fired when a new package is being uninstalled
|
||||
EventPackageUnInstall pluggable.EventType = "package.uninstall"
|
||||
|
||||
// Package build
|
||||
|
||||
// EventPackagePreBuild is the event fired before a package is being built
|
||||
EventPackagePreBuild pluggable.EventType = "package.pre.build"
|
||||
// EventPackagePreBuildArtifact is the event fired before a package tarball is being generated
|
||||
EventPackagePreBuildArtifact pluggable.EventType = "package.pre.build_artifact"
|
||||
// EventPackagePostBuildArtifact is the event fired after a package tarball is generated
|
||||
EventPackagePostBuildArtifact pluggable.EventType = "package.post.build_artifact"
|
||||
// EventPackagePostBuild is the event fired after a package was built
|
||||
EventPackagePostBuild pluggable.EventType = "package.post.build"
|
||||
|
||||
// Image build
|
||||
|
||||
// EventImagePreBuild is the event fired before a image is being built
|
||||
EventImagePreBuild pluggable.EventType = "image.pre.build"
|
||||
// EventImagePrePull is the event fired before a image is being pulled
|
||||
EventImagePrePull pluggable.EventType = "image.pre.pull"
|
||||
// EventImagePrePush is the event fired before a image is being pushed
|
||||
EventImagePrePush pluggable.EventType = "image.pre.push"
|
||||
// EventImagePostBuild is the event fired after an image is being built
|
||||
EventImagePostBuild pluggable.EventType = "image.post.build"
|
||||
// EventImagePostPull is the event fired after an image is being pulled
|
||||
EventImagePostPull pluggable.EventType = "image.post.pull"
|
||||
// EventImagePostPush is the event fired after an image is being pushed
|
||||
EventImagePostPush pluggable.EventType = "image.post.push"
|
||||
|
||||
// Repository events
|
||||
|
||||
// EventRepositoryPreBuild is the event fired before a repository is being built
|
||||
EventRepositoryPreBuild pluggable.EventType = "repository.pre.build"
|
||||
// EventRepositoryPostBuild is the event fired after a repository was built
|
||||
EventRepositoryPostBuild pluggable.EventType = "repository.post.build"
|
||||
)
|
||||
|
||||
// Manager is the bus instance manager, which subscribes plugins to events emitted by Luet
|
||||
var Manager *pluggable.Manager = pluggable.NewManager(
|
||||
[]pluggable.EventType{
|
||||
EventPackageInstall,
|
||||
EventPackageUnInstall,
|
||||
EventPackagePreBuild,
|
||||
EventPackagePreBuildArtifact,
|
||||
EventPackagePostBuildArtifact,
|
||||
EventPackagePostBuild,
|
||||
EventRepositoryPreBuild,
|
||||
EventRepositoryPostBuild,
|
||||
EventImagePreBuild,
|
||||
EventImagePrePull,
|
||||
EventImagePrePush,
|
||||
EventImagePostBuild,
|
||||
EventImagePostPull,
|
||||
EventImagePostPush,
|
||||
},
|
||||
)
|
@@ -28,12 +28,14 @@ import (
|
||||
"regexp"
|
||||
|
||||
system "github.com/docker/docker/pkg/system"
|
||||
"github.com/klauspost/compress/zstd"
|
||||
gzip "github.com/klauspost/pgzip"
|
||||
|
||||
//"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
bus "github.com/mudler/luet/pkg/bus"
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
"github.com/mudler/luet/pkg/helpers"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
@@ -46,8 +48,9 @@ import (
|
||||
type CompressionImplementation string
|
||||
|
||||
const (
|
||||
None CompressionImplementation = "none" // e.g. tar for standard packages
|
||||
GZip CompressionImplementation = "gzip"
|
||||
None CompressionImplementation = "none" // e.g. tar for standard packages
|
||||
GZip CompressionImplementation = "gzip"
|
||||
Zstandard CompressionImplementation = "zstd"
|
||||
)
|
||||
|
||||
type ArtifactIndex []Artifact
|
||||
@@ -170,6 +173,8 @@ func (a *PackageArtifact) WriteYaml(dst string) error {
|
||||
return errors.Wrap(err, "While marshalling for PackageArtifact YAML")
|
||||
}
|
||||
|
||||
bus.Manager.Publish(bus.EventPackagePreBuildArtifact, a)
|
||||
|
||||
mangle, err := NewPackageArtifactFromYaml(data)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Generated invalid artifact")
|
||||
@@ -191,6 +196,7 @@ func (a *PackageArtifact) WriteYaml(dst string) error {
|
||||
return errors.Wrap(err, "While writing PackageArtifact YAML")
|
||||
}
|
||||
//a.CompileSpec.GetPackage().SetPath(p)
|
||||
bus.Manager.Publish(bus.EventPackagePostBuildArtifact, a)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -238,6 +244,43 @@ func (a *PackageArtifact) SetPath(p string) {
|
||||
// Compress Archives and compress (TODO) to the artifact path
|
||||
func (a *PackageArtifact) Compress(src string, concurrency int) error {
|
||||
switch a.CompressionType {
|
||||
|
||||
case Zstandard:
|
||||
err := helpers.Tar(src, a.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
original, err := os.Open(a.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer original.Close()
|
||||
|
||||
zstdFile := a.Path + ".zstd"
|
||||
bufferedReader := bufio.NewReader(original)
|
||||
|
||||
// Open a file for writing.
|
||||
dst, err := os.Create(zstdFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enc, err := zstd.NewWriter(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(enc, bufferedReader)
|
||||
if err != nil {
|
||||
enc.Close()
|
||||
return err
|
||||
}
|
||||
if err := enc.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
os.RemoveAll(a.Path) // Remove original
|
||||
a.Path = zstdFile
|
||||
return nil
|
||||
case GZip:
|
||||
err := helpers.Tar(src, a.Path)
|
||||
if err != nil {
|
||||
@@ -363,6 +406,40 @@ func (a *PackageArtifact) Unpack(dst string, keepPerms bool) error {
|
||||
tarModifier := helpers.NewTarModifierWrapper(dst, tarModifierWrapperFunc)
|
||||
|
||||
switch a.CompressionType {
|
||||
case Zstandard:
|
||||
// Create the uncompressed archive
|
||||
archive, err := os.Create(a.GetPath() + ".uncompressed")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(a.GetPath() + ".uncompressed")
|
||||
defer archive.Close()
|
||||
|
||||
original, err := os.Open(a.Path)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Cannot open "+a.Path)
|
||||
}
|
||||
defer original.Close()
|
||||
|
||||
bufferedReader := bufio.NewReader(original)
|
||||
|
||||
d, err := zstd.NewReader(bufferedReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer d.Close()
|
||||
|
||||
_, err = io.Copy(archive, d)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Cannot copy to "+a.GetPath()+".uncompressed")
|
||||
}
|
||||
|
||||
err = helpers.UntarProtect(a.GetPath()+".uncompressed", dst,
|
||||
LuetCfg.GetGeneral().SameOwner, protectedFiles, tarModifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case GZip:
|
||||
// Create the uncompressed archive
|
||||
archive, err := os.Create(a.GetPath() + ".uncompressed")
|
||||
@@ -408,6 +485,27 @@ func (a *PackageArtifact) Unpack(dst string, keepPerms bool) error {
|
||||
func (a *PackageArtifact) FileList() ([]string, error) {
|
||||
var tr *tar.Reader
|
||||
switch a.CompressionType {
|
||||
case Zstandard:
|
||||
archive, err := os.Create(a.GetPath() + ".uncompressed")
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
defer os.RemoveAll(a.GetPath() + ".uncompressed")
|
||||
defer archive.Close()
|
||||
|
||||
original, err := os.Open(a.Path)
|
||||
if err != nil {
|
||||
return []string{}, errors.Wrap(err, "Cannot open "+a.Path)
|
||||
}
|
||||
defer original.Close()
|
||||
|
||||
bufferedReader := bufio.NewReader(original)
|
||||
r, err := zstd.NewReader(bufferedReader)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
defer r.Close()
|
||||
tr = tar.NewReader(r)
|
||||
case GZip:
|
||||
// Create the uncompressed archive
|
||||
archive, err := os.Create(a.GetPath() + ".uncompressed")
|
||||
|
@@ -96,23 +96,28 @@ ENV PACKAGE_CATEGORY=app-admin`))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(dockerfile).To(Equal(`
|
||||
FROM luet/base
|
||||
COPY . /luetbuild
|
||||
WORKDIR /luetbuild
|
||||
ENV PACKAGE_NAME=enman
|
||||
ENV PACKAGE_VERSION=1.4.0
|
||||
ENV PACKAGE_CATEGORY=app-admin
|
||||
RUN echo foo > /test
|
||||
RUN echo bar > /test2`))
|
||||
opts = CompilerBackendOptions{
|
||||
opts2 := CompilerBackendOptions{
|
||||
ImageName: "test",
|
||||
SourcePath: tmpdir,
|
||||
DockerFileName: "LuetDockerfile",
|
||||
Destination: filepath.Join(tmpdir, "output2.tar"),
|
||||
}
|
||||
Expect(b.ImageDefinitionToTar(opts)).ToNot(HaveOccurred())
|
||||
Expect(b.ImageDefinitionToTar(opts2)).ToNot(HaveOccurred())
|
||||
Expect(helpers.Exists(filepath.Join(tmpdir, "output2.tar"))).To(BeTrue())
|
||||
diffs, err := b.Changes(filepath.Join(tmpdir2, "output1.tar"), filepath.Join(tmpdir, "output2.tar"))
|
||||
diffs, err := b.Changes(opts, opts2)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
artifacts := []ArtifactNode{}
|
||||
artifacts := []ArtifactNode{{
|
||||
Name: "/luetbuild/LuetDockerfile",
|
||||
Size: 175,
|
||||
}}
|
||||
if os.Getenv("DOCKER_BUILDKIT") == "1" {
|
||||
artifacts = append(artifacts, ArtifactNode{Name: "/etc/resolv.conf", Size: 0})
|
||||
}
|
||||
|
25
pkg/compiler/backend/common.go
Normal file
25
pkg/compiler/backend/common.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright © 2020 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package backend
|
||||
|
||||
import (
|
||||
"github.com/google/go-containerregistry/pkg/crane"
|
||||
)
|
||||
|
||||
func imageAvailable(image string) bool {
|
||||
_, err := crane.Digest(image)
|
||||
return err == nil
|
||||
}
|
@@ -52,7 +52,10 @@ import (
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
func GenerateChanges(b compiler.CompilerBackend, srcImage, dstImage string) ([]compiler.ArtifactLayer, error) {
|
||||
func GenerateChanges(b compiler.CompilerBackend, fromImage, toImage compiler.CompilerBackendOptions) ([]compiler.ArtifactLayer, error) {
|
||||
|
||||
srcImage := fromImage.Destination
|
||||
dstImage := toImage.Destination
|
||||
|
||||
res := compiler.ArtifactLayer{FromImage: srcImage, ToImage: dstImage}
|
||||
|
||||
@@ -95,6 +98,7 @@ func GenerateChanges(b compiler.CompilerBackend, srcImage, dstImage string) ([]c
|
||||
|
||||
srcImageExtract := compiler.CompilerBackendOptions{
|
||||
SourcePath: srcImage,
|
||||
ImageName: fromImage.ImageName,
|
||||
Destination: srcRootFS,
|
||||
}
|
||||
err = b.ExtractRootfs(srcImageExtract, false) // No need to keep permissions as we just collect file diffs
|
||||
@@ -123,6 +127,7 @@ func GenerateChanges(b compiler.CompilerBackend, srcImage, dstImage string) ([]c
|
||||
|
||||
dstImageExtract := compiler.CompilerBackendOptions{
|
||||
SourcePath: dstImage,
|
||||
ImageName: toImage.ImageName,
|
||||
Destination: dstRootFS,
|
||||
}
|
||||
err = b.ExtractRootfs(dstImageExtract, false)
|
||||
|
@@ -32,12 +32,14 @@ var _ = Describe("Docker image diffs", func() {
|
||||
|
||||
Context("Generate diffs from docker images", func() {
|
||||
It("Detect no changes", func() {
|
||||
err := b.DownloadImage(compiler.CompilerBackendOptions{
|
||||
ImageName: "alpine:latest",
|
||||
})
|
||||
opts := compiler.CompilerBackendOptions{
|
||||
ImageName: "alpine:latest",
|
||||
Destination: "alpine:latest",
|
||||
}
|
||||
err := b.DownloadImage(opts)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
layers, err := GenerateChanges(b, "alpine:latest", "alpine:latest")
|
||||
layers, err := GenerateChanges(b, opts, opts)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(layers)).To(Equal(1))
|
||||
Expect(len(layers[0].Diffs.Additions)).To(Equal(0))
|
||||
@@ -55,7 +57,13 @@ var _ = Describe("Docker image diffs", func() {
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
layers, err := GenerateChanges(b, "quay.io/mocaccino/micro", "quay.io/mocaccino/extra")
|
||||
layers, err := GenerateChanges(b, compiler.CompilerBackendOptions{
|
||||
ImageName: "quay.io/mocaccino/micro",
|
||||
Destination: "quay.io/mocaccino/micro",
|
||||
}, compiler.CompilerBackendOptions{
|
||||
ImageName: "quay.io/mocaccino/extra",
|
||||
Destination: "quay.io/mocaccino/extra",
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(layers)).To(Equal(1))
|
||||
|
||||
|
@@ -24,6 +24,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
capi "github.com/mudler/docker-companion/api"
|
||||
|
||||
"github.com/mudler/luet/pkg/compiler"
|
||||
@@ -45,6 +46,7 @@ func (*SimpleDocker) BuildImage(opts compiler.CompilerBackendOptions) error {
|
||||
name := opts.ImageName
|
||||
path := opts.SourcePath
|
||||
dockerfileName := opts.DockerFileName
|
||||
|
||||
buildarg := []string{"build", "-f", dockerfileName, "-t", name, "."}
|
||||
|
||||
Debug(":whale2: Building image " + name)
|
||||
@@ -56,6 +58,21 @@ func (*SimpleDocker) BuildImage(opts compiler.CompilerBackendOptions) error {
|
||||
}
|
||||
Info(":whale: Building image " + name + " done")
|
||||
|
||||
if os.Getenv("DOCKER_SQUASH") == "true" {
|
||||
Info(":whale: Squashing image " + name)
|
||||
var client *docker.Client
|
||||
|
||||
client, err = docker.NewClientFromEnv()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not connect to the Docker daemon")
|
||||
}
|
||||
err = capi.Squash(client, name, name)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed squashing image")
|
||||
}
|
||||
Info(":whale: Squashing image " + name + " done")
|
||||
}
|
||||
|
||||
if config.LuetCfg.GetGeneral().ShowBuildOutput {
|
||||
Info(string(out))
|
||||
} else {
|
||||
@@ -83,7 +100,7 @@ func (*SimpleDocker) DownloadImage(opts compiler.CompilerBackendOptions) error {
|
||||
cmd := exec.Command("docker", buildarg...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed building image: "+string(out))
|
||||
return errors.Wrap(err, "Failed pulling image: "+string(out))
|
||||
}
|
||||
Info(":whale: Downloaded image:", name)
|
||||
return nil
|
||||
@@ -95,13 +112,17 @@ func (*SimpleDocker) ImageExists(imagename string) bool {
|
||||
cmd := exec.Command("docker", buildarg...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
Warning("Image not present")
|
||||
Debug("Image not present")
|
||||
Debug(string(out))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*SimpleDocker) ImageAvailable(imagename string) bool {
|
||||
return imageAvailable(imagename)
|
||||
}
|
||||
|
||||
func (*SimpleDocker) RemoveImage(opts compiler.CompilerBackendOptions) error {
|
||||
name := opts.ImageName
|
||||
buildarg := []string{"rmi", name}
|
||||
@@ -222,7 +243,7 @@ func (*SimpleDocker) ExtractRootfs(opts compiler.CompilerBackendOptions, keepPer
|
||||
}
|
||||
|
||||
// Changes retrieves changes between image layers
|
||||
func (d *SimpleDocker) Changes(fromImage, toImage string) ([]compiler.ArtifactLayer, error) {
|
||||
func (d *SimpleDocker) Changes(fromImage, toImage compiler.CompilerBackendOptions) ([]compiler.ArtifactLayer, error) {
|
||||
diffs, err := GenerateChanges(d, fromImage, toImage)
|
||||
|
||||
if config.LuetCfg.GetGeneral().Debug {
|
||||
|
@@ -87,28 +87,33 @@ ENV PACKAGE_CATEGORY=app-admin`))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(dockerfile).To(Equal(`
|
||||
FROM luet/base
|
||||
COPY . /luetbuild
|
||||
WORKDIR /luetbuild
|
||||
ENV PACKAGE_NAME=enman
|
||||
ENV PACKAGE_VERSION=1.4.0
|
||||
ENV PACKAGE_CATEGORY=app-admin
|
||||
RUN echo foo > /test
|
||||
RUN echo bar > /test2`))
|
||||
opts = CompilerBackendOptions{
|
||||
opts2 := CompilerBackendOptions{
|
||||
ImageName: "test",
|
||||
SourcePath: tmpdir,
|
||||
DockerFileName: "LuetDockerfile",
|
||||
Destination: filepath.Join(tmpdir, "output2.tar"),
|
||||
}
|
||||
Expect(b.ImageDefinitionToTar(opts)).ToNot(HaveOccurred())
|
||||
Expect(b.ImageDefinitionToTar(opts2)).ToNot(HaveOccurred())
|
||||
Expect(helpers.Exists(filepath.Join(tmpdir, "output2.tar"))).To(BeTrue())
|
||||
|
||||
artifacts := []ArtifactNode{}
|
||||
artifacts := []ArtifactNode{{
|
||||
Name: "/luetbuild/LuetDockerfile",
|
||||
Size: 175,
|
||||
}}
|
||||
if os.Getenv("DOCKER_BUILDKIT") == "1" {
|
||||
artifacts = append(artifacts, ArtifactNode{Name: "/etc/resolv.conf", Size: 0})
|
||||
}
|
||||
artifacts = append(artifacts, ArtifactNode{Name: "/test", Size: 4})
|
||||
artifacts = append(artifacts, ArtifactNode{Name: "/test2", Size: 4})
|
||||
|
||||
Expect(b.Changes(filepath.Join(tmpdir2, "output1.tar"), filepath.Join(tmpdir, "output2.tar"))).To(Equal(
|
||||
Expect(b.Changes(opts, opts2)).To(Equal(
|
||||
[]ArtifactLayer{{
|
||||
FromImage: filepath.Join(tmpdir2, "output1.tar"),
|
||||
ToImage: filepath.Join(tmpdir, "output2.tar"),
|
||||
@@ -119,5 +124,11 @@ RUN echo bar > /test2`))
|
||||
|
||||
})
|
||||
|
||||
It("Detects available images", func() {
|
||||
b := NewSimpleDockerBackend()
|
||||
Expect(b.ImageAvailable("quay.io/mocaccino/extra")).To(BeTrue())
|
||||
Expect(b.ImageAvailable("ubuntu:20.10")).To(BeTrue())
|
||||
Expect(b.ImageAvailable("igjo5ijgo25nho52")).To(BeFalse())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -59,7 +59,7 @@ func (*SimpleImg) RemoveImage(opts compiler.CompilerBackendOptions) error {
|
||||
defer SpinnerStop()
|
||||
out, err := exec.Command("img", buildarg...).CombinedOutput()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed building image: "+string(out))
|
||||
return errors.Wrap(err, "Failed removing image: "+string(out))
|
||||
}
|
||||
|
||||
Info(":tea: Image " + name + " removed")
|
||||
@@ -75,7 +75,7 @@ func (*SimpleImg) DownloadImage(opts compiler.CompilerBackendOptions) error {
|
||||
cmd := exec.Command("img", buildarg...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed building image: "+string(out))
|
||||
return errors.Wrap(err, "Failed downloading image: "+string(out))
|
||||
}
|
||||
|
||||
Info(":tea: Image " + name + " downloaded")
|
||||
@@ -97,6 +97,10 @@ func (*SimpleImg) CopyImage(src, dst string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*SimpleImg) ImageAvailable(imagename string) bool {
|
||||
return imageAvailable(imagename)
|
||||
}
|
||||
|
||||
func (*SimpleImg) ImageExists(imagename string) bool {
|
||||
// NOOP: not implemented
|
||||
// TODO: Since img doesn't have an inspect command,
|
||||
@@ -124,7 +128,7 @@ func (*SimpleImg) ExportImage(opts compiler.CompilerBackendOptions) error {
|
||||
Debug(":tea: Saving image " + name)
|
||||
out, err := exec.Command("img", buildarg...).CombinedOutput()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed building image: "+string(out))
|
||||
return errors.Wrap(err, "Failed exporting image: "+string(out))
|
||||
}
|
||||
Info(":tea: Image " + name + " saved")
|
||||
return nil
|
||||
@@ -149,7 +153,7 @@ func (*SimpleImg) ExtractRootfs(opts compiler.CompilerBackendOptions, keepPerms
|
||||
|
||||
// TODO: Use container-diff (https://github.com/GoogleContainerTools/container-diff) for checking out layer diffs
|
||||
// Changes uses container-diff (https://github.com/GoogleContainerTools/container-diff) for retrieving out layer diffs
|
||||
func (i *SimpleImg) Changes(fromImage, toImage string) ([]compiler.ArtifactLayer, error) {
|
||||
func (i *SimpleImg) Changes(fromImage, toImage compiler.CompilerBackendOptions) ([]compiler.ArtifactLayer, error) {
|
||||
return GenerateChanges(i, fromImage, toImage)
|
||||
}
|
||||
|
||||
|
@@ -16,18 +16,20 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
bus "github.com/mudler/luet/pkg/bus"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/mudler/luet/pkg/helpers"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
@@ -38,6 +40,7 @@ import (
|
||||
|
||||
const BuildFile = "build.yaml"
|
||||
const DefinitionFile = "definition.yaml"
|
||||
const CollectionFile = "collection.yaml"
|
||||
|
||||
type LuetCompiler struct {
|
||||
*tree.CompilerRecipe
|
||||
@@ -64,7 +67,6 @@ func NewLuetCompiler(backend CompilerBackend, db pkg.PackageDatabase, opt *Compi
|
||||
CompressionType: opt.CompressionType,
|
||||
KeepImg: opt.KeepImg,
|
||||
Concurrency: opt.Concurrency,
|
||||
Clean: opt.Clean,
|
||||
Options: *opt,
|
||||
SolverOptions: solvopts,
|
||||
}
|
||||
@@ -235,7 +237,66 @@ func (cs *LuetCompiler) stripFromRootfs(includes []string, rootfs string, includ
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage string, concurrency int, keepPermissions, keepImg bool, p CompilationSpec, generateArtifact bool) (Artifact, error) {
|
||||
func (cs *LuetCompiler) unpackFs(rootfs string, concurrency int, p CompilationSpec) (Artifact, error) {
|
||||
if p.GetPackageDir() != "" {
|
||||
Info(":tophat: Packing from output dir", p.GetPackageDir())
|
||||
rootfs = filepath.Join(rootfs, p.GetPackageDir())
|
||||
}
|
||||
|
||||
if len(p.GetIncludes()) > 0 {
|
||||
// strip from includes
|
||||
cs.stripFromRootfs(p.GetIncludes(), rootfs, true)
|
||||
}
|
||||
if len(p.GetExcludes()) > 0 {
|
||||
// strip from includes
|
||||
cs.stripFromRootfs(p.GetExcludes(), rootfs, false)
|
||||
}
|
||||
artifact := NewPackageArtifact(p.Rel(p.GetPackage().GetFingerPrint() + ".package.tar"))
|
||||
artifact.SetCompressionType(cs.CompressionType)
|
||||
|
||||
if err := artifact.Compress(rootfs, concurrency); err != nil {
|
||||
return nil, errors.Wrap(err, "Error met while creating package archive")
|
||||
}
|
||||
|
||||
artifact.SetCompileSpec(p)
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
func (cs *LuetCompiler) unpackDelta(rootfs string, concurrency int, keepPermissions bool, p CompilationSpec, builderOpts, runnerOpts CompilerBackendOptions) (Artifact, error) {
|
||||
pkgTag := ":package: " + p.GetPackage().HumanReadableString()
|
||||
if cs.Options.PullFirst && !cs.Backend.ImageExists(builderOpts.ImageName) && cs.Backend.ImageAvailable(builderOpts.ImageName) {
|
||||
err := cs.Backend.DownloadImage(builderOpts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not pull image")
|
||||
}
|
||||
} else if !cs.Backend.ImageExists(builderOpts.ImageName) {
|
||||
return nil, errors.New("No image found for " + builderOpts.ImageName)
|
||||
}
|
||||
if err := cs.Backend.ExportImage(builderOpts); err != nil {
|
||||
return nil, errors.Wrap(err, "Could not export image"+builderOpts.ImageName)
|
||||
}
|
||||
if !cs.Options.KeepImageExport {
|
||||
defer os.Remove(builderOpts.Destination)
|
||||
}
|
||||
Info(pkgTag, ":hammer: Generating delta")
|
||||
diffs, err := cs.Backend.Changes(builderOpts, runnerOpts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not generate changes from layers")
|
||||
}
|
||||
artifact, err := ExtractArtifactFromDelta(rootfs, p.Rel(p.GetPackage().GetFingerPrint()+".package.tar"), diffs, concurrency, keepPermissions, p.GetIncludes(), p.GetExcludes(), cs.CompressionType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not generate deltas")
|
||||
}
|
||||
|
||||
artifact.SetCompileSpec(p)
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
func (cs *LuetCompiler) buildPackageImage(image, buildertaggedImage, packageImage string,
|
||||
concurrency int, keepPermissions bool,
|
||||
p CompilationSpec) (CompilerBackendOptions, CompilerBackendOptions, error) {
|
||||
|
||||
var runnerOpts, builderOpts CompilerBackendOptions
|
||||
|
||||
pkgTag := ":package: " + p.GetPackage().HumanReadableString()
|
||||
|
||||
@@ -251,21 +312,13 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
|
||||
fp := p.GetPackage().HashFingerprint(packageImage)
|
||||
|
||||
if buildertaggedImage == "" {
|
||||
buildertaggedImage = cs.ImageRepository + "-" + fp + "-builder"
|
||||
buildertaggedImage = cs.ImageRepository + ":builder-" + fp
|
||||
Debug(pkgTag, "Creating intermediary image", buildertaggedImage, "from", image)
|
||||
}
|
||||
|
||||
// TODO: Cleanup, not actually hit
|
||||
if packageImage == "" {
|
||||
packageImage = cs.ImageRepository + "-" + fp
|
||||
}
|
||||
|
||||
if !cs.Clean {
|
||||
exists := cs.Backend.ImageExists(buildertaggedImage) && cs.Backend.ImageExists(packageImage)
|
||||
if art, err := LoadArtifactFromYaml(p); err == nil && (cs.Options.SkipIfMetadataExists || exists) {
|
||||
Debug("Artifact reloaded. Skipping build")
|
||||
return art, err
|
||||
}
|
||||
packageImage = cs.ImageRepository + ":builder-invalid" + fp
|
||||
}
|
||||
|
||||
p.SetSeedImage(image) // In this case, we ignore the build deps as we suppose that the image has them - otherwise we recompose the tree with a solver,
|
||||
@@ -273,19 +326,18 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
|
||||
|
||||
err := os.MkdirAll(p.Rel("build"), os.ModePerm)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error met while creating tempdir for building")
|
||||
return builderOpts, runnerOpts, errors.Wrap(err, "Error met while creating tempdir for building")
|
||||
}
|
||||
buildDir, err := ioutil.TempDir(p.Rel("build"), "pack")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error met while creating tempdir for building")
|
||||
return builderOpts, runnerOpts, errors.Wrap(err, "Error met while creating tempdir for building")
|
||||
}
|
||||
defer os.RemoveAll(buildDir) // clean up
|
||||
|
||||
// First we copy the source definitions into the output - we create a copy which the builds will need (we need to cache this phase somehow)
|
||||
err = helpers.CopyDir(p.GetPackage().GetPath(), buildDir)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not copy package sources")
|
||||
|
||||
return builderOpts, runnerOpts, errors.Wrap(err, "Could not copy package sources")
|
||||
}
|
||||
|
||||
// Copy file into the build context, the compilespec might have requested to do so.
|
||||
@@ -296,66 +348,112 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
|
||||
}
|
||||
}
|
||||
|
||||
Info(pkgTag, ":whale: Generating 'builder' image definition from", image)
|
||||
|
||||
// First we create the builder image
|
||||
p.WriteBuildImageDefinition(filepath.Join(buildDir, p.GetPackage().GetFingerPrint()+"-builder.dockerfile"))
|
||||
builderOpts := CompilerBackendOptions{
|
||||
if err := p.WriteBuildImageDefinition(filepath.Join(buildDir, p.GetPackage().GetFingerPrint()+"-builder.dockerfile")); err != nil {
|
||||
return builderOpts, runnerOpts, errors.Wrap(err, "Could not generate image definition")
|
||||
}
|
||||
|
||||
if len(p.GetPreBuildSteps()) == 0 {
|
||||
buildertaggedImage = image
|
||||
}
|
||||
|
||||
// Then we write the step image, which uses the builder one
|
||||
if err := p.WriteStepImageDefinition(buildertaggedImage, filepath.Join(buildDir, p.GetPackage().GetFingerPrint()+".dockerfile")); err != nil {
|
||||
return builderOpts, runnerOpts, errors.Wrap(err, "Could not generate image definition")
|
||||
}
|
||||
|
||||
builderOpts = CompilerBackendOptions{
|
||||
ImageName: buildertaggedImage,
|
||||
SourcePath: buildDir,
|
||||
DockerFileName: p.GetPackage().GetFingerPrint() + "-builder.dockerfile",
|
||||
Destination: p.Rel(p.GetPackage().GetFingerPrint() + "-builder.image.tar"),
|
||||
}
|
||||
|
||||
buildBuilderImage := true
|
||||
if cs.Options.PullFirst {
|
||||
if err := cs.Backend.DownloadImage(builderOpts); err == nil {
|
||||
buildBuilderImage = false
|
||||
}
|
||||
}
|
||||
|
||||
if buildBuilderImage {
|
||||
if err = cs.Backend.BuildImage(builderOpts); err != nil {
|
||||
return nil, errors.Wrap(err, "Could not build image: "+image+" "+builderOpts.DockerFileName)
|
||||
}
|
||||
}
|
||||
|
||||
if err = cs.Backend.ExportImage(builderOpts); err != nil {
|
||||
return nil, errors.Wrap(err, "Could not export image")
|
||||
}
|
||||
|
||||
if !cs.Options.KeepImageExport {
|
||||
defer os.Remove(builderOpts.Destination)
|
||||
}
|
||||
|
||||
if cs.Options.Push && buildBuilderImage {
|
||||
if err = cs.Backend.Push(builderOpts); err != nil {
|
||||
return nil, errors.Wrap(err, "Could not push image: "+image+" "+builderOpts.DockerFileName)
|
||||
}
|
||||
}
|
||||
// Then we write the step image, which uses the builder one
|
||||
p.WriteStepImageDefinition(buildertaggedImage, filepath.Join(buildDir, p.GetPackage().GetFingerPrint()+".dockerfile"))
|
||||
runnerOpts := CompilerBackendOptions{
|
||||
runnerOpts = CompilerBackendOptions{
|
||||
ImageName: packageImage,
|
||||
SourcePath: buildDir,
|
||||
DockerFileName: p.GetPackage().GetFingerPrint() + ".dockerfile",
|
||||
Destination: p.Rel(p.GetPackage().GetFingerPrint() + ".image.tar"),
|
||||
}
|
||||
|
||||
buildPackageImage := true
|
||||
if cs.Options.PullFirst {
|
||||
//Best effort pull
|
||||
if err := cs.Backend.DownloadImage(runnerOpts); err == nil {
|
||||
buildPackageImage = false
|
||||
buildAndPush := func(opts CompilerBackendOptions) error {
|
||||
buildImage := true
|
||||
if cs.Options.PullFirst {
|
||||
bus.Manager.Publish(bus.EventImagePrePull, opts)
|
||||
err := cs.Backend.DownloadImage(opts)
|
||||
if err == nil {
|
||||
buildImage = false
|
||||
} else {
|
||||
Warning("Failed to download '" + opts.ImageName + "'. Will keep going and build the image unless you use --fatal")
|
||||
Warning(err.Error())
|
||||
}
|
||||
bus.Manager.Publish(bus.EventImagePostPull, opts)
|
||||
}
|
||||
if buildImage {
|
||||
bus.Manager.Publish(bus.EventImagePreBuild, opts)
|
||||
if err := cs.Backend.BuildImage(opts); err != nil {
|
||||
return errors.Wrap(err, "Could not build image: "+image+" "+opts.DockerFileName)
|
||||
}
|
||||
bus.Manager.Publish(bus.EventImagePostBuild, opts)
|
||||
if cs.Options.Push {
|
||||
bus.Manager.Publish(bus.EventImagePrePush, opts)
|
||||
if err = cs.Backend.Push(opts); err != nil {
|
||||
return errors.Wrap(err, "Could not push image: "+image+" "+opts.DockerFileName)
|
||||
}
|
||||
bus.Manager.Publish(bus.EventImagePostPush, opts)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if len(p.GetPreBuildSteps()) != 0 {
|
||||
Info(pkgTag, ":whale: Generating 'builder' image from", image, "as", buildertaggedImage, "with prelude steps")
|
||||
if err := buildAndPush(builderOpts); err != nil {
|
||||
return builderOpts, runnerOpts, errors.Wrap(err, "Could not push image: "+image+" "+builderOpts.DockerFileName)
|
||||
}
|
||||
}
|
||||
|
||||
if buildPackageImage {
|
||||
if err := cs.Backend.BuildImage(runnerOpts); err != nil {
|
||||
return nil, errors.Wrap(err, "Failed building image for "+runnerOpts.ImageName+" "+runnerOpts.DockerFileName)
|
||||
}
|
||||
// Even if we might not have any steps to build, we do that so we can tag the image used in this moment and use that to cache it in a registry, or in the system.
|
||||
// acting as a docker tag.
|
||||
Info(pkgTag, ":whale: Generating 'package' image from", buildertaggedImage, "as", packageImage, "with build steps")
|
||||
if err := buildAndPush(runnerOpts); err != nil {
|
||||
return builderOpts, runnerOpts, errors.Wrap(err, "Could not push image: "+image+" "+builderOpts.DockerFileName)
|
||||
}
|
||||
|
||||
return builderOpts, runnerOpts, nil
|
||||
}
|
||||
|
||||
func (cs *LuetCompiler) genArtifact(p CompilationSpec, builderOpts, runnerOpts CompilerBackendOptions, concurrency int, keepPermissions bool) (Artifact, error) {
|
||||
|
||||
// generate Artifact
|
||||
var artifact Artifact
|
||||
var rootfs string
|
||||
var err error
|
||||
unpack := p.ImageUnpack()
|
||||
pkgTag := ":package: " + p.GetPackage().HumanReadableString()
|
||||
|
||||
// If package_dir was specified in the spec, we want to treat the content of the directory
|
||||
// as the root of our archive. ImageUnpack is implied to be true. override it
|
||||
if p.GetPackageDir() != "" {
|
||||
unpack = true
|
||||
}
|
||||
|
||||
if len(p.BuildSteps()) == 0 && len(p.GetPreBuildSteps()) == 0 && !unpack {
|
||||
fakePackage := p.Rel(p.GetPackage().GetFingerPrint() + ".package.tar")
|
||||
// We can't generate delta in this case. It implies the package is a virtual, and nothing has to be done really
|
||||
|
||||
file, err := os.Create(fakePackage)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed creating virtual package")
|
||||
}
|
||||
defer file.Close()
|
||||
tw := tar.NewWriter(file)
|
||||
defer tw.Close()
|
||||
|
||||
artifact := NewPackageArtifact(fakePackage)
|
||||
artifact.SetCompressionType(cs.CompressionType)
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
// prepare folder content of the image with the package compiled inside
|
||||
if err := cs.Backend.ExportImage(runnerOpts); err != nil {
|
||||
return nil, errors.Wrap(err, "Failed exporting image")
|
||||
}
|
||||
@@ -364,23 +462,7 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
|
||||
defer os.Remove(runnerOpts.Destination)
|
||||
}
|
||||
|
||||
if cs.Options.Push && buildPackageImage {
|
||||
err = cs.Backend.Push(runnerOpts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not push image: "+image+" "+builderOpts.DockerFileName)
|
||||
}
|
||||
}
|
||||
|
||||
var artifact Artifact
|
||||
unpack := p.ImageUnpack()
|
||||
|
||||
// If package_dir was specified in the spec, we want to treat the content of the directory
|
||||
// as the root of our archive. ImageUnpack is implied to be true. override it
|
||||
if p.GetPackageDir() != "" {
|
||||
unpack = true
|
||||
}
|
||||
|
||||
rootfs, err := ioutil.TempDir(p.GetOutputPath(), "rootfs")
|
||||
rootfs, err = ioutil.TempDir(p.GetOutputPath(), "rootfs")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not create tempdir")
|
||||
}
|
||||
@@ -388,66 +470,24 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
|
||||
|
||||
// TODO: Compression and such
|
||||
err = cs.Backend.ExtractRootfs(CompilerBackendOptions{
|
||||
ImageName: packageImage,
|
||||
ImageName: runnerOpts.ImageName,
|
||||
SourcePath: runnerOpts.Destination, Destination: rootfs}, keepPermissions)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not extract rootfs")
|
||||
}
|
||||
|
||||
if !keepImg {
|
||||
// We keep them around, so to not reload them from the tar (which should be the "correct way") and we automatically share the same layers
|
||||
// TODO: Handle caching and optionally do not remove things
|
||||
err = cs.Backend.RemoveImage(builderOpts)
|
||||
if err != nil {
|
||||
Warning("Could not remove image ", builderOpts.ImageName)
|
||||
// return nil, errors.Wrap(err, "Could not remove image")
|
||||
}
|
||||
err = cs.Backend.RemoveImage(runnerOpts)
|
||||
if err != nil {
|
||||
Warning("Could not remove image ", builderOpts.ImageName)
|
||||
// return nil, errors.Wrap(err, "Could not remove image")
|
||||
}
|
||||
}
|
||||
|
||||
if !generateArtifact {
|
||||
return &PackageArtifact{}, nil
|
||||
}
|
||||
|
||||
if unpack {
|
||||
if p.GetPackageDir() != "" {
|
||||
Info(":tophat: Packing from output dir", p.GetPackageDir())
|
||||
rootfs = filepath.Join(rootfs, p.GetPackageDir())
|
||||
}
|
||||
|
||||
if len(p.GetIncludes()) > 0 {
|
||||
// strip from includes
|
||||
cs.stripFromRootfs(p.GetIncludes(), rootfs, true)
|
||||
}
|
||||
if len(p.GetExcludes()) > 0 {
|
||||
// strip from includes
|
||||
cs.stripFromRootfs(p.GetExcludes(), rootfs, false)
|
||||
}
|
||||
artifact = NewPackageArtifact(p.Rel(p.GetPackage().GetFingerPrint() + ".package.tar"))
|
||||
artifact.SetCompressionType(cs.CompressionType)
|
||||
|
||||
err = artifact.Compress(rootfs, concurrency)
|
||||
// Take content of container as a base for our package files
|
||||
artifact, err = cs.unpackFs(rootfs, concurrency, p)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error met while creating package archive")
|
||||
return nil, errors.Wrap(err, "Error met while extracting image")
|
||||
}
|
||||
|
||||
artifact.SetCompileSpec(p)
|
||||
} else {
|
||||
Info(pkgTag, ":hammer: Generating delta")
|
||||
diffs, err := cs.Backend.Changes(p.Rel(p.GetPackage().GetFingerPrint()+"-builder.image.tar"), p.Rel(p.GetPackage().GetFingerPrint()+".image.tar"))
|
||||
// Generate delta between the two images
|
||||
artifact, err = cs.unpackDelta(rootfs, concurrency, keepPermissions, p, builderOpts, runnerOpts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not generate changes from layers")
|
||||
return nil, errors.Wrap(err, "Error met while generating delta")
|
||||
}
|
||||
artifact, err = ExtractArtifactFromDelta(rootfs, p.Rel(p.GetPackage().GetFingerPrint()+".package.tar"), diffs, concurrency, keepPermissions, p.GetIncludes(), p.GetExcludes(), cs.CompressionType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Could not generate deltas")
|
||||
}
|
||||
|
||||
artifact.SetCompileSpec(p)
|
||||
}
|
||||
|
||||
filelist, err := artifact.FileList()
|
||||
@@ -456,7 +496,6 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
|
||||
}
|
||||
|
||||
artifact.SetFiles(filelist)
|
||||
|
||||
artifact.GetCompileSpec().GetPackage().SetBuildTimestamp(time.Now().String())
|
||||
|
||||
err = artifact.WriteYaml(p.GetOutputPath())
|
||||
@@ -468,6 +507,59 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
func (cs *LuetCompiler) waitForImage(image string) {
|
||||
if cs.Options.PullFirst && cs.Options.Wait && !cs.Backend.ImageAvailable(image) {
|
||||
Info(fmt.Sprintf("Waiting for image %s to be available... :zzz:", image))
|
||||
Spinner(22)
|
||||
defer SpinnerStop()
|
||||
for !cs.Backend.ImageAvailable(image) {
|
||||
Info(fmt.Sprintf("Image %s not available yet, sleeping", image))
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage string,
|
||||
concurrency int,
|
||||
keepPermissions, keepImg bool,
|
||||
p CompilationSpec, generateArtifact bool) (Artifact, error) {
|
||||
|
||||
if !generateArtifact {
|
||||
exists := cs.Backend.ImageExists(packageImage)
|
||||
if art, err := LoadArtifactFromYaml(p); err == nil && exists { // If YAML is correctly loaded, and both images exists, no reason to rebuild.
|
||||
Debug("Artifact reloaded from YAML. Skipping build")
|
||||
return art, err
|
||||
}
|
||||
cs.waitForImage(packageImage)
|
||||
if cs.Options.PullFirst && cs.Backend.ImageAvailable(packageImage) {
|
||||
return &PackageArtifact{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
builderOpts, runnerOpts, err := cs.buildPackageImage(image, buildertaggedImage, packageImage, concurrency, keepPermissions, p)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed building package image")
|
||||
}
|
||||
|
||||
if !keepImg {
|
||||
defer func() {
|
||||
// We keep them around, so to not reload them from the tar (which should be the "correct way") and we automatically share the same layers
|
||||
if err := cs.Backend.RemoveImage(builderOpts); err != nil {
|
||||
Warning("Could not remove image ", builderOpts.ImageName)
|
||||
}
|
||||
if err := cs.Backend.RemoveImage(runnerOpts); err != nil {
|
||||
Warning("Could not remove image ", runnerOpts.ImageName)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if !generateArtifact {
|
||||
return &PackageArtifact{}, nil
|
||||
}
|
||||
|
||||
return cs.genArtifact(p, builderOpts, runnerOpts, concurrency, keepPermissions)
|
||||
}
|
||||
|
||||
func (cs *LuetCompiler) FromDatabase(db pkg.PackageDatabase, minimum bool, dst string) ([]CompilationSpec, error) {
|
||||
compilerSpecs := NewLuetCompilationspecs()
|
||||
|
||||
@@ -566,6 +658,14 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, p Compila
|
||||
targetAssertion := p.GetSourceAssertion().Search(p.GetPackage().GetFingerPrint())
|
||||
targetPackageHash := cs.ImageRepository + ":" + targetAssertion.Hash.PackageHash
|
||||
|
||||
bus.Manager.Publish(bus.EventPackagePreBuild, struct {
|
||||
CompileSpec CompilationSpec
|
||||
Assert solver.PackageAssert
|
||||
}{
|
||||
CompileSpec: p,
|
||||
Assert: *targetAssertion,
|
||||
})
|
||||
|
||||
// - If image is set we just generate a plain dockerfile
|
||||
// Treat last case (easier) first. The image is provided and we just compute a plain dockerfile with the images listed as above
|
||||
if p.GetImage() != "" {
|
||||
@@ -606,6 +706,14 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, p Compila
|
||||
Debug(pkgTag, " :arrow_right_hook: :whale: Builder image from", buildImageHash)
|
||||
Debug(pkgTag, " :arrow_right_hook: :whale: Package image name", currentPackageImageHash)
|
||||
|
||||
bus.Manager.Publish(bus.EventPackagePreBuild, struct {
|
||||
CompileSpec CompilationSpec
|
||||
Assert solver.PackageAssert
|
||||
}{
|
||||
CompileSpec: compileSpec,
|
||||
Assert: assertion,
|
||||
})
|
||||
|
||||
lastHash = currentPackageImageHash
|
||||
if compileSpec.GetImage() != "" {
|
||||
Debug(pkgTag, " :wrench: Compiling "+compileSpec.GetPackage().HumanReadableString()+" from image")
|
||||
@@ -625,6 +733,15 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, p Compila
|
||||
// deperrs = append(deperrs, err)
|
||||
// break // stop at first error
|
||||
}
|
||||
|
||||
bus.Manager.Publish(bus.EventPackagePostBuild, struct {
|
||||
CompileSpec CompilationSpec
|
||||
Artifact Artifact
|
||||
}{
|
||||
CompileSpec: compileSpec,
|
||||
Artifact: artifact,
|
||||
})
|
||||
|
||||
departifacts = append(departifacts, artifact)
|
||||
Info(pkgTag, ":white_check_mark: Done")
|
||||
}
|
||||
@@ -643,6 +760,14 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, p Compila
|
||||
artifact.SetDependencies(departifacts)
|
||||
artifact.SetSourceAssertion(p.GetSourceAssertion())
|
||||
|
||||
bus.Manager.Publish(bus.EventPackagePostBuild, struct {
|
||||
CompileSpec CompilationSpec
|
||||
Artifact Artifact
|
||||
}{
|
||||
CompileSpec: p,
|
||||
Artifact: artifact,
|
||||
})
|
||||
|
||||
return artifact, err
|
||||
} else {
|
||||
return departifacts[len(departifacts)-1], nil
|
||||
@@ -658,32 +783,51 @@ func (cs *LuetCompiler) FromPackage(p pkg.Package) (CompilationSpec, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buildFile := pack.Rel(BuildFile)
|
||||
if !helpers.Exists(buildFile) {
|
||||
return nil, errors.New("No build file present for " + p.GetFingerPrint())
|
||||
}
|
||||
defFile := pack.Rel(DefinitionFile)
|
||||
if !helpers.Exists(defFile) {
|
||||
return nil, errors.New("No build file present for " + p.GetFingerPrint())
|
||||
}
|
||||
def, err := ioutil.ReadFile(defFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var dataresult []byte
|
||||
|
||||
val := pack.Rel(DefinitionFile)
|
||||
if _, err := os.Stat(pack.Rel(CollectionFile)); err == nil {
|
||||
val = pack.Rel(CollectionFile)
|
||||
|
||||
data, err := ioutil.ReadFile(val)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendering file "+val)
|
||||
}
|
||||
|
||||
dataBuild, err := ioutil.ReadFile(pack.Rel(BuildFile))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendering file "+val)
|
||||
}
|
||||
packsRaw, err := pkg.GetRawPackages(data)
|
||||
|
||||
raw := packsRaw.Find(pack.GetName(), pack.GetCategory(), pack.GetVersion())
|
||||
|
||||
d := map[string]interface{}{}
|
||||
if len(cs.Options.BuildValuesFile) > 0 {
|
||||
defBuild, err := ioutil.ReadFile(cs.Options.BuildValuesFile)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendering file "+val)
|
||||
}
|
||||
err = yaml.Unmarshal(defBuild, &d)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendering file "+val)
|
||||
}
|
||||
}
|
||||
|
||||
dat, err := helpers.RenderHelm(string(dataBuild), raw, d)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendering file "+pack.Rel(BuildFile))
|
||||
}
|
||||
dataresult = []byte(dat)
|
||||
} else {
|
||||
out, err := helpers.RenderFiles(pack.Rel(BuildFile), val, cs.Options.BuildValuesFile)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendering file "+pack.Rel(BuildFile))
|
||||
}
|
||||
dataresult = []byte(out)
|
||||
}
|
||||
|
||||
build, err := ioutil.ReadFile(buildFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var values templatedata
|
||||
if err = yaml.Unmarshal(def, &values); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := helpers.RenderHelm(string(build), values)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewLuetCompilationSpec([]byte(out), pack)
|
||||
return NewLuetCompilationSpec(dataresult, pack)
|
||||
}
|
||||
|
||||
func (cs *LuetCompiler) GetBackend() CompilerBackend {
|
||||
|
@@ -50,8 +50,8 @@ var _ = Describe("Compiler", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2", "chmod +x generate.sh"}))
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "chmod +x generate.sh", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2"}))
|
||||
|
||||
spec.SetOutputPath(tmpdir)
|
||||
compiler.SetConcurrency(2)
|
||||
|
@@ -49,13 +49,13 @@ type CompilerOptions struct {
|
||||
PullFirst, KeepImg, Push bool
|
||||
Concurrency int
|
||||
CompressionType CompressionImplementation
|
||||
Clean bool
|
||||
KeepImageExport bool
|
||||
|
||||
OnlyDeps bool
|
||||
NoDeps bool
|
||||
SolverOptions config.LuetSolverOptions
|
||||
SkipIfMetadataExists bool
|
||||
Wait bool
|
||||
OnlyDeps bool
|
||||
NoDeps bool
|
||||
SolverOptions config.LuetSolverOptions
|
||||
BuildValuesFile string
|
||||
|
||||
PackageTargetOnly bool
|
||||
}
|
||||
@@ -68,7 +68,6 @@ func NewDefaultCompilerOptions() *CompilerOptions {
|
||||
CompressionType: None,
|
||||
KeepImg: true,
|
||||
Concurrency: runtime.NumCPU(),
|
||||
Clean: true,
|
||||
OnlyDeps: false,
|
||||
NoDeps: false,
|
||||
}
|
||||
@@ -78,7 +77,7 @@ type CompilerBackend interface {
|
||||
BuildImage(CompilerBackendOptions) error
|
||||
ExportImage(CompilerBackendOptions) error
|
||||
RemoveImage(CompilerBackendOptions) error
|
||||
Changes(fromImage, toImage string) ([]ArtifactLayer, error)
|
||||
Changes(fromImage, toImage CompilerBackendOptions) ([]ArtifactLayer, error)
|
||||
ImageDefinitionToTar(CompilerBackendOptions) error
|
||||
ExtractRootfs(opts CompilerBackendOptions, keepPerms bool) error
|
||||
|
||||
@@ -86,6 +85,7 @@ type CompilerBackend interface {
|
||||
DownloadImage(opts CompilerBackendOptions) error
|
||||
|
||||
Push(opts CompilerBackendOptions) error
|
||||
ImageAvailable(string) bool
|
||||
|
||||
ImageExists(string) bool
|
||||
}
|
||||
|
@@ -203,10 +203,9 @@ func (cs *LuetCompilationSpec) CopyRetrieves(dest string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: docker build image first. Then a backend can be used to actually spin up a container with it and run the steps within
|
||||
func (cs *LuetCompilationSpec) RenderBuildImage() (string, error) {
|
||||
func (cs *LuetCompilationSpec) genDockerfile(image string, steps []string) string {
|
||||
spec := `
|
||||
FROM ` + cs.GetSeedImage() + `
|
||||
FROM ` + image + `
|
||||
COPY . /luetbuild
|
||||
WORKDIR /luetbuild
|
||||
ENV PACKAGE_NAME=` + cs.Package.GetName() + `
|
||||
@@ -231,31 +230,22 @@ ADD ` + s + ` /luetbuild/`
|
||||
ENV ` + s
|
||||
}
|
||||
|
||||
for _, s := range cs.GetPreBuildSteps() {
|
||||
for _, s := range steps {
|
||||
spec = spec + `
|
||||
RUN ` + s
|
||||
}
|
||||
return spec, nil
|
||||
return spec
|
||||
}
|
||||
|
||||
// TODO: docker build image first. Then a backend can be used to actually spin up a container with it and run the steps within
|
||||
// RenderBuildImage renders the dockerfile of the image used as a pre-build step
|
||||
func (cs *LuetCompilationSpec) RenderBuildImage() (string, error) {
|
||||
return cs.genDockerfile(cs.GetSeedImage(), cs.GetPreBuildSteps()), nil
|
||||
|
||||
}
|
||||
|
||||
// RenderStepImage renders the dockerfile used for the image used for building the package
|
||||
func (cs *LuetCompilationSpec) RenderStepImage(image string) (string, error) {
|
||||
spec := `
|
||||
FROM ` + image + `
|
||||
ENV PACKAGE_NAME=` + cs.Package.GetName() + `
|
||||
ENV PACKAGE_VERSION=` + cs.Package.GetVersion() + `
|
||||
ENV PACKAGE_CATEGORY=` + cs.Package.GetCategory()
|
||||
|
||||
for _, s := range cs.Env {
|
||||
spec = spec + `
|
||||
ENV ` + s
|
||||
}
|
||||
for _, s := range cs.BuildSteps() {
|
||||
spec = spec + `
|
||||
RUN ` + s
|
||||
}
|
||||
|
||||
return spec, nil
|
||||
return cs.genDockerfile(image, cs.BuildSteps()), nil
|
||||
}
|
||||
|
||||
func (cs *LuetCompilationSpec) WriteBuildImageDefinition(path string) error {
|
||||
|
@@ -96,6 +96,8 @@ ENV test=1`))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(dockerfile).To(Equal(`
|
||||
FROM luet/base
|
||||
COPY . /luetbuild
|
||||
WORKDIR /luetbuild
|
||||
ENV PACKAGE_NAME=enman
|
||||
ENV PACKAGE_VERSION=1.4.0
|
||||
ENV PACKAGE_CATEGORY=app-admin
|
||||
@@ -168,9 +170,13 @@ ENV test=1`))
|
||||
|
||||
Expect(dockerfile).To(Equal(`
|
||||
FROM luet/base
|
||||
COPY . /luetbuild
|
||||
WORKDIR /luetbuild
|
||||
ENV PACKAGE_NAME=a
|
||||
ENV PACKAGE_VERSION=1.0
|
||||
ENV PACKAGE_CATEGORY=test
|
||||
ADD test /luetbuild/
|
||||
ADD http://www.google.com /luetbuild/
|
||||
ENV test=1
|
||||
RUN echo foo > /test
|
||||
RUN echo bar > /test2`))
|
||||
|
@@ -28,6 +28,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mudler/luet/pkg/helpers"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
solver "github.com/mudler/luet/pkg/solver"
|
||||
|
||||
v "github.com/spf13/viper"
|
||||
@@ -71,6 +72,15 @@ type LuetSolverOptions struct {
|
||||
Implementation solver.SolverType `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:
|
||||
@@ -267,6 +277,16 @@ func GenDefault(viper *v.Viper) {
|
||||
viper.SetDefault("solver.max_attempts", 9000)
|
||||
}
|
||||
|
||||
func (c *LuetConfig) GetSystemDB() pkg.PackageDatabase {
|
||||
switch LuetCfg.GetSystem().DatabaseEngine {
|
||||
case "boltdb":
|
||||
return pkg.NewBoltDatabase(
|
||||
filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db"))
|
||||
default:
|
||||
return pkg.NewInMemoryDatabase(true)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *LuetConfig) AddSystemRepository(r LuetRepository) {
|
||||
c.SystemRepositories = append(c.SystemRepositories, r)
|
||||
}
|
||||
|
@@ -19,6 +19,8 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
copy "github.com/otiai10/copy"
|
||||
@@ -41,6 +43,8 @@ func OrderFiles(target string, files []string) ([]string, []string) {
|
||||
}
|
||||
}
|
||||
|
||||
dirs := []string{}
|
||||
|
||||
for _, f := range files {
|
||||
target := filepath.Join(target, f)
|
||||
fi, err := os.Lstat(target)
|
||||
@@ -48,11 +52,16 @@ func OrderFiles(target string, files []string) ([]string, []string) {
|
||||
continue
|
||||
}
|
||||
if m := fi.Mode(); m.IsDir() {
|
||||
newFiles = append(newFiles, f)
|
||||
dirs = append(dirs, f)
|
||||
}
|
||||
}
|
||||
|
||||
return newFiles, notPresent
|
||||
// Compare how many sub paths there are, and push at the end the ones that have less subpaths
|
||||
sort.Slice(dirs, func(i, j int) bool {
|
||||
return len(strings.Split(dirs[i], string(os.PathSeparator))) > len(strings.Split(dirs[j], string(os.PathSeparator)))
|
||||
})
|
||||
|
||||
return append(newFiles, dirs...), notPresent
|
||||
}
|
||||
|
||||
func ListDir(dir string) ([]string, error) {
|
||||
|
@@ -60,5 +60,27 @@ var _ = Describe("Helpers", func() {
|
||||
Expect(ordered).To(Equal([]string{"baz", "bar/foo", "foo", "baz2/foo", "bar", "baz2"}))
|
||||
Expect(notExisting).To(Equal([]string{"notexisting"}))
|
||||
})
|
||||
|
||||
It("orders correctly when there are folders with folders", func() {
|
||||
testDir, err := ioutil.TempDir(os.TempDir(), "test")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
err = os.MkdirAll(filepath.Join(testDir, "bar"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = os.MkdirAll(filepath.Join(testDir, "foo"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = os.MkdirAll(filepath.Join(testDir, "foo", "bar"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = os.MkdirAll(filepath.Join(testDir, "foo", "baz"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = os.MkdirAll(filepath.Join(testDir, "foo", "baz", "fa"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
ordered, _ := OrderFiles(testDir, []string{"foo", "foo/bar", "bar", "foo/baz/fa", "foo/baz"})
|
||||
Expect(ordered).To(Equal([]string{"foo/baz/fa", "foo/bar", "foo/baz", "foo", "bar"}))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -1,14 +1,17 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v2"
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chartutil"
|
||||
"helm.sh/helm/v3/pkg/engine"
|
||||
)
|
||||
|
||||
// RenderHelm renders the template string with helm
|
||||
func RenderHelm(template string, values map[string]interface{}) (string, error) {
|
||||
func RenderHelm(template string, values, d map[string]interface{}) (string, error) {
|
||||
c := &chart.Chart{
|
||||
Metadata: &chart.Metadata{
|
||||
Name: "",
|
||||
@@ -20,7 +23,7 @@ func RenderHelm(template string, values map[string]interface{}) (string, error)
|
||||
Values: map[string]interface{}{"Values": values},
|
||||
}
|
||||
|
||||
v, err := chartutil.CoalesceValues(c, map[string]interface{}{})
|
||||
v, err := chartutil.CoalesceValues(c, map[string]interface{}{"Values": d})
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "while rendering template")
|
||||
}
|
||||
@@ -31,3 +34,38 @@ func RenderHelm(template string, values map[string]interface{}) (string, error)
|
||||
|
||||
return out["templates"], nil
|
||||
}
|
||||
|
||||
type templatedata map[string]interface{}
|
||||
|
||||
func RenderFiles(toTemplate, valuesFile string, defaultFile string) (string, error) {
|
||||
raw, err := ioutil.ReadFile(toTemplate)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "reading file "+toTemplate)
|
||||
}
|
||||
|
||||
if !Exists(valuesFile) {
|
||||
return "", errors.Wrap(err, "file not existing "+valuesFile)
|
||||
}
|
||||
val, err := ioutil.ReadFile(valuesFile)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "reading file "+valuesFile)
|
||||
}
|
||||
|
||||
var values templatedata
|
||||
d := templatedata{}
|
||||
if len(defaultFile) > 0 {
|
||||
def, err := ioutil.ReadFile(defaultFile)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "reading file "+valuesFile)
|
||||
}
|
||||
if err = yaml.Unmarshal(def, &d); err != nil {
|
||||
return "", errors.Wrap(err, "unmarshalling file "+toTemplate)
|
||||
}
|
||||
}
|
||||
|
||||
if err = yaml.Unmarshal(val, &values); err != nil {
|
||||
return "", errors.Wrap(err, "unmarshalling file "+toTemplate)
|
||||
}
|
||||
|
||||
return RenderHelm(string(raw), values, d)
|
||||
}
|
||||
|
@@ -16,17 +16,132 @@
|
||||
package helpers_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
. "github.com/mudler/luet/pkg/helpers"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func writeFile(path string, content string) {
|
||||
err := ioutil.WriteFile(path, []byte(content), 0644)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
var _ = Describe("Helpers", func() {
|
||||
Context("RenderHelm", func() {
|
||||
It("Renders templates", func() {
|
||||
out, err := RenderHelm("{{.Values.Test}}", map[string]interface{}{"Test": "foo"})
|
||||
out, err := RenderHelm("{{.Values.Test}}{{.Values.Bar}}", map[string]interface{}{"Test": "foo"}, map[string]interface{}{"Bar": "bar"})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(out).To(Equal("foo"))
|
||||
Expect(out).To(Equal("foobar"))
|
||||
})
|
||||
It("Renders templates with overrides", func() {
|
||||
out, err := RenderHelm("{{.Values.Test}}{{.Values.Bar}}", map[string]interface{}{"Test": "foo", "Bar": "baz"}, map[string]interface{}{"Bar": "bar"})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(out).To(Equal("foobar"))
|
||||
})
|
||||
|
||||
It("Renders templates", func() {
|
||||
out, err := RenderHelm("{{.Values.Test}}{{.Values.Bar}}", map[string]interface{}{"Test": "foo", "Bar": "bar"}, map[string]interface{}{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(out).To(Equal("foobar"))
|
||||
})
|
||||
|
||||
It("Render files default overrides", func() {
|
||||
testDir, err := ioutil.TempDir(os.TempDir(), "test")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
toTemplate := filepath.Join(testDir, "totemplate.yaml")
|
||||
values := filepath.Join(testDir, "values.yaml")
|
||||
d := filepath.Join(testDir, "default.yaml")
|
||||
|
||||
writeFile(toTemplate, `{{.Values.foo}}`)
|
||||
writeFile(values, `
|
||||
foo: "bar"
|
||||
`)
|
||||
writeFile(d, `
|
||||
foo: "baz"
|
||||
`)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
res, err := RenderFiles(toTemplate, values, d)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(res).To(Equal("baz"))
|
||||
|
||||
})
|
||||
|
||||
It("Render files from values", func() {
|
||||
testDir, err := ioutil.TempDir(os.TempDir(), "test")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
toTemplate := filepath.Join(testDir, "totemplate.yaml")
|
||||
values := filepath.Join(testDir, "values.yaml")
|
||||
d := filepath.Join(testDir, "default.yaml")
|
||||
|
||||
writeFile(toTemplate, `{{.Values.foo}}`)
|
||||
writeFile(values, `
|
||||
foo: "bar"
|
||||
`)
|
||||
writeFile(d, `
|
||||
faa: "baz"
|
||||
`)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
res, err := RenderFiles(toTemplate, values, d)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(res).To(Equal("bar"))
|
||||
|
||||
})
|
||||
|
||||
It("Render files from values if no default", func() {
|
||||
testDir, err := ioutil.TempDir(os.TempDir(), "test")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
toTemplate := filepath.Join(testDir, "totemplate.yaml")
|
||||
values := filepath.Join(testDir, "values.yaml")
|
||||
|
||||
writeFile(toTemplate, `{{.Values.foo}}`)
|
||||
writeFile(values, `
|
||||
foo: "bar"
|
||||
`)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
res, err := RenderFiles(toTemplate, values, "")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(res).To(Equal("bar"))
|
||||
})
|
||||
|
||||
It("doesn't interpolate if no one provides the values", func() {
|
||||
testDir, err := ioutil.TempDir(os.TempDir(), "test")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
toTemplate := filepath.Join(testDir, "totemplate.yaml")
|
||||
values := filepath.Join(testDir, "values.yaml")
|
||||
d := filepath.Join(testDir, "default.yaml")
|
||||
|
||||
writeFile(toTemplate, `{{.Values.foo}}`)
|
||||
writeFile(values, `
|
||||
foao: "bar"
|
||||
`)
|
||||
writeFile(d, `
|
||||
faa: "baz"
|
||||
`)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
res, err := RenderFiles(toTemplate, values, d)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(res).To(Equal(""))
|
||||
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -22,6 +22,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
|
||||
@@ -30,6 +31,8 @@ import (
|
||||
"github.com/mudler/luet/pkg/helpers"
|
||||
|
||||
"github.com/cavaliercoder/grab"
|
||||
|
||||
"github.com/schollz/progressbar/v3"
|
||||
)
|
||||
|
||||
type HttpClient struct {
|
||||
@@ -87,7 +90,7 @@ func (c *HttpClient) DownloadArtifact(artifact compiler.Artifact) (compiler.Arti
|
||||
client := grab.NewClient()
|
||||
|
||||
for _, uri := range c.RepoData.Urls {
|
||||
Info("Downloading artifact", artifactName, "from", uri)
|
||||
Debug("Downloading artifact", artifactName, "from", uri)
|
||||
|
||||
u, err = url.Parse(uri)
|
||||
if err != nil {
|
||||
@@ -101,20 +104,61 @@ func (c *HttpClient) DownloadArtifact(artifact compiler.Artifact) (compiler.Arti
|
||||
}
|
||||
|
||||
resp := client.Do(req)
|
||||
|
||||
bar := progressbar.NewOptions64(
|
||||
resp.Size(),
|
||||
progressbar.OptionSetDescription(
|
||||
fmt.Sprintf("[cyan] %s - [reset]",
|
||||
filepath.Base(resp.Request.HTTPRequest.URL.RequestURI()))),
|
||||
progressbar.OptionSetRenderBlankState(true),
|
||||
progressbar.OptionEnableColorCodes(config.LuetCfg.GetLogging().Color),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
progressbar.OptionShowBytes(true),
|
||||
progressbar.OptionShowCount(),
|
||||
progressbar.OptionSetPredictTime(true),
|
||||
progressbar.OptionFullWidth(),
|
||||
progressbar.OptionSetTheme(progressbar.Theme{
|
||||
Saucer: "[white]=[reset]",
|
||||
SaucerHead: "[white]>[reset]",
|
||||
SaucerPadding: " ",
|
||||
BarStart: "[",
|
||||
BarEnd: "]",
|
||||
}))
|
||||
|
||||
bar.Reset()
|
||||
// start download loop
|
||||
t := time.NewTicker(500 * time.Millisecond)
|
||||
defer t.Stop()
|
||||
|
||||
download_loop:
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
bar.Set64(resp.BytesComplete())
|
||||
|
||||
case <-resp.Done:
|
||||
// download is complete
|
||||
break download_loop
|
||||
}
|
||||
}
|
||||
|
||||
if err = resp.Err(); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
Info("Downloaded", artifactName, "of",
|
||||
fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (",
|
||||
fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )")
|
||||
|
||||
Debug("Copying file ", filepath.Join(temp, artifactName), "to", cacheFile)
|
||||
err = helpers.CopyFile(filepath.Join(temp, artifactName), cacheFile)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
Info("\nDownloaded", artifactName, "of",
|
||||
fmt.Sprintf("%.2f", (float64(resp.BytesComplete())/1000)/1000), "MB (",
|
||||
fmt.Sprintf("%.2f", (float64(resp.BytesPerSecond())/1024)/1024), "MiB/s )")
|
||||
|
||||
Debug("\nCopying file ", filepath.Join(temp, artifactName), "to", cacheFile)
|
||||
err = helpers.CopyFile(filepath.Join(temp, artifactName), cacheFile)
|
||||
|
||||
bar.Finish()
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
@@ -158,7 +202,7 @@ func (c *HttpClient) DownloadFile(name string) (string, error) {
|
||||
}
|
||||
u.Path = path.Join(u.Path, name)
|
||||
|
||||
Info("Downloading", u.String())
|
||||
Debug("Downloading", u.String())
|
||||
|
||||
req, err = c.PrepareReq(temp, u.String())
|
||||
if err != nil {
|
||||
|
@@ -24,13 +24,14 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
. "github.com/logrusorgru/aurora"
|
||||
"github.com/mudler/luet/pkg/bus"
|
||||
compiler "github.com/mudler/luet/pkg/compiler"
|
||||
"github.com/mudler/luet/pkg/config"
|
||||
"github.com/mudler/luet/pkg/helpers"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
"github.com/mudler/luet/pkg/solver"
|
||||
"github.com/mudler/luet/pkg/tree"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -45,6 +46,7 @@ type LuetInstallerOptions struct {
|
||||
FullUninstall, FullCleanUninstall bool
|
||||
CheckConflicts bool
|
||||
SolverUpgrade, RemoveUnavailableOnUpgrade, UpgradeNewRevisions bool
|
||||
Ask bool
|
||||
}
|
||||
|
||||
type LuetInstaller struct {
|
||||
@@ -63,7 +65,82 @@ func NewLuetInstaller(opts LuetInstallerOptions) Installer {
|
||||
return &LuetInstaller{Options: opts}
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
|
||||
if l.Options.SolverUpgrade {
|
||||
uninstall, solution, err = solv.UpgradeUniverse(l.Options.RemoveUnavailableOnUpgrade)
|
||||
if err != nil {
|
||||
return uninstall, toInstall, errors.Wrap(err, "Failed solving solution for upgrade")
|
||||
}
|
||||
} else {
|
||||
uninstall, solution, err = solv.Upgrade(l.Options.FullUninstall, true)
|
||||
if err != nil {
|
||||
return uninstall, toInstall, errors.Wrap(err, "Failed solving solution for upgrade")
|
||||
}
|
||||
}
|
||||
|
||||
for _, assertion := range solution {
|
||||
// Be sure to filter from solutions packages already installed in the system
|
||||
if _, err := s.Database.FindPackage(assertion.Package); err != nil && assertion.Value {
|
||||
toInstall = append(toInstall, assertion.Package)
|
||||
}
|
||||
}
|
||||
|
||||
if l.Options.UpgradeNewRevisions {
|
||||
for _, p := range s.Database.World() {
|
||||
matches := syncedRepos.PackageMatches(pkg.Packages{p})
|
||||
if len(matches) == 0 {
|
||||
// Package missing. the user should run luet upgrade --universe
|
||||
continue
|
||||
}
|
||||
for _, artefact := range matches[0].Repo.GetIndex() {
|
||||
if artefact.GetCompileSpec().GetPackage() == nil {
|
||||
return uninstall, toInstall, errors.New("Package in compilespec empty")
|
||||
|
||||
}
|
||||
if artefact.GetCompileSpec().GetPackage().Matches(p) && artefact.GetCompileSpec().GetPackage().GetBuildTimestamp() != p.GetBuildTimestamp() {
|
||||
toInstall = append(toInstall, matches[0].Package).Unique()
|
||||
uninstall = append(uninstall, p).Unique()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uninstall, toInstall, nil
|
||||
}
|
||||
|
||||
func packsToList(p pkg.Packages) string {
|
||||
var packs []string
|
||||
|
||||
for _, pp := range p {
|
||||
packs = append(packs, pp.HumanReadableString())
|
||||
}
|
||||
return strings.Join(packs, " ")
|
||||
}
|
||||
|
||||
func matchesToList(artefacts map[string]ArtifactMatch) string {
|
||||
var packs []string
|
||||
|
||||
for fingerprint, match := range artefacts {
|
||||
packs = append(packs, fmt.Sprintf("%s (%s)", fingerprint, match.Repository.GetName()))
|
||||
}
|
||||
return strings.Join(packs, " ")
|
||||
}
|
||||
|
||||
// Upgrade upgrades a System based on the Installer options. Returns error in case of failure
|
||||
func (l *LuetInstaller) Upgrade(s *System) error {
|
||||
|
||||
syncedRepos, err := l.SyncRepositories(true)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -73,84 +150,40 @@ func (l *LuetInstaller) Upgrade(s *System) error {
|
||||
if l.Options.UpgradeNewRevisions {
|
||||
Info(":memo: note: will consider new build revisions while upgrading")
|
||||
}
|
||||
|
||||
Spinner(32)
|
||||
defer SpinnerStop()
|
||||
// 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 uninstall pkg.Packages
|
||||
var solution solver.PackagesAssertions
|
||||
|
||||
if l.Options.SolverUpgrade {
|
||||
|
||||
uninstall, solution, err = solv.UpgradeUniverse(l.Options.RemoveUnavailableOnUpgrade)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed solving solution for upgrade")
|
||||
}
|
||||
} else {
|
||||
uninstall, solution, err = solv.Upgrade(!l.Options.FullUninstall, l.Options.NoDeps)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed solving solution for upgrade")
|
||||
}
|
||||
|
||||
uninstall, toInstall, err := l.computeUpgrade(syncedRepos, s)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed computing upgrade")
|
||||
}
|
||||
SpinnerStop()
|
||||
|
||||
if len(uninstall) > 0 {
|
||||
Info(":recycle: Packages marked for uninstall:")
|
||||
Info(":recycle: Packages that are going to be removed from the system:\n ", Yellow(packsToList(uninstall)).BgBlack().String())
|
||||
}
|
||||
|
||||
for _, p := range uninstall {
|
||||
Info(fmt.Sprintf("- %s", p.HumanReadableString()))
|
||||
if len(toInstall) > 0 {
|
||||
Info(":zap:Packages that are going to be installed in the system:\n ", Green(packsToList(toInstall)).BgBlack().String())
|
||||
}
|
||||
|
||||
if len(solution) > 0 {
|
||||
Info(":zap: Packages marked for upgrade:")
|
||||
if len(toInstall) == 0 && len(uninstall) == 0 {
|
||||
Info("Nothing to do")
|
||||
return nil
|
||||
}
|
||||
|
||||
toInstall := pkg.Packages{}
|
||||
for _, assertion := range solution {
|
||||
// Be sure to filter from solutions packages already installed in the system
|
||||
if _, err := s.Database.FindPackage(assertion.Package); err != nil && assertion.Value {
|
||||
Info(fmt.Sprintf("- %s", assertion.Package.HumanReadableString()))
|
||||
toInstall = append(toInstall, assertion.Package)
|
||||
if l.Options.Ask {
|
||||
Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.")
|
||||
if Ask() {
|
||||
l.Options.Ask = false // Don't prompt anymore
|
||||
return l.swap(syncedRepos, uninstall, toInstall, s, true)
|
||||
} else {
|
||||
return errors.New("Aborted by user")
|
||||
}
|
||||
}
|
||||
|
||||
if l.Options.UpgradeNewRevisions {
|
||||
Info(":mag: Checking packages with new revisions available")
|
||||
for _, p := range s.Database.World() {
|
||||
matches := syncedRepos.PackageMatches(pkg.Packages{p})
|
||||
if len(matches) == 0 {
|
||||
// Package missing. the user should run luet upgrade --universe
|
||||
Info(":warning: Installed packages seems to be missing from remote repositories.")
|
||||
Info(":warning: It is suggested to run 'luet upgrade --universe'")
|
||||
continue
|
||||
}
|
||||
for _, artefact := range matches[0].Repo.GetIndex() {
|
||||
if artefact.GetCompileSpec().GetPackage() == nil {
|
||||
return errors.New("Package in compilespec empty")
|
||||
|
||||
}
|
||||
if artefact.GetCompileSpec().GetPackage().Matches(p) && artefact.GetCompileSpec().GetPackage().GetBuildTimestamp() != p.GetBuildTimestamp() {
|
||||
toInstall = append(toInstall, matches[0].Package).Unique()
|
||||
uninstall = append(uninstall, p).Unique()
|
||||
Info(
|
||||
fmt.Sprintf("- %s ( %s vs %s ) repo: %s (date: %s)",
|
||||
p.HumanReadableString(),
|
||||
artefact.GetCompileSpec().GetPackage().GetBuildTimestamp(),
|
||||
p.GetBuildTimestamp(),
|
||||
matches[0].Repo.GetName(),
|
||||
matches[0].Repo.GetLastUpdate(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return l.swap(syncedRepos, uninstall, toInstall, s)
|
||||
Spinner(32)
|
||||
defer SpinnerStop()
|
||||
return l.swap(syncedRepos, uninstall, toInstall, s, true)
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) SyncRepositories(inMemory bool) (Repositories, error) {
|
||||
@@ -180,19 +213,55 @@ func (l *LuetInstaller) Swap(toRemove pkg.Packages, toInstall pkg.Packages, s *S
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return l.swap(syncedRepos, toRemove, toInstall, s)
|
||||
|
||||
toRemoveFinal := pkg.Packages{}
|
||||
for _, p := range toRemove {
|
||||
packs, _ := s.Database.FindPackages(p)
|
||||
if len(packs) == 0 {
|
||||
return errors.New("Package " + p.HumanReadableString() + " not found in the system")
|
||||
}
|
||||
for _, pp := range packs {
|
||||
toRemoveFinal = append(toRemoveFinal, pp)
|
||||
}
|
||||
}
|
||||
|
||||
return l.swap(syncedRepos, toRemoveFinal, toInstall, s, false)
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) swap(syncedRepos Repositories, toRemove pkg.Packages, toInstall pkg.Packages, s *System) error {
|
||||
// First match packages against repositories by priority
|
||||
func (l *LuetInstaller) computeSwap(syncedRepos Repositories, toRemove pkg.Packages, toInstall pkg.Packages, s *System) (map[string]ArtifactMatch, pkg.Packages, solver.PackagesAssertions, pkg.PackageDatabase, error) {
|
||||
|
||||
allRepos := pkg.NewInMemoryDatabase(false)
|
||||
syncedRepos.SyncDatabase(allRepos)
|
||||
|
||||
toInstall = syncedRepos.ResolveSelectors(toInstall)
|
||||
|
||||
if err := l.download(syncedRepos, toInstall); err != nil {
|
||||
return errors.Wrap(err, "Pre-downloading packages")
|
||||
// First check what would have been done
|
||||
installedtmp, err := s.Database.Copy()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Failed create temporary in-memory db")
|
||||
}
|
||||
|
||||
systemAfterChanges := &System{Database: installedtmp}
|
||||
|
||||
packs, err := l.computeUninstall(systemAfterChanges, toRemove...)
|
||||
if err != nil && !l.Options.Force {
|
||||
Error("Failed computing uninstall for ", packsToList(toRemove))
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "computing uninstall "+packsToList(toRemove))
|
||||
}
|
||||
for _, p := range packs {
|
||||
err = systemAfterChanges.Database.RemovePackage(p)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "Failed removing package from database")
|
||||
}
|
||||
}
|
||||
|
||||
return l.computeInstall(syncedRepos, toInstall, systemAfterChanges)
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) swap(syncedRepos Repositories, toRemove pkg.Packages, toInstall pkg.Packages, s *System, forceNodeps bool) error {
|
||||
forced := l.Options.Force
|
||||
nodeps := l.Options.NoDeps
|
||||
|
||||
// We don't want any conflict with the installed to raise during the upgrade.
|
||||
// In this way we both force uninstalls and we avoid to check with conflicts
|
||||
// against the current system state which is pending to deletion
|
||||
@@ -200,23 +269,47 @@ func (l *LuetInstaller) swap(syncedRepos Repositories, toRemove pkg.Packages, to
|
||||
// if the old A results installed in the system. This is due to the fact that
|
||||
// now the solver enforces the constraints and explictly denies two packages
|
||||
// of the same version installed.
|
||||
forced := l.Options.Force
|
||||
|
||||
l.Options.Force = true
|
||||
if forceNodeps {
|
||||
l.Options.NoDeps = true
|
||||
}
|
||||
|
||||
for _, u := range toRemove {
|
||||
Info(":package:", u.HumanReadableString(), "Marked for deletion")
|
||||
match, packages, assertions, allRepos, err := l.computeSwap(syncedRepos, toRemove, toInstall, s)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed computing package replacement")
|
||||
}
|
||||
|
||||
err := l.Uninstall(u, s)
|
||||
if err != nil && !l.Options.Force {
|
||||
Error("Failed uninstall for ", u.HumanReadableString())
|
||||
return errors.Wrap(err, "uninstalling "+u.HumanReadableString())
|
||||
if l.Options.Ask {
|
||||
if len(toRemove) > 0 {
|
||||
Info(":recycle: Packages that are going to be removed from the system:\n ", Yellow(packsToList(toRemove)).BgBlack().String())
|
||||
}
|
||||
|
||||
}
|
||||
l.Options.Force = forced
|
||||
if len(match) > 0 {
|
||||
Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String())
|
||||
}
|
||||
|
||||
return l.install(syncedRepos, toInstall, s)
|
||||
Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.")
|
||||
if Ask() {
|
||||
l.Options.Ask = false // Don't prompt anymore
|
||||
} else {
|
||||
return errors.New("Aborted by user")
|
||||
}
|
||||
}
|
||||
|
||||
// First match packages against repositories by priority
|
||||
if err := l.download(syncedRepos, match); err != nil {
|
||||
return errors.Wrap(err, "Pre-downloading packages")
|
||||
}
|
||||
|
||||
err = l.Uninstall(s, toRemove...)
|
||||
if err != nil && !l.Options.Force {
|
||||
Error("Failed uninstall for ", packsToList(toRemove))
|
||||
return errors.Wrap(err, "uninstalling "+packsToList(toRemove))
|
||||
}
|
||||
|
||||
l.Options.Force = forced
|
||||
l.Options.NoDeps = nodeps
|
||||
return l.install(syncedRepos, match, packages, assertions, allRepos, s)
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error {
|
||||
@@ -224,35 +317,54 @@ func (l *LuetInstaller) Install(cp pkg.Packages, s *System) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return l.install(syncedRepos, cp, s)
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) download(syncedRepos Repositories, cp pkg.Packages) error {
|
||||
toDownload := map[string]ArtifactMatch{}
|
||||
|
||||
// FIXME: This can be optimized. We don't need to re-match this to the repository
|
||||
// But we could just do it once
|
||||
|
||||
// Gathers things to download
|
||||
for _, currentPack := range cp {
|
||||
matches := syncedRepos.PackageMatches(pkg.Packages{currentPack})
|
||||
if len(matches) == 0 {
|
||||
return errors.New("Failed matching solutions against repository for " + currentPack.HumanReadableString() + " where are definitions coming from?!")
|
||||
}
|
||||
A:
|
||||
for _, artefact := range matches[0].Repo.GetIndex() {
|
||||
if artefact.GetCompileSpec().GetPackage() == nil {
|
||||
return errors.New("Package in compilespec empty")
|
||||
match, packages, assertions, allRepos, err := l.computeInstall(syncedRepos, cp, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if we have to process something, or return to the user an error
|
||||
if len(match) == 0 {
|
||||
Info("No packages to install")
|
||||
return nil
|
||||
}
|
||||
// Resolvers might decide to remove some packages from being installed
|
||||
if !l.Options.SolverOptions.ResolverIsSet() {
|
||||
for _, p := range cp {
|
||||
found := false
|
||||
vers, _ := s.Database.FindPackageVersions(p) // If was installed, it is found, as it was filtered
|
||||
if len(vers) >= 1 {
|
||||
found = true
|
||||
continue
|
||||
}
|
||||
if matches[0].Package.Matches(artefact.GetCompileSpec().GetPackage()) {
|
||||
|
||||
toDownload[currentPack.GetFingerPrint()] = ArtifactMatch{Package: currentPack, Artifact: artefact, Repository: matches[0].Repo}
|
||||
for _, m := range match {
|
||||
if m.Package.GetName() == p.GetName() {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
break A
|
||||
if !found {
|
||||
return fmt.Errorf("Package '%s' not found", p.HumanReadableString())
|
||||
}
|
||||
}
|
||||
}
|
||||
Info("Packages that are going to be installed in the system: \n ", Green(matchesToList(match)).BgBlack().String())
|
||||
|
||||
if l.Options.Ask {
|
||||
Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.")
|
||||
if Ask() {
|
||||
l.Options.Ask = false // Don't prompt anymore
|
||||
return l.install(syncedRepos, match, packages, assertions, allRepos, s)
|
||||
} else {
|
||||
return errors.New("Aborted by user")
|
||||
}
|
||||
}
|
||||
return l.install(syncedRepos, match, packages, assertions, allRepos, s)
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) download(syncedRepos Repositories, toDownload map[string]ArtifactMatch) error {
|
||||
|
||||
// Download packages into cache in parallel.
|
||||
all := make(chan ArtifactMatch)
|
||||
|
||||
@@ -316,23 +428,25 @@ func (l *LuetInstaller) Reclaim(s *System) error {
|
||||
return errors.Wrap(err, "Failed creating package")
|
||||
}
|
||||
s.Database.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: pack.GetFingerPrint(), Files: match.Artifact.GetFiles()})
|
||||
Info(":zap: Reclaimed package:", pack.HumanReadableString())
|
||||
Info(":zap:Reclaimed package:", pack.HumanReadableString())
|
||||
}
|
||||
Info("Done!")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *System) error {
|
||||
func (l *LuetInstaller) computeInstall(syncedRepos Repositories, cp pkg.Packages, s *System) (map[string]ArtifactMatch, pkg.Packages, solver.PackagesAssertions, pkg.PackageDatabase, error) {
|
||||
var p pkg.Packages
|
||||
toInstall := map[string]ArtifactMatch{}
|
||||
allRepos := pkg.NewInMemoryDatabase(false)
|
||||
var solution solver.PackagesAssertions
|
||||
|
||||
// Check if the package is installed first
|
||||
for _, pi := range cp {
|
||||
|
||||
vers, _ := s.Database.FindPackageVersions(pi)
|
||||
|
||||
if len(vers) >= 1 {
|
||||
Warning("Filtering out package " + pi.HumanReadableString() + ", it has other versions already installed. Uninstall one of them first ")
|
||||
// Warning("Filtering out package " + pi.HumanReadableString() + ", it has other versions already installed. Uninstall one of them first ")
|
||||
continue
|
||||
//return errors.New("Package " + pi.GetFingerPrint() + " has other versions already installed. Uninstall one of them first: " + strings.Join(vers, " "))
|
||||
|
||||
@@ -341,8 +455,7 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
|
||||
}
|
||||
|
||||
if len(p) == 0 {
|
||||
Warning("No package to install, bailing out with no errors")
|
||||
return nil
|
||||
return toInstall, p, solution, allRepos, nil
|
||||
}
|
||||
// First get metas from all repos (and decodes trees)
|
||||
|
||||
@@ -350,25 +463,19 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
|
||||
// matches := syncedRepos.PackageMatches(p)
|
||||
|
||||
// compute a "big" world
|
||||
allRepos := pkg.NewInMemoryDatabase(false)
|
||||
syncedRepos.SyncDatabase(allRepos)
|
||||
p = syncedRepos.ResolveSelectors(p)
|
||||
toInstall := map[string]ArtifactMatch{}
|
||||
var packagesToInstall pkg.Packages
|
||||
var err error
|
||||
var solution solver.PackagesAssertions
|
||||
|
||||
if !l.Options.NoDeps {
|
||||
Info(":deciduous_tree: Computing installation, hang tight")
|
||||
solv := solver.NewResolver(solver.Options{Type: l.Options.SolverOptions.Implementation, Concurrency: l.Options.Concurrency}, s.Database, allRepos, pkg.NewInMemoryDatabase(false), l.Options.SolverOptions.Resolver())
|
||||
solution, err = solv.Install(p)
|
||||
/// TODO: PackageAssertions needs to be a map[fingerprint]pack so lookup is in O(1)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Failed solving solution for package")
|
||||
return toInstall, p, solution, allRepos, errors.Wrap(err, "Failed solving solution for package")
|
||||
}
|
||||
Info(":deciduous_tree: Finished calculating dependencies")
|
||||
// Gathers things to install
|
||||
Info(":deciduous_tree: Checking for packages already installed, and prepare for installation")
|
||||
for _, assertion := range solution {
|
||||
if assertion.Value {
|
||||
if _, err := s.Database.FindPackage(assertion.Package); err == nil {
|
||||
@@ -387,52 +494,41 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
|
||||
packagesToInstall = append(packagesToInstall, currentPack)
|
||||
}
|
||||
}
|
||||
Info(":deciduous_tree: Finding packages to install from :cloud:")
|
||||
// Gathers things to install
|
||||
for _, currentPack := range packagesToInstall {
|
||||
// Check if package is already installed.
|
||||
|
||||
matches := syncedRepos.PackageMatches(pkg.Packages{currentPack})
|
||||
if len(matches) == 0 {
|
||||
return errors.New("Failed matching solutions against repository for " + currentPack.HumanReadableString() + " where are definitions coming from?!")
|
||||
return toInstall, p, solution, allRepos, errors.New("Failed matching solutions against repository for " + currentPack.HumanReadableString() + " where are definitions coming from?!")
|
||||
}
|
||||
A:
|
||||
for _, artefact := range matches[0].Repo.GetIndex() {
|
||||
if artefact.GetCompileSpec().GetPackage() == nil {
|
||||
return errors.New("Package in compilespec empty")
|
||||
|
||||
return toInstall, p, solution, allRepos, errors.New("Package in compilespec empty")
|
||||
}
|
||||
if matches[0].Package.Matches(artefact.GetCompileSpec().GetPackage()) {
|
||||
currentPack.SetBuildTimestamp(artefact.GetCompileSpec().GetPackage().GetBuildTimestamp())
|
||||
// Filter out already installed
|
||||
if _, err := s.Database.FindPackage(currentPack); err != nil {
|
||||
toInstall[currentPack.GetFingerPrint()] = ArtifactMatch{Package: currentPack, Artifact: artefact, Repository: matches[0].Repo}
|
||||
Info("\t:package:", currentPack.HumanReadableString(), ":cloud:", matches[0].Repo.GetName())
|
||||
}
|
||||
break A
|
||||
}
|
||||
}
|
||||
}
|
||||
return toInstall, p, solution, allRepos, nil
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) install(syncedRepos Repositories, toInstall map[string]ArtifactMatch, p pkg.Packages, solution solver.PackagesAssertions, allRepos pkg.PackageDatabase, s *System) error {
|
||||
// Install packages into rootfs in parallel.
|
||||
if err := l.download(syncedRepos, toInstall); err != nil {
|
||||
return errors.Wrap(err, "Downloading packages")
|
||||
}
|
||||
|
||||
all := make(chan ArtifactMatch)
|
||||
|
||||
var wg = new(sync.WaitGroup)
|
||||
|
||||
// Download first
|
||||
for i := 0; i < l.Options.Concurrency; i++ {
|
||||
wg.Add(1)
|
||||
go l.downloadWorker(i, wg, all)
|
||||
}
|
||||
|
||||
for _, c := range toInstall {
|
||||
all <- c
|
||||
}
|
||||
close(all)
|
||||
wg.Wait()
|
||||
|
||||
all = make(chan ArtifactMatch)
|
||||
|
||||
wg = new(sync.WaitGroup)
|
||||
wg := new(sync.WaitGroup)
|
||||
|
||||
// Do the real install
|
||||
for i := 0; i < l.Options.Concurrency; i++ {
|
||||
@@ -452,9 +548,9 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Failed creating package")
|
||||
}
|
||||
bus.Manager.Publish(bus.EventPackageInstall, c)
|
||||
}
|
||||
executedFinalizer := map[string]bool{}
|
||||
|
||||
var toFinalize []pkg.Package
|
||||
if !l.Options.NoDeps {
|
||||
// TODO: Lower those errors as warning
|
||||
for _, w := range p {
|
||||
@@ -466,36 +562,17 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
|
||||
ORDER:
|
||||
for _, ass := range ordered {
|
||||
if ass.Value {
|
||||
|
||||
installed, ok := toInstall[ass.Package.GetFingerPrint()]
|
||||
if !ok {
|
||||
// It was a dep already installed in the system, so we can skip it safely
|
||||
continue ORDER
|
||||
}
|
||||
|
||||
treePackage, err := installed.Repository.GetTree().GetDatabase().FindPackage(ass.Package)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error getting package "+ass.Package.HumanReadableString())
|
||||
}
|
||||
if helpers.Exists(treePackage.Rel(tree.FinalizerFile)) {
|
||||
finalizerRaw, err := ioutil.ReadFile(treePackage.Rel(tree.FinalizerFile))
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Error reading file "+treePackage.Rel(tree.FinalizerFile))
|
||||
}
|
||||
if _, exists := executedFinalizer[ass.Package.GetFingerPrint()]; !exists {
|
||||
Info("Executing finalizer for " + ass.Package.HumanReadableString())
|
||||
finalizer, err := NewLuetFinalizerFromYaml(finalizerRaw)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Error reading finalizer "+treePackage.Rel(tree.FinalizerFile))
|
||||
}
|
||||
err = finalizer.RunInstall(s)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Error executing install finalizer "+treePackage.Rel(tree.FinalizerFile))
|
||||
}
|
||||
executedFinalizer[ass.Package.GetFingerPrint()] = true
|
||||
}
|
||||
}
|
||||
|
||||
toFinalize = append(toFinalize, treePackage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,29 +583,11 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error getting package "+c.Package.HumanReadableString())
|
||||
}
|
||||
if helpers.Exists(treePackage.Rel(tree.FinalizerFile)) {
|
||||
finalizerRaw, err := ioutil.ReadFile(treePackage.Rel(tree.FinalizerFile))
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Error reading file "+treePackage.Rel(tree.FinalizerFile))
|
||||
}
|
||||
if _, exists := executedFinalizer[c.Package.GetFingerPrint()]; !exists {
|
||||
Info(":shell: Executing finalizer for " + c.Package.HumanReadableString())
|
||||
finalizer, err := NewLuetFinalizerFromYaml(finalizerRaw)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Error reading finalizer "+treePackage.Rel(tree.FinalizerFile))
|
||||
}
|
||||
err = finalizer.RunInstall(s)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Error executing install finalizer "+treePackage.Rel(tree.FinalizerFile))
|
||||
}
|
||||
executedFinalizer[c.Package.GetFingerPrint()] = true
|
||||
}
|
||||
}
|
||||
toFinalize = append(toFinalize, treePackage)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
return s.ExecuteFinalizers(toFinalize)
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) downloadPackage(a ArtifactMatch) (compiler.Artifact, error) {
|
||||
@@ -539,7 +598,7 @@ func (l *LuetInstaller) downloadPackage(a ArtifactMatch) (compiler.Artifact, err
|
||||
}
|
||||
|
||||
err = artifact.Verify()
|
||||
if err != nil && !l.Options.Force {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Artifact integrity check failure")
|
||||
}
|
||||
return artifact, nil
|
||||
@@ -573,15 +632,11 @@ func (l *LuetInstaller) downloadWorker(i int, wg *sync.WaitGroup, c <-chan Artif
|
||||
for p := range c {
|
||||
// TODO: Keep trace of what was added from the tar, and save it into system
|
||||
_, err := l.downloadPackage(p)
|
||||
if err != nil && !l.Options.Force {
|
||||
//TODO: Uninstall, rollback.
|
||||
Fatal("Failed installing package "+p.Package.GetName(), err.Error())
|
||||
return errors.Wrap(err, "Failed installing package "+p.Package.GetName())
|
||||
}
|
||||
if err == nil {
|
||||
Info(":package: ", p.Package.HumanReadableString(), "downloaded")
|
||||
} else if err != nil && l.Options.Force {
|
||||
Info(":package: ", p.Package.HumanReadableString(), "downloaded with failures (force download)")
|
||||
if err != nil {
|
||||
Fatal("Failed downloading package "+p.Package.GetName(), err.Error())
|
||||
return errors.Wrap(err, "Failed downloading package "+p.Package.GetName())
|
||||
} else {
|
||||
Info(":package: Package ", p.Package.HumanReadableString(), "downloaded")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,9 +655,9 @@ func (l *LuetInstaller) installerWorker(i int, wg *sync.WaitGroup, c <-chan Arti
|
||||
return errors.Wrap(err, "Failed installing package "+p.Package.GetName())
|
||||
}
|
||||
if err == nil {
|
||||
Info(":package: ", p.Package.HumanReadableString(), "installed")
|
||||
Info(":package: Package ", p.Package.HumanReadableString(), "installed")
|
||||
} else if err != nil && l.Options.Force {
|
||||
Info(":package: ", p.Package.HumanReadableString(), "installed with failures (force install)")
|
||||
Info(":package: Package ", p.Package.HumanReadableString(), "installed with failures (forced install)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,16 +749,15 @@ func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error {
|
||||
return errors.Wrap(err, "Failed removing package from database")
|
||||
}
|
||||
|
||||
Info(":recycle:", p.GetFingerPrint(), "Removed :heavy_check_mark:")
|
||||
bus.Manager.Publish(bus.EventPackageUnInstall, p)
|
||||
|
||||
Info(":recycle: ", p.GetFingerPrint(), "Removed :heavy_check_mark:")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) Uninstall(p pkg.Package, s *System) error {
|
||||
Spinner(32)
|
||||
defer SpinnerStop()
|
||||
|
||||
Info(":recycle: Uninstalling :package:", p.HumanReadableString(), "hang tight")
|
||||
func (l *LuetInstaller) computeUninstall(s *System, packs ...pkg.Package) (pkg.Packages, error) {
|
||||
|
||||
var toUninstall pkg.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 := l.Options.CheckConflicts
|
||||
@@ -715,49 +769,79 @@ func (l *LuetInstaller) Uninstall(p pkg.Package, s *System) error {
|
||||
|
||||
// Create a temporary DB with the installed packages
|
||||
// so the solver is much faster finding the deptree
|
||||
installedtmp := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
for _, i := range s.Database.World() {
|
||||
_, err := installedtmp.CreatePackage(i)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed create temporary in-memory db")
|
||||
}
|
||||
// First check what would have been done
|
||||
installedtmp, err := s.Database.Copy()
|
||||
if err != nil {
|
||||
return toUninstall, errors.Wrap(err, "Failed create temporary in-memory db")
|
||||
}
|
||||
|
||||
if !l.Options.NoDeps {
|
||||
Info(":mag: Finding :package:", p.HumanReadableString(), "dependency graph :deciduous_tree:")
|
||||
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
|
||||
var err error
|
||||
if l.Options.FullCleanUninstall {
|
||||
solution, err = solv.UninstallUniverse(pkg.Packages{p})
|
||||
solution, err = solv.UninstallUniverse(packs)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Could not solve the uninstall constraints. Tip: try with --solver-type qlearning or with --force, or by removing packages excluding their dependencies with --nodeps")
|
||||
return toUninstall, errors.Wrap(err, "Could not solve the uninstall constraints. Tip: try with --solver-type qlearning or with --force, or by removing packages excluding their dependencies with --nodeps")
|
||||
}
|
||||
} else {
|
||||
solution, err = solv.Uninstall(p, checkConflicts, full)
|
||||
solution, err = solv.Uninstall(checkConflicts, full, packs...)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Could not solve the uninstall constraints. Tip: try with --solver-type qlearning or with --force, or by removing packages excluding their dependencies with --nodeps")
|
||||
return toUninstall, errors.Wrap(err, "Could not solve the uninstall constraints. Tip: try with --solver-type qlearning or with --force, or by removing packages excluding their dependencies with --nodeps")
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range solution {
|
||||
Info(":recycle: Uninstalling", p.HumanReadableString())
|
||||
toUninstall = append(toUninstall, p)
|
||||
}
|
||||
} else {
|
||||
toUninstall = append(toUninstall, packs...)
|
||||
}
|
||||
|
||||
return toUninstall, nil
|
||||
}
|
||||
func (l *LuetInstaller) Uninstall(s *System, packs ...pkg.Package) error {
|
||||
|
||||
for _, p := range packs {
|
||||
if packs, _ := s.Database.FindPackages(p); len(packs) == 0 {
|
||||
return errors.New("Package not found in the system")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Spinner(32)
|
||||
toUninstall, err := l.computeUninstall(s, packs...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "while computing uninstall")
|
||||
}
|
||||
SpinnerStop()
|
||||
|
||||
uninstall := func() error {
|
||||
for _, p := range toUninstall {
|
||||
err := l.uninstall(p, s)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Uninstall failed")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Info(":recycle: Uninstalling", p.HumanReadableString(), "without deps")
|
||||
err := l.uninstall(p, s)
|
||||
if err != nil && !l.Options.Force {
|
||||
return errors.Wrap(err, "Uninstall failed")
|
||||
}
|
||||
Info(":recycle: :package:", p.HumanReadableString(), "uninstalled :heavy_check_mark:")
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
|
||||
if len(toUninstall) == 0 {
|
||||
Info("Nothing to do")
|
||||
return nil
|
||||
}
|
||||
|
||||
if l.Options.Ask {
|
||||
Info(":recycle: Packages that are going to be removed from the system:\n ", Yellow(packsToList(toUninstall)).BgBlack().String())
|
||||
Info("By going forward, you are also accepting the licenses of the packages that you are going to install in your system.")
|
||||
if Ask() {
|
||||
l.Options.Ask = false // Don't prompt anymore
|
||||
return uninstall()
|
||||
} else {
|
||||
return errors.New("Aborted by user")
|
||||
}
|
||||
}
|
||||
return uninstall()
|
||||
}
|
||||
|
||||
func (l *LuetInstaller) Repositories(r []Repository) { l.PackageRepositories = r }
|
||||
|
@@ -60,8 +60,8 @@ var _ = Describe("Installer", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2", "chmod +x generate.sh"}))
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "chmod +x generate.sh", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2"}))
|
||||
|
||||
spec.SetOutputPath(tmpdir)
|
||||
c.SetConcurrency(2)
|
||||
@@ -134,7 +134,7 @@ urls:
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(p.GetName()).To(Equal("b"))
|
||||
|
||||
err = inst.Uninstall(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}, system)
|
||||
err = inst.Uninstall(system, &pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Nothing should be there anymore (files, packagedb entry)
|
||||
@@ -176,8 +176,8 @@ urls:
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2", "chmod +x generate.sh"}))
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "chmod +x generate.sh", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2"}))
|
||||
|
||||
spec.SetOutputPath(tmpdir)
|
||||
c.SetConcurrency(2)
|
||||
@@ -253,7 +253,7 @@ urls:
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(p.GetName()).To(Equal("b"))
|
||||
|
||||
err = inst.Uninstall(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}, system)
|
||||
err = inst.Uninstall(system, &pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Nothing should be there anymore (files, packagedb entry)
|
||||
@@ -294,8 +294,8 @@ urls:
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2", "chmod +x generate.sh"}))
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "chmod +x generate.sh", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2"}))
|
||||
|
||||
spec.SetOutputPath(tmpdir)
|
||||
c.SetConcurrency(2)
|
||||
@@ -373,7 +373,7 @@ urls:
|
||||
Expect(files).To(Equal([]string{"artifact42", "test5", "test6"}))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = inst.Uninstall(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}, system)
|
||||
err = inst.Uninstall(system, &pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Nothing should be there anymore (files, packagedb entry)
|
||||
@@ -412,8 +412,8 @@ urls:
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2", "chmod +x generate.sh"}))
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "chmod +x generate.sh", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2"}))
|
||||
|
||||
spec.SetOutputPath(tmpdir)
|
||||
c.SetConcurrency(2)
|
||||
|
@@ -24,7 +24,7 @@ import (
|
||||
|
||||
type Installer interface {
|
||||
Install(pkg.Packages, *System) error
|
||||
Uninstall(pkg.Package, *System) error
|
||||
Uninstall(*System, ...pkg.Package) error
|
||||
Upgrade(s *System) error
|
||||
Reclaim(s *System) error
|
||||
|
||||
|
@@ -26,6 +26,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mudler/luet/pkg/bus"
|
||||
"github.com/mudler/luet/pkg/compiler"
|
||||
"github.com/mudler/luet/pkg/config"
|
||||
"github.com/mudler/luet/pkg/helpers"
|
||||
@@ -426,6 +427,14 @@ func (r *LuetSystemRepository) Write(dst string, resetRevision bool) error {
|
||||
r.Name, r.Revision, r.LastUpdate,
|
||||
))
|
||||
|
||||
bus.Manager.Publish(bus.EventRepositoryPreBuild, struct {
|
||||
Repo LuetSystemRepository
|
||||
Path string
|
||||
}{
|
||||
Repo: *r,
|
||||
Path: dst,
|
||||
})
|
||||
|
||||
// Create tree and repository file
|
||||
archive, err := config.LuetCfg.GetSystem().TempDir("archive")
|
||||
if err != nil {
|
||||
@@ -506,6 +515,14 @@ func (r *LuetSystemRepository) Write(dst string, resetRevision bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
bus.Manager.Publish(bus.EventRepositoryPostBuild, struct {
|
||||
Repo LuetSystemRepository
|
||||
Path string
|
||||
}{
|
||||
Repo: *r,
|
||||
Path: dst,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -694,9 +711,12 @@ func (r *LuetSystemRepository) Sync(force bool) (Repository, error) {
|
||||
repo.SetPriority(r.GetPriority())
|
||||
repo.SetName(r.GetName())
|
||||
InfoC(
|
||||
aurora.Bold(
|
||||
aurora.Yellow(":information_source: Repository "+repo.GetName()+" priority: ")).String() +
|
||||
aurora.Bold(aurora.Green(repo.GetPriority())).String() + " - type " +
|
||||
aurora.Yellow(":information_source:").String() +
|
||||
aurora.Magenta("Repository: ").String() +
|
||||
aurora.Green(aurora.Bold(repo.GetName()).String()).String() +
|
||||
aurora.Magenta(" Priority: ").String() +
|
||||
aurora.Bold(aurora.Green(repo.GetPriority())).String() +
|
||||
aurora.Magenta(" Type: ").String() +
|
||||
aurora.Bold(aurora.Green(repo.GetType())).String(),
|
||||
)
|
||||
return repo, nil
|
||||
@@ -809,13 +829,11 @@ PACKAGE:
|
||||
c, err := r.GetTree().GetDatabase().FindPackageCandidate(pack)
|
||||
// If FindPackageCandidate returns the same package, it means it couldn't find one.
|
||||
// Skip this repository and keep looking.
|
||||
if c.String() == pack.String() {
|
||||
if err != nil { //c.String() == pack.String() {
|
||||
continue REPOSITORY
|
||||
}
|
||||
if err == nil {
|
||||
matches = append(matches, c)
|
||||
continue PACKAGE
|
||||
}
|
||||
matches = append(matches, c)
|
||||
continue PACKAGE
|
||||
} else {
|
||||
// If it's not a selector, just append it
|
||||
matches = append(matches, pack)
|
||||
|
@@ -60,8 +60,8 @@ var _ = Describe("Repository", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2", "chmod +x generate.sh"}))
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "chmod +x generate.sh", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2"}))
|
||||
|
||||
spec.SetOutputPath(tmpdir)
|
||||
compiler.SetConcurrency(1)
|
||||
@@ -133,8 +133,8 @@ var _ = Describe("Repository", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2", "chmod +x generate.sh"}))
|
||||
Expect(spec.BuildSteps()).To(Equal([]string{"echo artifact5 > /test5", "echo artifact6 > /test6", "chmod +x generate.sh", "./generate.sh"}))
|
||||
Expect(spec.GetPreBuildSteps()).To(Equal([]string{"echo foo > /test", "echo bar > /test2"}))
|
||||
|
||||
spec.SetOutputPath(tmpdir)
|
||||
spec2.SetOutputPath(tmpdir)
|
||||
|
@@ -1,7 +1,11 @@
|
||||
package installer
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/mudler/luet/pkg/helpers"
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
"github.com/mudler/luet/pkg/tree"
|
||||
)
|
||||
|
||||
type System struct {
|
||||
@@ -12,3 +16,38 @@ type System struct {
|
||||
func (s *System) World() (pkg.Packages, error) {
|
||||
return s.Database.World(), nil
|
||||
}
|
||||
|
||||
type templatedata map[string]interface{}
|
||||
|
||||
func (s *System) ExecuteFinalizers(packs []pkg.Package) error {
|
||||
var errs error
|
||||
executedFinalizer := map[string]bool{}
|
||||
for _, p := range packs {
|
||||
if helpers.Exists(p.Rel(tree.FinalizerFile)) {
|
||||
out, err := helpers.RenderFiles(p.Rel(tree.FinalizerFile), p.Rel(tree.DefinitionFile), "")
|
||||
if err != nil {
|
||||
Warning("Failed rendering finalizer for ", p.HumanReadableString(), err.Error())
|
||||
errs = multierror.Append(errs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, exists := executedFinalizer[p.GetFingerPrint()]; !exists {
|
||||
Info("Executing finalizer for " + p.HumanReadableString())
|
||||
finalizer, err := NewLuetFinalizerFromYaml([]byte(out))
|
||||
if err != nil {
|
||||
Warning("Failed reading finalizer for ", p.HumanReadableString(), err.Error())
|
||||
errs = multierror.Append(errs, err)
|
||||
continue
|
||||
}
|
||||
err = finalizer.RunInstall(s)
|
||||
if err != nil {
|
||||
Warning("Failed running finalizer for ", p.HumanReadableString(), err.Error())
|
||||
errs = multierror.Append(errs, err)
|
||||
continue
|
||||
}
|
||||
executedFinalizer[p.GetFingerPrint()] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
. "github.com/mudler/luet/pkg/config"
|
||||
|
||||
@@ -36,6 +37,22 @@ func GetAurora() Aurora {
|
||||
return aurora
|
||||
}
|
||||
|
||||
func Ask() bool {
|
||||
var input string
|
||||
|
||||
Info("Do you want to continue with this operation? [y/N]: ")
|
||||
_, err := fmt.Scanln(&input)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
input = strings.ToLower(input)
|
||||
|
||||
if input == "y" || input == "yes" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ZapLogger() error {
|
||||
var err error
|
||||
if z == nil {
|
||||
@@ -183,9 +200,9 @@ func msg(level string, withoutColor bool, msg ...interface{}) {
|
||||
case "debug":
|
||||
levelMsg = White(message).BgBlack().String()
|
||||
case "info":
|
||||
levelMsg = Bold(White(message)).BgBlack().String()
|
||||
levelMsg = message
|
||||
case "error":
|
||||
levelMsg = Bold(Red(":bomb: " + message + ":fire:")).BgBlack().String()
|
||||
levelMsg = Red(message).String()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +248,6 @@ func Error(mess ...interface{}) {
|
||||
}
|
||||
|
||||
func Fatal(mess ...interface{}) {
|
||||
Error(mess)
|
||||
Error(mess...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
@@ -28,6 +28,10 @@ type PackageDatabase interface {
|
||||
}
|
||||
|
||||
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)
|
||||
|
@@ -47,6 +47,14 @@ func NewBoltDatabase(path string) PackageDatabase {
|
||||
return &BoltDatabase{Path: path, ProvidesDatabase: map[string]map[string]Package{}}
|
||||
}
|
||||
|
||||
func (db *BoltDatabase) Clone(to PackageDatabase) error {
|
||||
return clone(db, to)
|
||||
}
|
||||
|
||||
func (db *BoltDatabase) Copy() (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}))
|
||||
if err != nil {
|
||||
@@ -86,6 +94,17 @@ func (db *BoltDatabase) Retrieve(ID string) ([]byte, error) {
|
||||
return enc, nil
|
||||
}
|
||||
|
||||
// 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) {
|
||||
memory := NewInMemoryDatabase(false)
|
||||
for _, p := range db.World() {
|
||||
memory.CreatePackage(p)
|
||||
}
|
||||
return memory.GetRevdeps(p)
|
||||
}
|
||||
|
||||
func (db *BoltDatabase) FindPackage(tofind Package) (Package, error) {
|
||||
// Provides: Return the replaced package here
|
||||
if provided, err := db.getProvide(tofind); err == nil {
|
||||
@@ -330,17 +349,18 @@ func (db *BoltDatabase) FindPackageCandidate(p Package) (Package, error) {
|
||||
|
||||
required, err := db.FindPackage(p)
|
||||
if err != nil {
|
||||
|
||||
err = nil
|
||||
// return nil, errors.Wrap(err, "Couldn't find required package in db definition")
|
||||
packages, err := p.Expand(db)
|
||||
// Info("Expanded", packages, err)
|
||||
if err != nil || len(packages) == 0 {
|
||||
required = p
|
||||
err = errors.Wrap(err, "Candidate not found")
|
||||
} else {
|
||||
required = packages.Best(nil)
|
||||
|
||||
}
|
||||
return required, nil
|
||||
return required, err
|
||||
//required = &DefaultPackage{Name: "test"}
|
||||
}
|
||||
|
||||
@@ -351,10 +371,22 @@ 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) {
|
||||
if !p.IsSelector() {
|
||||
pack, err := db.FindPackage(p)
|
||||
if err != nil {
|
||||
return []Package{}, err
|
||||
}
|
||||
return []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
|
||||
}
|
||||
}
|
||||
|
||||
var versionsInWorld []Package
|
||||
for _, w := range db.World() {
|
||||
if w.GetName() != p.GetName() || w.GetCategory() != p.GetCategory() {
|
||||
|
@@ -81,7 +81,6 @@ var _ = Describe("BoltDB 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{})
|
||||
@@ -102,7 +101,6 @@ var _ = Describe("BoltDB 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{})
|
||||
@@ -123,7 +121,6 @@ var _ = Describe("BoltDB Database", func() {
|
||||
})
|
||||
|
||||
It("Provides 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{})
|
||||
@@ -147,6 +144,144 @@ var _ = Describe("BoltDB Database", func() {
|
||||
Expect(pack).To(Equal(a3))
|
||||
})
|
||||
|
||||
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{})
|
||||
|
||||
a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})
|
||||
Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}))
|
||||
|
||||
_, err := db.CreatePackage(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(a1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(a3)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
pack, err := db.FindPackage(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(pack).To(Equal(a3))
|
||||
})
|
||||
|
||||
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{})
|
||||
|
||||
a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})
|
||||
Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}))
|
||||
|
||||
_, err := db.CreatePackage(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(a1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(a3)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(a3))
|
||||
})
|
||||
|
||||
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{})
|
||||
|
||||
z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})
|
||||
Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}))
|
||||
|
||||
_, err := db.CreatePackage(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(a1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(z)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(z))
|
||||
})
|
||||
|
||||
It("replaces definitions of unexisting packages", func() {
|
||||
a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})
|
||||
Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}))
|
||||
|
||||
_, err := db.CreatePackage(a1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(z)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(z))
|
||||
})
|
||||
|
||||
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{})
|
||||
|
||||
z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})
|
||||
Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{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{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(z))
|
||||
})
|
||||
|
||||
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{})
|
||||
|
||||
z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})
|
||||
Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{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{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(z))
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
|
38
pkg/package/database_common.go
Normal file
38
pkg/package/database_common.go
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright © 2020 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package pkg
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
|
||||
func clone(src, dst PackageDatabase) error {
|
||||
for _, i := range src.World() {
|
||||
_, err := dst.CreatePackage(i)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed create package "+i.HumanReadableString())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copy(src PackageDatabase) (PackageDatabase, error) {
|
||||
dst := NewInMemoryDatabase(false)
|
||||
|
||||
if err := clone(src, dst); err != nil {
|
||||
return dst, errors.Wrap(err, "Failed create temporary in-memory db")
|
||||
}
|
||||
|
||||
return dst, nil
|
||||
}
|
@@ -31,6 +31,7 @@ var DBInMemoryInstance = &InMemoryDatabase{
|
||||
Database: map[string]string{},
|
||||
CacheNoVersion: map[string]map[string]interface{}{},
|
||||
ProvidesDatabase: map[string]map[string]Package{},
|
||||
RevDepsDatabase: map[string]map[string]Package{},
|
||||
}
|
||||
|
||||
type InMemoryDatabase struct {
|
||||
@@ -39,6 +40,7 @@ type InMemoryDatabase struct {
|
||||
FileDatabase map[string][]string
|
||||
CacheNoVersion map[string]map[string]interface{}
|
||||
ProvidesDatabase map[string]map[string]Package
|
||||
RevDepsDatabase map[string]map[string]Package
|
||||
}
|
||||
|
||||
func NewInMemoryDatabase(singleton bool) PackageDatabase {
|
||||
@@ -50,6 +52,7 @@ func NewInMemoryDatabase(singleton bool) PackageDatabase {
|
||||
Database: map[string]string{},
|
||||
CacheNoVersion: map[string]map[string]interface{}{},
|
||||
ProvidesDatabase: map[string]map[string]Package{},
|
||||
RevDepsDatabase: map[string]map[string]Package{},
|
||||
}
|
||||
}
|
||||
return DBInMemoryInstance
|
||||
@@ -125,6 +128,47 @@ 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
|
||||
if _, ok := visited[p.HumanReadableString()]; ok {
|
||||
return versionsInWorld, nil
|
||||
}
|
||||
visited[p.HumanReadableString()] = true
|
||||
|
||||
var res Packages
|
||||
packs, err := db.FindPackages(p)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
for _, pp := range packs {
|
||||
// db.Lock()
|
||||
list := db.RevDepsDatabase[pp.GetFingerPrint()]
|
||||
// db.Unlock()
|
||||
for _, revdep := range list {
|
||||
dep, err := db.FindPackage(revdep)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res = append(res, dep)
|
||||
|
||||
packs, err := db.getRevdeps(dep, visited)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res = append(res, packs...)
|
||||
|
||||
}
|
||||
}
|
||||
return res.Unique(), nil
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
@@ -143,9 +187,16 @@ func (db *InMemoryDatabase) CreatePackage(p Package) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
db.populateCaches(pd)
|
||||
|
||||
return ID, nil
|
||||
}
|
||||
|
||||
func (db *InMemoryDatabase) populateCaches(p Package) {
|
||||
pd, _ := p.(*DefaultPackage)
|
||||
|
||||
// Create extra cache between package -> []versions
|
||||
db.Lock()
|
||||
defer db.Unlock()
|
||||
|
||||
// Provides: Store package provides, we will reuse this when walking deps
|
||||
for _, provide := range pd.Provides {
|
||||
@@ -157,21 +208,41 @@ func (db *InMemoryDatabase) CreatePackage(p Package) (string, error) {
|
||||
db.ProvidesDatabase[provide.GetPackageName()][provide.GetVersion()] = p
|
||||
}
|
||||
|
||||
_, ok = db.CacheNoVersion[p.GetPackageName()]
|
||||
_, ok := db.CacheNoVersion[p.GetPackageName()]
|
||||
if !ok {
|
||||
db.CacheNoVersion[p.GetPackageName()] = make(map[string]interface{})
|
||||
}
|
||||
db.CacheNoVersion[p.GetPackageName()][p.GetVersion()] = nil
|
||||
db.Unlock()
|
||||
|
||||
return ID, nil
|
||||
for _, re := range pd.GetRequires() {
|
||||
packages, _ := db.FindPackages(re)
|
||||
db.Lock()
|
||||
|
||||
for _, pa := range packages {
|
||||
_, ok := db.RevDepsDatabase[pa.GetFingerPrint()]
|
||||
if !ok {
|
||||
db.RevDepsDatabase[pa.GetFingerPrint()] = make(map[string]Package)
|
||||
}
|
||||
db.RevDepsDatabase[pa.GetFingerPrint()][pd.GetFingerPrint()] = pd
|
||||
}
|
||||
_, ok := db.RevDepsDatabase[re.GetFingerPrint()]
|
||||
if !ok {
|
||||
db.RevDepsDatabase[re.GetFingerPrint()] = make(map[string]Package)
|
||||
}
|
||||
db.RevDepsDatabase[re.GetFingerPrint()][pd.GetFingerPrint()] = pd
|
||||
db.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (db *InMemoryDatabase) getProvide(p Package) (Package, error) {
|
||||
|
||||
db.Lock()
|
||||
|
||||
pa, ok := db.ProvidesDatabase[p.GetPackageName()][p.GetVersion()]
|
||||
if !ok {
|
||||
versions, ok := db.ProvidesDatabase[p.GetPackageName()]
|
||||
db.Unlock()
|
||||
defer db.Unlock()
|
||||
|
||||
if !ok {
|
||||
return nil, errors.New("No versions found for package")
|
||||
@@ -195,9 +266,18 @@ func (db *InMemoryDatabase) getProvide(p Package) (Package, error) {
|
||||
return nil, errors.New("No package provides this")
|
||||
}
|
||||
db.Unlock()
|
||||
|
||||
return db.FindPackage(pa)
|
||||
}
|
||||
|
||||
func (db *InMemoryDatabase) Clone(to PackageDatabase) error {
|
||||
return clone(db, to)
|
||||
}
|
||||
|
||||
func (db *InMemoryDatabase) Copy() (PackageDatabase, error) {
|
||||
return copy(db)
|
||||
}
|
||||
|
||||
func (db *InMemoryDatabase) encodePackage(p Package) (string, string, error) {
|
||||
pd, ok := p.(*DefaultPackage)
|
||||
if !ok {
|
||||
@@ -229,8 +309,9 @@ func (db *InMemoryDatabase) FindPackageVersions(p Package) (Packages, error) {
|
||||
if provided, err := db.getProvide(p); err == nil {
|
||||
p = provided
|
||||
}
|
||||
|
||||
db.Lock()
|
||||
versions, ok := db.CacheNoVersion[p.GetPackageName()]
|
||||
db.Unlock()
|
||||
if !ok {
|
||||
return nil, errors.New("No versions found for package")
|
||||
}
|
||||
@@ -247,29 +328,41 @@ func (db *InMemoryDatabase) FindPackageVersions(p Package) (Packages, error) {
|
||||
|
||||
// FindPackages return the list of the packages beloging to cat/name (any versions in requested range)
|
||||
func (db *InMemoryDatabase) FindPackages(p Package) (Packages, error) {
|
||||
|
||||
if !p.IsSelector() {
|
||||
pack, err := db.FindPackage(p)
|
||||
if err != nil {
|
||||
return []Package{}, err
|
||||
}
|
||||
return []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
|
||||
}
|
||||
}
|
||||
|
||||
db.Lock()
|
||||
var matches []*DefaultPackage
|
||||
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})
|
||||
}
|
||||
}
|
||||
db.Unlock()
|
||||
if !ok {
|
||||
return nil, errors.New(fmt.Sprintf("No versions found for: %s", p.HumanReadableString()))
|
||||
}
|
||||
var versionsInWorld []Package
|
||||
for ve, _ := range versions {
|
||||
match, err := p.SelectorMatchVersion(ve, nil)
|
||||
for _, p := range matches {
|
||||
w, err := db.FindPackage(p)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error on match selector")
|
||||
}
|
||||
|
||||
if match {
|
||||
w, err := db.FindPackage(&DefaultPackage{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 nil, errors.Wrap(err, "Cache mismatch - this shouldn't happen")
|
||||
}
|
||||
versionsInWorld = append(versionsInWorld, w)
|
||||
}
|
||||
return Packages(versionsInWorld), nil
|
||||
}
|
||||
@@ -349,16 +442,17 @@ func (db *InMemoryDatabase) FindPackageCandidate(p Package) (Package, error) {
|
||||
|
||||
required, err := db.FindPackage(p)
|
||||
if err != nil {
|
||||
err = nil
|
||||
// return nil, errors.Wrap(err, "Couldn't find required package in db definition")
|
||||
packages, err := p.Expand(db)
|
||||
// Info("Expanded", packages, err)
|
||||
if err != nil || len(packages) == 0 {
|
||||
required = p
|
||||
err = errors.Wrap(err, "Candidate not found")
|
||||
} else {
|
||||
required = packages.Best(nil)
|
||||
|
||||
}
|
||||
return required, nil
|
||||
return required, err
|
||||
//required = &DefaultPackage{Name: "test"}
|
||||
}
|
||||
|
||||
|
@@ -98,30 +98,150 @@ var _ = Describe("Database", func() {
|
||||
|
||||
})
|
||||
|
||||
It("Provides 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{})
|
||||
Context("Provides", func() {
|
||||
|
||||
a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})
|
||||
Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}))
|
||||
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{})
|
||||
|
||||
_, err := db.CreatePackage(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})
|
||||
Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}))
|
||||
|
||||
_, err = db.CreatePackage(a1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err := db.CreatePackage(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(a3)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = db.CreatePackage(a1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
_, err = db.CreatePackage(a3)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
pack, err := db.FindPackage(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(pack).To(Equal(a3))
|
||||
})
|
||||
|
||||
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{})
|
||||
|
||||
a3.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}})
|
||||
Expect(a3.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: "1.0"}}))
|
||||
|
||||
_, err := db.CreatePackage(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(a1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(a3)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(a3))
|
||||
})
|
||||
|
||||
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{})
|
||||
|
||||
z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})
|
||||
Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}))
|
||||
|
||||
_, err := db.CreatePackage(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(a1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(z)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(z))
|
||||
})
|
||||
|
||||
It("replaces definitions of unexisting packages", func() {
|
||||
db := NewInMemoryDatabase(false)
|
||||
a1 := NewPackage("A", "1.1", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
z := NewPackage("Z", "1.3", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})
|
||||
Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}}))
|
||||
|
||||
_, err := db.CreatePackage(a1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = db.CreatePackage(z)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := NewPackage("A", "1.0", []*DefaultPackage{}, []*DefaultPackage{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(z))
|
||||
})
|
||||
|
||||
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{})
|
||||
|
||||
z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})
|
||||
Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{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{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(z))
|
||||
})
|
||||
|
||||
When("Searching with selectors", 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{})
|
||||
|
||||
z.SetProvides([]*DefaultPackage{{Name: "A", Category: "", Version: ">=1.0"}})
|
||||
Expect(z.GetProvides()).To(Equal([]*DefaultPackage{{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{})
|
||||
|
||||
packs, err := db.FindPackages(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packs).To(ContainElement(z))
|
||||
})
|
||||
})
|
||||
|
||||
pack, err := db.FindPackage(s)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(pack).To(Equal(a3))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
|
@@ -49,7 +49,6 @@ type Package interface {
|
||||
Requires([]*DefaultPackage) Package
|
||||
Conflicts([]*DefaultPackage) Package
|
||||
Revdeps(PackageDatabase) Packages
|
||||
ExpandedRevdeps(definitiondb PackageDatabase, visited map[string]interface{}) Packages
|
||||
LabelDeps(PackageDatabase, string) Packages
|
||||
|
||||
GetProvides() []*DefaultPackage
|
||||
@@ -147,6 +146,60 @@ func DefaultPackageFromYaml(yml []byte) (DefaultPackage, error) {
|
||||
return unescaped, nil
|
||||
}
|
||||
|
||||
type rawPackages []map[string]interface{}
|
||||
|
||||
func (r rawPackages) Find(name, category, version string) map[string]interface{} {
|
||||
for _, v := range r {
|
||||
if v["name"] == name && v["category"] == category && v["version"] == version {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
func GetRawPackages(yml []byte) (rawPackages, error) {
|
||||
var rawPackages struct {
|
||||
Packages []map[string]interface{} `yaml:"packages"`
|
||||
}
|
||||
source, err := yaml.YAMLToJSON(yml)
|
||||
if err != nil {
|
||||
return []map[string]interface{}{}, err
|
||||
}
|
||||
|
||||
rawIn := json.RawMessage(source)
|
||||
bytes, err := rawIn.MarshalJSON()
|
||||
if err != nil {
|
||||
return []map[string]interface{}{}, err
|
||||
}
|
||||
err = json.Unmarshal(bytes, &rawPackages)
|
||||
if err != nil {
|
||||
return []map[string]interface{}{}, err
|
||||
}
|
||||
return rawPackages.Packages, nil
|
||||
|
||||
}
|
||||
func DefaultPackagesFromYaml(yml []byte) ([]DefaultPackage, error) {
|
||||
|
||||
var unescaped struct {
|
||||
Packages []DefaultPackage `json:"packages"`
|
||||
}
|
||||
source, err := yaml.YAMLToJSON(yml)
|
||||
if err != nil {
|
||||
return []DefaultPackage{}, err
|
||||
}
|
||||
|
||||
rawIn := json.RawMessage(source)
|
||||
bytes, err := rawIn.MarshalJSON()
|
||||
if err != nil {
|
||||
return []DefaultPackage{}, err
|
||||
}
|
||||
err = json.Unmarshal(bytes, &unescaped)
|
||||
if err != nil {
|
||||
return []DefaultPackage{}, 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) {
|
||||
buffer := &bytes.Buffer{}
|
||||
@@ -459,8 +512,7 @@ func walkPackage(p Package, definitiondb PackageDatabase, visited map[string]int
|
||||
}
|
||||
visited[p.HumanReadableString()] = true
|
||||
|
||||
revdepvisited := make(map[string]interface{})
|
||||
revdeps := p.ExpandedRevdeps(definitiondb, revdepvisited)
|
||||
revdeps, _ := definitiondb.GetRevdeps(p)
|
||||
for _, r := range revdeps {
|
||||
versionsInWorld = append(versionsInWorld, r)
|
||||
}
|
||||
@@ -494,52 +546,6 @@ func (p *DefaultPackage) Related(definitiondb PackageDatabase) Packages {
|
||||
return walkPackage(p, definitiondb, map[string]interface{}{})
|
||||
}
|
||||
|
||||
// ExpandedRevdeps returns the package reverse dependencies,
|
||||
// matching also selectors in versions (>, <, >=, <=)
|
||||
func (p *DefaultPackage) ExpandedRevdeps(definitiondb PackageDatabase, visited map[string]interface{}) Packages {
|
||||
var versionsInWorld Packages
|
||||
if _, ok := visited[p.HumanReadableString()]; ok {
|
||||
return versionsInWorld
|
||||
}
|
||||
visited[p.HumanReadableString()] = true
|
||||
|
||||
for _, w := range definitiondb.World() {
|
||||
if w.Matches(p) {
|
||||
continue
|
||||
}
|
||||
match := false
|
||||
|
||||
for _, re := range w.GetRequires() {
|
||||
if re.Matches(p) {
|
||||
match = true
|
||||
}
|
||||
if !match {
|
||||
|
||||
packages, _ := re.Expand(definitiondb)
|
||||
for _, pa := range packages {
|
||||
if pa.Matches(p) {
|
||||
match = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if ok, _ := w.RequiresContains(definitiondb, p); ok {
|
||||
|
||||
}
|
||||
|
||||
if match {
|
||||
versionsInWorld = append(versionsInWorld, w)
|
||||
|
||||
versionsInWorld = append(versionsInWorld, w.ExpandedRevdeps(definitiondb, visited).Unique()...)
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
}
|
||||
//visited[p.HumanReadableString()] = true
|
||||
return versionsInWorld.Unique()
|
||||
}
|
||||
|
||||
func (p *DefaultPackage) LabelDeps(definitiondb PackageDatabase, labelKey string) Packages {
|
||||
var pkgsWithLabelInWorld Packages
|
||||
// TODO: check if integrate some index to improve
|
||||
|
@@ -220,8 +220,8 @@ var _ = Describe("Package", func() {
|
||||
_, err := definitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
visited := make(map[string]interface{})
|
||||
lst := a.ExpandedRevdeps(definitions, visited)
|
||||
lst, err := definitions.GetRevdeps(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lst).To(ContainElement(c))
|
||||
Expect(lst).To(ContainElement(d))
|
||||
Expect(lst).To(ContainElement(e))
|
||||
@@ -242,9 +242,9 @@ var _ = Describe("Package", func() {
|
||||
_, err := definitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
visited := make(map[string]interface{})
|
||||
|
||||
lst := a.ExpandedRevdeps(definitions, visited)
|
||||
lst, err := definitions.GetRevdeps(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lst).To(ContainElement(b))
|
||||
Expect(lst).To(ContainElement(c))
|
||||
Expect(lst).To(ContainElement(d))
|
||||
@@ -266,9 +266,8 @@ var _ = Describe("Package", func() {
|
||||
_, err := definitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
visited := make(map[string]interface{})
|
||||
|
||||
lst := a.ExpandedRevdeps(definitions, visited)
|
||||
lst, err := definitions.GetRevdeps(a)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lst).To(ContainElement(b))
|
||||
Expect(lst).To(ContainElement(c))
|
||||
Expect(lst).To(ContainElement(d))
|
||||
|
@@ -76,7 +76,7 @@ func (s *Parallel) noRulesInstalled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Parallel) buildParallelFormula(formulas []bf.Formula, packages pkg.Packages) (bf.Formula, error) {
|
||||
func (s *Parallel) buildParallelFormula(db pkg.PackageDatabase, formulas []bf.Formula, packages pkg.Packages) (bf.Formula, error) {
|
||||
var wg = new(sync.WaitGroup)
|
||||
var wg2 = new(sync.WaitGroup)
|
||||
|
||||
@@ -87,7 +87,7 @@ func (s *Parallel) buildParallelFormula(formulas []bf.Formula, packages pkg.Pack
|
||||
go func(wg *sync.WaitGroup, c <-chan pkg.Package) {
|
||||
defer wg.Done()
|
||||
for p := range c {
|
||||
solvable, err := p.BuildFormula(s.DefinitionDatabase, s.ParallelDatabase)
|
||||
solvable, err := p.BuildFormula(db, s.ParallelDatabase)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -126,13 +126,13 @@ func (s *Parallel) BuildInstalled() (bf.Formula, error) {
|
||||
var packages pkg.Packages
|
||||
for _, p := range s.Installed() {
|
||||
packages = append(packages, p)
|
||||
for _, dep := range p.Related(s.DefinitionDatabase) {
|
||||
for _, dep := range p.Related(s.InstalledDatabase) {
|
||||
packages = append(packages, dep)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return s.buildParallelFormula(formulas, packages)
|
||||
return s.buildParallelFormula(s.InstalledDatabase, formulas, packages)
|
||||
}
|
||||
|
||||
// BuildWorld builds the formula which olds the requirements from the package definitions
|
||||
@@ -148,7 +148,7 @@ func (s *Parallel) BuildWorld(includeInstalled bool) (bf.Formula, error) {
|
||||
//f = bf.And(f, solvable)
|
||||
formulas = append(formulas, solvable)
|
||||
}
|
||||
return s.buildParallelFormula(formulas, s.World())
|
||||
return s.buildParallelFormula(s.DefinitionDatabase, formulas, s.World())
|
||||
}
|
||||
|
||||
// BuildWorld builds the formula which olds the requirements from the package definitions
|
||||
@@ -200,7 +200,7 @@ func (s *Parallel) BuildPartialWorld(includeInstalled bool) (bf.Formula, error)
|
||||
close(results)
|
||||
wg2.Wait()
|
||||
|
||||
return s.buildParallelFormula(formulas, packages)
|
||||
return s.buildParallelFormula(s.DefinitionDatabase, formulas, packages)
|
||||
|
||||
//return s.buildParallelFormula(formulas, s.World())
|
||||
}
|
||||
@@ -273,9 +273,11 @@ func (s *Parallel) Conflicts(pack pkg.Package, lsp pkg.Packages) (bool, error) {
|
||||
for _, p := range ls {
|
||||
temporarySet.CreatePackage(p)
|
||||
}
|
||||
visited := make(map[string]interface{})
|
||||
revdeps := p.ExpandedRevdeps(temporarySet, visited)
|
||||
|
||||
revdeps, err := temporarySet.GetRevdeps(p)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "error scanning revdeps")
|
||||
}
|
||||
var revdepsErr error
|
||||
for _, r := range revdeps {
|
||||
if revdepsErr == nil {
|
||||
@@ -444,10 +446,9 @@ func (s *Parallel) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAsse
|
||||
removed := pkg.Packages{}
|
||||
|
||||
// TODO: this is memory expensive, we need to optimize this
|
||||
universe := pkg.NewInMemoryDatabase(false)
|
||||
|
||||
for _, p := range s.DefinitionDatabase.World() {
|
||||
universe.CreatePackage(p)
|
||||
universe, err := s.DefinitionDatabase.Copy()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "couldn't build world copy")
|
||||
}
|
||||
for _, p := range s.Installed() {
|
||||
universe.CreatePackage(p)
|
||||
@@ -469,23 +470,22 @@ func (s *Parallel) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAsse
|
||||
go func(wg *sync.WaitGroup, c <-chan pkg.Package) {
|
||||
defer wg.Done()
|
||||
for p := range c {
|
||||
available, err := universe.FindPackageVersions(p)
|
||||
if err != nil {
|
||||
removed = append(removed, p) /// FIXME: Racy
|
||||
}
|
||||
if len(available) == 0 {
|
||||
available, err := s.DefinitionDatabase.FindPackageVersions(p)
|
||||
if len(available) == 0 || err != nil {
|
||||
removed = append(removed, p)
|
||||
continue
|
||||
}
|
||||
|
||||
bestmatch := available.Best(nil)
|
||||
// Found a better version available
|
||||
if !bestmatch.Matches(p) {
|
||||
encodedP, _ := p.Encode(universe)
|
||||
P := bf.Var(encodedP)
|
||||
results <- bf.And(bf.Not(P), r)
|
||||
encodedP, _ = bestmatch.Encode(universe)
|
||||
P = bf.Var(encodedP)
|
||||
results <- bf.And(P, r)
|
||||
oldP, _ := p.Encode(universe)
|
||||
toreplaceP := bf.Var(oldP)
|
||||
best, _ := bestmatch.Encode(universe)
|
||||
toUpgrade := bf.Var(best)
|
||||
|
||||
solvablenew, _ := bestmatch.BuildFormula(s.DefinitionDatabase, s.ParallelDatabase)
|
||||
results <- bf.And(bf.Not(toreplaceP), bf.And(append(solvablenew, toUpgrade)...))
|
||||
}
|
||||
}
|
||||
}(wg, all)
|
||||
@@ -512,8 +512,7 @@ func (s *Parallel) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAsse
|
||||
// Treat removed packages from universe as marked for deletion
|
||||
if dropremoved {
|
||||
|
||||
// SAT encode the clauses against the world
|
||||
for _, p := range removed {
|
||||
for _, p := range removed.Unique() {
|
||||
encodedP, err := p.Encode(universe)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "couldn't encode package")
|
||||
@@ -558,9 +557,9 @@ func (s *Parallel) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAss
|
||||
toInstall := pkg.Packages{}
|
||||
|
||||
// we do this in memory so we take into account of provides
|
||||
universe := pkg.NewInMemoryDatabase(false)
|
||||
for _, p := range s.DefinitionDatabase.World() {
|
||||
universe.CreatePackage(p)
|
||||
universe, err := s.DefinitionDatabase.Copy()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Could not copy def db")
|
||||
}
|
||||
|
||||
installedcopy := pkg.NewInMemoryDatabase(false)
|
||||
@@ -615,23 +614,22 @@ func (s *Parallel) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAss
|
||||
}
|
||||
|
||||
// Then try to uninstall the versions in the system, and store that tree
|
||||
for _, p := range toUninstall {
|
||||
r, err := s.Uninstall(p, checkconflicts, false)
|
||||
r, err := s.Uninstall(checkconflicts, false, toUninstall...)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't uninstall candidates ")
|
||||
}
|
||||
for _, z := range r {
|
||||
err = installedcopy.RemovePackage(z)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't uninstall selected candidate "+p.GetFingerPrint())
|
||||
}
|
||||
for _, z := range r {
|
||||
err = installedcopy.RemovePackage(z)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't remove copy of package targetted for removal")
|
||||
}
|
||||
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't remove copy of package targetted for removal")
|
||||
}
|
||||
}
|
||||
|
||||
if len(toInstall) == 0 {
|
||||
return toUninstall, PackagesAssertions{}, nil
|
||||
}
|
||||
r, e := s2.Install(toInstall)
|
||||
return toUninstall, r, e
|
||||
assertions, e := s2.Install(toInstall)
|
||||
return toUninstall, assertions, e
|
||||
// To that tree, ask to install the versions that should be upgraded, and try to solve
|
||||
// Return the solution
|
||||
|
||||
@@ -639,21 +637,30 @@ func (s *Parallel) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAss
|
||||
|
||||
// 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 *Parallel) Uninstall(c pkg.Package, checkconflicts, full bool) (pkg.Packages, error) {
|
||||
func (s *Parallel) Uninstall(checkconflicts, full bool, packs ...pkg.Package) (pkg.Packages, error) {
|
||||
if len(packs) == 0 {
|
||||
return pkg.Packages{}, nil
|
||||
}
|
||||
var res pkg.Packages
|
||||
candidate, err := s.InstalledDatabase.FindPackage(c)
|
||||
if err != nil {
|
||||
toRemove := pkg.Packages{}
|
||||
|
||||
// return nil, errors.Wrap(err, "Couldn't find required package in db definition")
|
||||
packages, err := c.Expand(s.InstalledDatabase)
|
||||
// Info("Expanded", packages, err)
|
||||
if err != nil || len(packages) == 0 {
|
||||
candidate = c
|
||||
} else {
|
||||
candidate = packages.Best(nil)
|
||||
for _, c := range packs {
|
||||
candidate, err := s.InstalledDatabase.FindPackage(c)
|
||||
if err != nil {
|
||||
|
||||
// return nil, errors.Wrap(err, "Couldn't find required package in db definition")
|
||||
packages, err := c.Expand(s.InstalledDatabase)
|
||||
// Info("Expanded", packages, err)
|
||||
if err != nil || len(packages) == 0 {
|
||||
candidate = c
|
||||
} else {
|
||||
candidate = packages.Best(nil)
|
||||
}
|
||||
//Relax search, otherwise we cannot compute solutions for packages not in definitions
|
||||
// return nil, errors.Wrap(err, "Package not found between installed")
|
||||
}
|
||||
//Relax search, otherwise we cannot compute solutions for packages not in definitions
|
||||
// return nil, errors.Wrap(err, "Package not found between installed")
|
||||
|
||||
toRemove = append(toRemove, candidate)
|
||||
}
|
||||
// Build a fake "Installed" - Candidate and its requires tree
|
||||
var InstalledMinusCandidate pkg.Packages
|
||||
@@ -661,30 +668,38 @@ func (s *Parallel) Uninstall(c pkg.Package, checkconflicts, full bool) (pkg.Pack
|
||||
// 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
|
||||
if !full && checkconflicts {
|
||||
if conflicts, err := s.Conflicts(candidate, s.Installed()); conflicts {
|
||||
return nil, err
|
||||
} else {
|
||||
return pkg.Packages{candidate}, nil
|
||||
for _, candidate := range toRemove {
|
||||
if conflicts, err := s.Conflicts(candidate, s.Installed()); conflicts {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return toRemove, nil
|
||||
}
|
||||
|
||||
// TODO: Can be optimized
|
||||
for _, i := range s.Installed() {
|
||||
if !i.Matches(candidate) {
|
||||
contains, err := candidate.RequiresContains(s.ParallelDatabase, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed getting installed list")
|
||||
}
|
||||
if !contains {
|
||||
InstalledMinusCandidate = append(InstalledMinusCandidate, i)
|
||||
matched := false
|
||||
for _, candidate := range toRemove {
|
||||
if !i.Matches(candidate) {
|
||||
contains, err := candidate.RequiresContains(s.ParallelDatabase, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed getting installed list")
|
||||
}
|
||||
if !contains {
|
||||
matched = true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if matched {
|
||||
InstalledMinusCandidate = append(InstalledMinusCandidate, i)
|
||||
}
|
||||
}
|
||||
|
||||
s2 := &Parallel{Concurrency: s.Concurrency, InstalledDatabase: pkg.NewInMemoryDatabase(false), DefinitionDatabase: s.DefinitionDatabase, ParallelDatabase: pkg.NewInMemoryDatabase(false)}
|
||||
s2 := &Parallel{Concurrency: s.Concurrency, InstalledDatabase: pkg.NewInMemoryDatabase(false), DefinitionDatabase: s.InstalledDatabase, ParallelDatabase: pkg.NewInMemoryDatabase(false)}
|
||||
s2.SetResolver(s.Resolver)
|
||||
// Get the requirements to install the candidate
|
||||
asserts, err := s2.Install(pkg.Packages{candidate})
|
||||
asserts, err := s2.Install(toRemove)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -401,7 +401,7 @@ var _ = Describe("Parallel", func() {
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: D, Value: false}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(4))
|
||||
Expect(len(solution)).To(Equal(3))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -529,7 +529,7 @@ var _ = Describe("Parallel", func() {
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
Expect(len(solution)).To(Equal(5))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -570,7 +570,7 @@ var _ = Describe("Parallel", func() {
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
Expect(len(solution)).To(Equal(5))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -593,7 +593,7 @@ var _ = Describe("Parallel", func() {
|
||||
}
|
||||
s = &Parallel{InstalledDatabase: dbInstalled, Concurrency: 4, DefinitionDatabase: dbDefinitions, ParallelDatabase: db}
|
||||
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -619,7 +619,7 @@ var _ = Describe("Parallel", func() {
|
||||
}
|
||||
s = &Parallel{InstalledDatabase: dbInstalled, Concurrency: 4, DefinitionDatabase: dbDefinitions, ParallelDatabase: db}
|
||||
|
||||
solution, err := s.Uninstall(&pkg.DefaultPackage{Name: "A", Version: ">1.0"}, true, true)
|
||||
solution, err := s.Uninstall(true, true, &pkg.DefaultPackage{Name: "A", Version: ">1.0"})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -643,7 +643,7 @@ var _ = Describe("Parallel", func() {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -667,12 +667,13 @@ var _ = Describe("Parallel", func() {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
Expect(solution).To(ContainElement(B))
|
||||
|
||||
Expect(len(solution)).To(Equal(1))
|
||||
Expect(len(solution)).To(Equal(2))
|
||||
})
|
||||
|
||||
It("Uninstalls complex packages correctly, even if shared deps are required by system packages", func() {
|
||||
@@ -690,7 +691,7 @@ var _ = Describe("Parallel", func() {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -699,6 +700,31 @@ var _ = Describe("Parallel", func() {
|
||||
Expect(len(solution)).To(Equal(1))
|
||||
})
|
||||
|
||||
It("Uninstalls multiple 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{})
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(true, true, A, C)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(solution).To(ContainElement(C))
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
Expect(solution).ToNot(ContainElement(B))
|
||||
|
||||
Expect(len(solution)).To(Equal(2))
|
||||
})
|
||||
|
||||
It("Uninstalls complex packages in world correctly", func() {
|
||||
C := pkg.NewPackage("C", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
D := pkg.NewPackage("D", "", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -715,7 +741,7 @@ var _ = Describe("Parallel", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -741,7 +767,7 @@ var _ = Describe("Parallel", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -1070,7 +1096,7 @@ var _ = Describe("Parallel", func() {
|
||||
}
|
||||
|
||||
val, err := s.Conflicts(D, dbInstalled.World())
|
||||
Expect(err.Error()).To(Equal("\n/A-\n/B-"))
|
||||
Expect(err.Error()).To(Or(Equal("\n/A-\n/B-"), Equal("\n/B-\n/A-")))
|
||||
Expect(val).To(BeTrue())
|
||||
})
|
||||
|
||||
@@ -1260,12 +1286,172 @@ var _ = Describe("Parallel", 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(PackageAssert{Package: A, Value: false}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(4))
|
||||
Expect(len(solution)).To(Equal(3))
|
||||
})
|
||||
|
||||
It("UpgradeUniverse upgrades correctly", func() {
|
||||
|
||||
D := pkg.NewPackage("d", "1.5", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
D.SetCategory("test")
|
||||
C = pkg.NewPackage("c", "1.5", []*pkg.DefaultPackage{
|
||||
&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"},
|
||||
&pkg.DefaultPackage{Name: "d", Version: ">=1.0", Category: "test"},
|
||||
}, []*pkg.DefaultPackage{})
|
||||
C.SetCategory("test")
|
||||
C1 := pkg.NewPackage("c", "1.6", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
C1.SetCategory("test")
|
||||
B = pkg.NewPackage("b", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B.SetCategory("test")
|
||||
|
||||
B1 := pkg.NewPackage("b", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "c", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
B1.SetCategory("test")
|
||||
A = pkg.NewPackage("a", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
A.SetCategory("test")
|
||||
A1 = pkg.NewPackage("a", "1.2", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
A1.SetCategory("test")
|
||||
|
||||
for _, p := range []pkg.Package{A1, B, B1, C, C1, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
uninstall, solution, err := s.UpgradeUniverse(false)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(len(uninstall)).To(Equal(2))
|
||||
Expect(uninstall).To(ContainElement(A))
|
||||
Expect(uninstall).To(ContainElement(B))
|
||||
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A1, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B1, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C1, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
})
|
||||
|
||||
It("UpgradeUniverse upgrades correctly", func() {
|
||||
|
||||
D := pkg.NewPackage("d", "1.5", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
D.SetCategory("test")
|
||||
D1 := pkg.NewPackage("d", "1.6", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
D1.SetCategory("test")
|
||||
C = pkg.NewPackage("c", "1.5", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
C.SetCategory("test")
|
||||
B = pkg.NewPackage("b", "1.0", []*pkg.DefaultPackage{
|
||||
&pkg.DefaultPackage{Name: "c", Version: ">=1.0", Category: "test"},
|
||||
}, []*pkg.DefaultPackage{})
|
||||
B.SetCategory("test")
|
||||
|
||||
A = pkg.NewPackage("a", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
A.SetCategory("test")
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D, D1} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
uninstall, solution, err := s.UpgradeUniverse(false)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(len(uninstall)).To(Equal(1))
|
||||
Expect(uninstall[0].GetName()).To(Equal("d"))
|
||||
Expect(uninstall[0].GetVersion()).To(Equal("1.5"))
|
||||
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(3))
|
||||
})
|
||||
|
||||
It("Upgrade upgrades correctly", func() {
|
||||
|
||||
D := pkg.NewPackage("d", "1.5", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
D.SetCategory("test")
|
||||
C = pkg.NewPackage("c", "1.5", []*pkg.DefaultPackage{
|
||||
&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"},
|
||||
&pkg.DefaultPackage{Name: "d", Version: ">=1.0", Category: "test"},
|
||||
}, []*pkg.DefaultPackage{})
|
||||
C.SetCategory("test")
|
||||
C1 := pkg.NewPackage("c", "1.6", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
C1.SetCategory("test")
|
||||
B = pkg.NewPackage("b", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
B.SetCategory("test")
|
||||
|
||||
B1 := pkg.NewPackage("b", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "c", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
B1.SetCategory("test")
|
||||
A = pkg.NewPackage("a", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
A.SetCategory("test")
|
||||
A1 = pkg.NewPackage("a", "1.2", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
A1.SetCategory("test")
|
||||
|
||||
for _, p := range []pkg.Package{A1, B, B1, C, C1, D} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
uninstall, solution, err := s.Upgrade(false, false)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(len(uninstall)).To(Equal(2))
|
||||
Expect(uninstall).To(ContainElement(A))
|
||||
Expect(uninstall).To(ContainElement(B))
|
||||
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: A1, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: B1, Value: true}))
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: C1, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
})
|
||||
|
||||
It("Upgrade upgrades correctly", func() {
|
||||
|
||||
D := pkg.NewPackage("d", "1.5", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
D.SetCategory("test")
|
||||
D1 := pkg.NewPackage("d", "1.6", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
D1.SetCategory("test")
|
||||
C = pkg.NewPackage("c", "1.5", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
C.SetCategory("test")
|
||||
B = pkg.NewPackage("b", "1.0", []*pkg.DefaultPackage{
|
||||
&pkg.DefaultPackage{Name: "c", Version: ">=1.0", Category: "test"},
|
||||
}, []*pkg.DefaultPackage{})
|
||||
B.SetCategory("test")
|
||||
|
||||
A = pkg.NewPackage("a", "1.1", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "b", Version: "1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
A.SetCategory("test")
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D, D1} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, D} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
uninstall, solution, err := s.Upgrade(false, false)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(len(uninstall)).To(Equal(1))
|
||||
Expect(uninstall[0].GetName()).To(Equal("d"))
|
||||
Expect(uninstall[0].GetVersion()).To(Equal("1.5"))
|
||||
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(5))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -37,7 +37,7 @@ const (
|
||||
type PackageSolver interface {
|
||||
SetDefinitionDatabase(pkg.PackageDatabase)
|
||||
Install(p pkg.Packages) (PackagesAssertions, error)
|
||||
Uninstall(candidate pkg.Package, checkconflicts, full bool) (pkg.Packages, 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)
|
||||
@@ -134,13 +134,13 @@ func (s *Solver) BuildInstalled() (bf.Formula, error) {
|
||||
var packages pkg.Packages
|
||||
for _, p := range s.Installed() {
|
||||
packages = append(packages, p)
|
||||
for _, dep := range p.Related(s.DefinitionDatabase) {
|
||||
for _, dep := range p.Related(s.InstalledDatabase) {
|
||||
packages = append(packages, dep)
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range packages {
|
||||
solvable, err := p.BuildFormula(s.DefinitionDatabase, s.SolverDatabase)
|
||||
solvable, err := p.BuildFormula(s.InstalledDatabase, s.SolverDatabase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -211,8 +211,8 @@ func (s *Solver) BuildPartialWorld(includeInstalled bool) (bf.Formula, error) {
|
||||
if len(formulas) != 0 {
|
||||
return bf.And(formulas...), nil
|
||||
}
|
||||
return bf.True, nil
|
||||
|
||||
return bf.True, nil
|
||||
}
|
||||
|
||||
func (s *Solver) getList(db pkg.PackageDatabase, lsp pkg.Packages) (pkg.Packages, error) {
|
||||
@@ -255,8 +255,11 @@ func (s *Solver) Conflicts(pack pkg.Package, lsp pkg.Packages) (bool, error) {
|
||||
for _, p := range ls {
|
||||
temporarySet.CreatePackage(p)
|
||||
}
|
||||
visited := make(map[string]interface{})
|
||||
revdeps := p.ExpandedRevdeps(temporarySet, visited)
|
||||
|
||||
revdeps, err := temporarySet.GetRevdeps(p)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "error scanning revdeps")
|
||||
}
|
||||
|
||||
var revdepsErr error
|
||||
for _, r := range revdeps {
|
||||
@@ -396,23 +399,23 @@ func (s *Solver) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAssert
|
||||
notUptodate := pkg.Packages{}
|
||||
removed := pkg.Packages{}
|
||||
toUpgrade := pkg.Packages{}
|
||||
replacements := map[pkg.Package]pkg.Package{}
|
||||
|
||||
// TODO: this is memory expensive, we need to optimize this
|
||||
universe := pkg.NewInMemoryDatabase(false)
|
||||
for _, p := range s.DefinitionDatabase.World() {
|
||||
universe.CreatePackage(p)
|
||||
universe, err := s.DefinitionDatabase.Copy()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Failed copying db")
|
||||
}
|
||||
|
||||
for _, p := range s.Installed() {
|
||||
universe.CreatePackage(p)
|
||||
}
|
||||
|
||||
// Grab all the installed ones, see if they are eligible for update
|
||||
for _, p := range s.Installed() {
|
||||
available, err := universe.FindPackageVersions(p)
|
||||
if err != nil {
|
||||
available, err := s.DefinitionDatabase.FindPackageVersions(p)
|
||||
if len(available) == 0 || err != nil {
|
||||
removed = append(removed, p)
|
||||
}
|
||||
if len(available) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -421,6 +424,7 @@ func (s *Solver) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAssert
|
||||
if !bestmatch.Matches(p) {
|
||||
notUptodate = append(notUptodate, p)
|
||||
toUpgrade = append(toUpgrade, bestmatch)
|
||||
replacements[p] = bestmatch
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,28 +438,37 @@ func (s *Solver) UpgradeUniverse(dropremoved bool) (pkg.Packages, PackagesAssert
|
||||
|
||||
// Treat removed packages from universe as marked for deletion
|
||||
if dropremoved {
|
||||
notUptodate = append(notUptodate, removed...)
|
||||
// SAT encode the clauses against the world
|
||||
for _, p := range removed.Unique() {
|
||||
encodedP, err := p.Encode(universe)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "couldn't encode package")
|
||||
}
|
||||
P := bf.Var(encodedP)
|
||||
formulas = append(formulas, bf.And(bf.Not(P), r))
|
||||
}
|
||||
}
|
||||
|
||||
// SAT encode the clauses against the world
|
||||
for _, p := range notUptodate.Unique() {
|
||||
encodedP, err := p.Encode(universe)
|
||||
for old, new := range replacements {
|
||||
oldP, err := old.Encode(universe)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "couldn't encode package")
|
||||
}
|
||||
P := bf.Var(encodedP)
|
||||
formulas = append(formulas, bf.And(bf.Not(P), r))
|
||||
}
|
||||
|
||||
for _, p := range toUpgrade {
|
||||
encodedP, err := p.Encode(universe)
|
||||
oldencodedP := bf.Var(oldP)
|
||||
newP, err := new.Encode(universe)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "couldn't encode package")
|
||||
}
|
||||
P := bf.Var(encodedP)
|
||||
formulas = append(formulas, bf.And(P, r))
|
||||
newEncodedP := bf.Var(newP)
|
||||
|
||||
//solvable, err := old.BuildFormula(s.DefinitionDatabase, s.SolverDatabase)
|
||||
solvablenew, err := new.BuildFormula(s.DefinitionDatabase, s.SolverDatabase)
|
||||
|
||||
formulas = append(formulas, bf.And(bf.Not(oldencodedP), bf.And(append(solvablenew, newEncodedP)...)))
|
||||
}
|
||||
|
||||
//formulas = append(formulas, r)
|
||||
|
||||
markedForRemoval := pkg.Packages{}
|
||||
|
||||
if len(formulas) == 0 {
|
||||
@@ -489,10 +502,10 @@ func (s *Solver) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAsser
|
||||
toUninstall := pkg.Packages{}
|
||||
toInstall := pkg.Packages{}
|
||||
|
||||
// we do this in memory so we take into account of provides
|
||||
universe := pkg.NewInMemoryDatabase(false)
|
||||
for _, p := range s.DefinitionDatabase.World() {
|
||||
universe.CreatePackage(p)
|
||||
// we do this in memory so we take into account of provides, and its faster
|
||||
universe, err := s.DefinitionDatabase.Copy()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed creating db copy")
|
||||
}
|
||||
|
||||
installedcopy := pkg.NewInMemoryDatabase(false)
|
||||
@@ -518,23 +531,24 @@ func (s *Solver) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAsser
|
||||
}
|
||||
}
|
||||
// Then try to uninstall the versions in the system, and store that tree
|
||||
for _, p := range toUninstall {
|
||||
r, err := s.Uninstall(p, checkconflicts, false)
|
||||
r, err := s.Uninstall(checkconflicts, false, toUninstall.Unique()...)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't uninstall candidates ")
|
||||
}
|
||||
for _, z := range r {
|
||||
err = installedcopy.RemovePackage(z)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't uninstall selected candidate "+p.GetFingerPrint())
|
||||
}
|
||||
for _, z := range r {
|
||||
err = installedcopy.RemovePackage(z)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't remove copy of package targetted for removal")
|
||||
}
|
||||
return nil, nil, errors.Wrap(err, "Could not compute upgrade - couldn't remove copy of package targetted for removal")
|
||||
}
|
||||
}
|
||||
|
||||
if len(toInstall) == 0 {
|
||||
return toUninstall, PackagesAssertions{}, nil
|
||||
}
|
||||
r, e := s2.Install(toInstall)
|
||||
return toUninstall, r, e
|
||||
|
||||
assertions, err := s2.Install(toInstall.Unique())
|
||||
|
||||
return toUninstall, assertions, err
|
||||
// To that tree, ask to install the versions that should be upgraded, and try to solve
|
||||
// Return the solution
|
||||
|
||||
@@ -542,52 +556,72 @@ func (s *Solver) Upgrade(checkconflicts, full bool) (pkg.Packages, PackagesAsser
|
||||
|
||||
// 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(c pkg.Package, checkconflicts, full bool) (pkg.Packages, error) {
|
||||
var res pkg.Packages
|
||||
candidate, err := s.InstalledDatabase.FindPackage(c)
|
||||
if err != nil {
|
||||
|
||||
// return nil, errors.Wrap(err, "Couldn't find required package in db definition")
|
||||
packages, err := c.Expand(s.InstalledDatabase)
|
||||
// Info("Expanded", packages, err)
|
||||
if err != nil || len(packages) == 0 {
|
||||
candidate = c
|
||||
} else {
|
||||
candidate = packages.Best(nil)
|
||||
}
|
||||
//Relax search, otherwise we cannot compute solutions for packages not in definitions
|
||||
// return nil, errors.Wrap(err, "Package not found between installed")
|
||||
func (s *Solver) Uninstall(checkconflicts, full bool, packs ...pkg.Package) (pkg.Packages, error) {
|
||||
if len(packs) == 0 {
|
||||
return pkg.Packages{}, nil
|
||||
}
|
||||
var res pkg.Packages
|
||||
|
||||
toRemove := pkg.Packages{}
|
||||
|
||||
for _, c := range packs {
|
||||
candidate, err := s.InstalledDatabase.FindPackage(c)
|
||||
if err != nil {
|
||||
|
||||
// return nil, errors.Wrap(err, "Couldn't find required package in db definition")
|
||||
packages, err := c.Expand(s.InstalledDatabase)
|
||||
// Info("Expanded", packages, err)
|
||||
if err != nil || len(packages) == 0 {
|
||||
candidate = c
|
||||
} else {
|
||||
candidate = packages.Best(nil)
|
||||
}
|
||||
//Relax search, otherwise we cannot compute solutions for packages not in definitions
|
||||
// return nil, errors.Wrap(err, "Package not found between installed")
|
||||
}
|
||||
|
||||
toRemove = append(toRemove, candidate)
|
||||
}
|
||||
|
||||
// Build a fake "Installed" - Candidate and its requires tree
|
||||
var InstalledMinusCandidate pkg.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
|
||||
if !full && checkconflicts {
|
||||
if conflicts, err := s.Conflicts(candidate, s.Installed()); conflicts {
|
||||
return nil, err
|
||||
} else {
|
||||
return pkg.Packages{candidate}, nil
|
||||
for _, candidate := range toRemove {
|
||||
if conflicts, err := s.Conflicts(candidate, s.Installed()); conflicts {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return toRemove, nil
|
||||
}
|
||||
|
||||
// TODO: Can be optimized
|
||||
for _, i := range s.Installed() {
|
||||
if !i.Matches(candidate) {
|
||||
contains, err := candidate.RequiresContains(s.SolverDatabase, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed getting installed list")
|
||||
}
|
||||
if !contains {
|
||||
InstalledMinusCandidate = append(InstalledMinusCandidate, i)
|
||||
matched := false
|
||||
for _, candidate := range toRemove {
|
||||
if !i.Matches(candidate) {
|
||||
contains, err := candidate.RequiresContains(s.SolverDatabase, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed getting installed list")
|
||||
}
|
||||
if !contains {
|
||||
matched = true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if matched {
|
||||
InstalledMinusCandidate = append(InstalledMinusCandidate, i)
|
||||
}
|
||||
}
|
||||
|
||||
s2 := NewSolver(Options{Type: SingleCoreSimple}, pkg.NewInMemoryDatabase(false), s.DefinitionDatabase, pkg.NewInMemoryDatabase(false))
|
||||
s2 := NewSolver(Options{Type: SingleCoreSimple}, pkg.NewInMemoryDatabase(false), s.InstalledDatabase, pkg.NewInMemoryDatabase(false))
|
||||
s2.SetResolver(s.Resolver)
|
||||
|
||||
// Get the requirements to install the candidate
|
||||
asserts, err := s2.Install(pkg.Packages{candidate})
|
||||
asserts, err := s2.Install(toRemove)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -634,6 +668,7 @@ func (s *Solver) BuildFormula() (bf.Formula, error) {
|
||||
}
|
||||
|
||||
for _, wanted := range s.Wanted {
|
||||
|
||||
encodedW, err := wanted.Encode(s.SolverDatabase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -401,7 +401,7 @@ var _ = Describe("Solver", func() {
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: D, Value: false}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(4))
|
||||
Expect(len(solution)).To(Equal(3))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -529,7 +529,7 @@ var _ = Describe("Solver", func() {
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
Expect(len(solution)).To(Equal(5))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -570,7 +570,7 @@ var _ = Describe("Solver", func() {
|
||||
Expect(solution).To(ContainElement(PackageAssert{Package: D1, Value: false}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: E, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(6))
|
||||
Expect(len(solution)).To(Equal(5))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
@@ -593,7 +593,7 @@ var _ = Describe("Solver", func() {
|
||||
}
|
||||
s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -619,7 +619,7 @@ var _ = Describe("Solver", func() {
|
||||
}
|
||||
s = NewSolver(Options{Type: SingleCoreSimple}, dbInstalled, dbDefinitions, db)
|
||||
|
||||
solution, err := s.Uninstall(&pkg.DefaultPackage{Name: "A", Version: ">1.0"}, true, true)
|
||||
solution, err := s.Uninstall(true, true, &pkg.DefaultPackage{Name: "A", Version: ">1.0"})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -643,7 +643,7 @@ var _ = Describe("Solver", func() {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -667,12 +667,13 @@ var _ = Describe("Solver", func() {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
Expect(solution).To(ContainElement(B))
|
||||
|
||||
Expect(len(solution)).To(Equal(1))
|
||||
Expect(len(solution)).To(Equal(2))
|
||||
})
|
||||
|
||||
It("Uninstalls complex packages correctly, even if shared deps are required by system packages", func() {
|
||||
@@ -690,7 +691,7 @@ var _ = Describe("Solver", func() {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -715,7 +716,7 @@ var _ = Describe("Solver", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -741,7 +742,7 @@ var _ = Describe("Solver", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
solution, err := s.Uninstall(A, true, true)
|
||||
solution, err := s.Uninstall(true, true, A)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(solution).To(ContainElement(A))
|
||||
@@ -1070,7 +1071,7 @@ var _ = Describe("Solver", func() {
|
||||
}
|
||||
|
||||
val, err := s.Conflicts(D, dbInstalled.World())
|
||||
Expect(err.Error()).To(Equal("\n/A-\n/B-"))
|
||||
Expect(err.Error()).To(Or(Equal("\n/A-\n/B-"), Equal("\n/B-\n/A-")))
|
||||
Expect(val).To(BeTrue())
|
||||
})
|
||||
|
||||
@@ -1209,6 +1210,8 @@ var _ = Describe("Solver", func() {
|
||||
})
|
||||
})
|
||||
Context("Upgrades", func() {
|
||||
E := pkg.NewPackage("e", "1.5", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
E.SetCategory("test")
|
||||
C := pkg.NewPackage("c", "1.5", []*pkg.DefaultPackage{&pkg.DefaultPackage{Name: "a", Version: ">=1.0", Category: "test"}}, []*pkg.DefaultPackage{})
|
||||
C.SetCategory("test")
|
||||
B := pkg.NewPackage("b", "1.0", []*pkg.DefaultPackage{}, []*pkg.DefaultPackage{})
|
||||
@@ -1296,10 +1299,37 @@ var _ = Describe("Solver", func() {
|
||||
|
||||
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(PackageAssert{Package: A, Value: false}))
|
||||
|
||||
Expect(len(solution)).To(Equal(4))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: C, Value: true}))
|
||||
Expect(solution).ToNot(ContainElement(PackageAssert{Package: A, Value: true}))
|
||||
|
||||
Expect(len(solution)).To(Equal(3))
|
||||
})
|
||||
|
||||
It("Suggests to remove untracked packages", func() {
|
||||
for _, p := range []pkg.Package{E} {
|
||||
_, err := dbDefinitions.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
for _, p := range []pkg.Package{A, B, C, E} {
|
||||
_, err := dbInstalled.CreatePackage(p)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
uninstall, solution, err := s.UpgradeUniverse(true)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(uninstall)).To(Equal(3))
|
||||
|
||||
Expect(uninstall).To(ContainElement(B))
|
||||
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(len(solution)).To(Equal(3))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -44,6 +44,14 @@ type DefaultPackageSanitized struct {
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
func NewDefaultPackageSanitizedFromYaml(data []byte) (*DefaultPackageSanitized, error) {
|
||||
ans := &DefaultPackageSanitized{}
|
||||
if err := yaml.Unmarshal(data, ans); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ans, nil
|
||||
}
|
||||
|
||||
func NewDefaultPackageSanitized(p pkg.Package) *DefaultPackageSanitized {
|
||||
ans := &DefaultPackageSanitized{
|
||||
Name: p.GetName(),
|
||||
@@ -110,3 +118,12 @@ func NewDefaultPackageSanitized(p pkg.Package) *DefaultPackageSanitized {
|
||||
func (p *DefaultPackageSanitized) Yaml() ([]byte, error) {
|
||||
return yaml.Marshal(p)
|
||||
}
|
||||
|
||||
func (p *DefaultPackageSanitized) Clone() (*DefaultPackageSanitized, error) {
|
||||
data, err := p.Yaml()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewDefaultPackageSanitizedFromYaml(data)
|
||||
}
|
||||
|
@@ -1,142 +0,0 @@
|
||||
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package gentoo
|
||||
|
||||
// NOTE: Look here as an example of the builder definition executor
|
||||
// https://gist.github.com/adnaan/6ca68c7985c6f851def3
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
tree "github.com/mudler/luet/pkg/tree"
|
||||
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
)
|
||||
|
||||
type MemoryDB int
|
||||
|
||||
const (
|
||||
InMemory MemoryDB = iota
|
||||
BoltDB MemoryDB = iota
|
||||
)
|
||||
|
||||
func NewGentooBuilder(e EbuildParser, concurrency int, db MemoryDB) tree.Parser {
|
||||
return &GentooBuilder{EbuildParser: e, Concurrency: concurrency}
|
||||
}
|
||||
|
||||
type GentooBuilder struct {
|
||||
EbuildParser EbuildParser
|
||||
Concurrency int
|
||||
DBType MemoryDB
|
||||
}
|
||||
|
||||
type EbuildParser interface {
|
||||
ScanEbuild(string) (pkg.Packages, error)
|
||||
}
|
||||
|
||||
func (gb *GentooBuilder) scanEbuild(path string, db pkg.PackageDatabase) error {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
Error(r)
|
||||
}
|
||||
}()
|
||||
pkgs, err := gb.EbuildParser.ScanEbuild(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, p := range pkgs {
|
||||
_, err := db.FindPackage(p)
|
||||
if err != nil {
|
||||
_, err := db.CreatePackage(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gb *GentooBuilder) worker(i int, wg *sync.WaitGroup, s <-chan string, db pkg.PackageDatabase) {
|
||||
defer wg.Done()
|
||||
|
||||
for path := range s {
|
||||
Info("#"+strconv.Itoa(i), "parsing", path)
|
||||
err := gb.scanEbuild(path, db)
|
||||
if err != nil {
|
||||
Error(path, ":", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (gb *GentooBuilder) Generate(dir string) (pkg.PackageDatabase, error) {
|
||||
|
||||
var toScan = make(chan string)
|
||||
Spinner(27)
|
||||
defer SpinnerStop()
|
||||
var db pkg.PackageDatabase
|
||||
// Support for
|
||||
switch gb.DBType {
|
||||
case InMemory:
|
||||
db = pkg.NewInMemoryDatabase(false)
|
||||
case BoltDB:
|
||||
tmpfile, err := ioutil.TempFile("", "boltdb")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db = pkg.NewBoltDatabase(tmpfile.Name())
|
||||
default:
|
||||
db = pkg.NewInMemoryDatabase(false)
|
||||
}
|
||||
|
||||
Debug("Concurrency", gb.Concurrency)
|
||||
// the waitgroup will allow us to wait for all the goroutines to finish at the end
|
||||
var wg = new(sync.WaitGroup)
|
||||
for i := 0; i < gb.Concurrency; i++ {
|
||||
wg.Add(1)
|
||||
go gb.worker(i, wg, toScan, db)
|
||||
}
|
||||
|
||||
// TODO: Handle cleaning after? Cleanup implemented in GetPackageSet().Clean()
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
// Ensure that only file with suffix .ebuild are elaborated.
|
||||
// and ignore .swp files or files with string ebuild on name
|
||||
if strings.HasSuffix(info.Name(), ".ebuild") {
|
||||
toScan <- path
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
close(toScan)
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return db, err
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
@@ -1,177 +0,0 @@
|
||||
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package gentoo_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
. "github.com/mudler/luet/pkg/tree/builder/gentoo"
|
||||
)
|
||||
|
||||
type FakeParser struct {
|
||||
}
|
||||
|
||||
func (f *FakeParser) ScanEbuild(path string) (pkg.Packages, error) {
|
||||
return pkg.Packages{&pkg.DefaultPackage{Name: path}}, nil
|
||||
}
|
||||
|
||||
var _ = Describe("GentooBuilder", func() {
|
||||
|
||||
Context("Simple test", func() {
|
||||
for _, dbType := range []MemoryDB{InMemory, BoltDB} {
|
||||
It("parses correctly deps", func() {
|
||||
gb := NewGentooBuilder(&FakeParser{}, 20, dbType)
|
||||
tree, err := gb.Generate("../../../../tests/fixtures/overlay")
|
||||
defer func() {
|
||||
Expect(tree.Clean()).ToNot(HaveOccurred())
|
||||
}()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(tree.GetPackages())).To(Equal(10))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Context("Parse ebuild1", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/overlay/app-crypt/pinentry-gnome/pinentry-gnome-1.0.0-r2.ebuild")
|
||||
It("parses correctly deps", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(pkgs[0].GetLicense()).To(Equal("GPL-2"))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("GNOME 3 frontend for pinentry"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse ebuild2", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/parser/mod_dav_svn-1.12.2.ebuild")
|
||||
|
||||
It("Parsing ebuild2", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(pkgs[0].GetLicense()).To(Equal("Subversion"))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("Subversion WebDAV support"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse ebuild3", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/parser/linux-sources-1.ebuild")
|
||||
|
||||
It("Check parsing of the ebuild3", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(len(pkgs[0].GetRequires())).To(Equal(0))
|
||||
Expect(pkgs[0].GetLicense()).To(Equal(""))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("Virtual for Linux kernel sources"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse ebuild4", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/parser/sabayon-mce-1.1-r5.ebuild")
|
||||
|
||||
It("Check parsing of the ebuild4", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(len(pkgs[0].GetRequires())).To(Equal(2))
|
||||
Expect(pkgs[0].GetLicense()).To(Equal("GPL-2"))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("Sabayon Linux Media Center Infrastructure"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse ebuild5", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/parser/libreoffice-l10n-meta-6.2.8.2.ebuild")
|
||||
|
||||
It("Check parsing of the ebuild5", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(len(pkgs[0].GetRequires())).To(Equal(146))
|
||||
Expect(pkgs[0].GetLicense()).To(Equal("LGPL-2"))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("LibreOffice.org localisation meta-package"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse ebuild6", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/parser/pkgs-checker-0.2.0.ebuild")
|
||||
|
||||
It("Check parsing of the ebuild6", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(len(pkgs[0].GetRequires())).To(Equal(0))
|
||||
Expect(pkgs[0].GetLicense()).To(Equal("GPL-3"))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("Sabayon Packages Checker"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse ebuild7", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/parser/calamares-sabayon-base-modules-1.15.ebuild")
|
||||
|
||||
It("Check parsing of the ebuild7", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(len(pkgs[0].GetRequires())).To(Equal(2))
|
||||
Expect(pkgs[0].GetLicense()).To(Equal("CC-BY-SA-4.0"))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("Sabayon Official Calamares base modules"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse ebuild8", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/parser/subversion-1.12.0.ebuild")
|
||||
|
||||
It("Check parsing of the ebuild8", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(len(pkgs[0].GetRequires())).To(Equal(25))
|
||||
Expect(pkgs[0].GetLicense()).To(Equal("Subversion GPL-2"))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("Advanced version control system"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse ebuild9", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/parser/kodi-raspberrypi-16.0.ebuild")
|
||||
|
||||
PIt("Check parsing of the ebuild9", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(len(pkgs[0].GetRequires())).To(Equal(66))
|
||||
Expect(pkgs[0].GetLicense()).To(Equal("GPL-2"))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("Kodi is a free and open source media-player and entertainment hub"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse ebuild10", func() {
|
||||
parser := &SimpleEbuildParser{}
|
||||
pkgs, err := parser.ScanEbuild("../../../../tests/fixtures/parser/tango-icon-theme-0.8.90-r1.ebuild")
|
||||
|
||||
It("Check parsing of the ebuild10", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
fmt.Println("PKG ", pkgs[0])
|
||||
Expect(len(pkgs[0].GetRequires())).To(Equal(2))
|
||||
Expect(pkgs[0].GetLicense()).To(Equal("public-domain"))
|
||||
Expect(pkgs[0].GetDescription()).To(Equal("SVG and PNG icon theme from the Tango project"))
|
||||
})
|
||||
})
|
||||
|
||||
})
|
@@ -1,447 +0,0 @@
|
||||
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package gentoo
|
||||
|
||||
// NOTE: Look here as an example of the builder definition executor
|
||||
// https://gist.github.com/adnaan/6ca68c7985c6f851def3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/mudler/luet/pkg/logger"
|
||||
|
||||
_gentoo "github.com/Sabayon/pkgs-checker/pkg/gentoo"
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
"mvdan.cc/sh/v3/expand"
|
||||
"mvdan.cc/sh/v3/shell"
|
||||
"mvdan.cc/sh/v3/syntax"
|
||||
)
|
||||
|
||||
const (
|
||||
uriRegex = "(.*[.]tar[.].*|.*[.]zip|.*[.]run|.*[.]png|.*[.]rpm|.*[.]gz)"
|
||||
)
|
||||
|
||||
// SimpleEbuildParser ignores USE flags and generates just 1-1 package
|
||||
type SimpleEbuildParser struct {
|
||||
World pkg.PackageDatabase
|
||||
}
|
||||
|
||||
type GentooDependency struct {
|
||||
Use string
|
||||
UseCondition _gentoo.PackageCond
|
||||
SubDeps []*GentooDependency
|
||||
Dep *_gentoo.GentooPackage
|
||||
}
|
||||
|
||||
type GentooRDEPEND struct {
|
||||
Dependencies []*GentooDependency
|
||||
}
|
||||
|
||||
func NewGentooDependency(pkg, use string) (*GentooDependency, error) {
|
||||
var err error
|
||||
ans := &GentooDependency{
|
||||
Use: use,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
}
|
||||
|
||||
if strings.HasPrefix(use, "!") {
|
||||
ans.Use = ans.Use[1:]
|
||||
ans.UseCondition = _gentoo.PkgCondNot
|
||||
}
|
||||
|
||||
if pkg != "" {
|
||||
ans.Dep, err = _gentoo.ParsePackageStr(pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: Fix this on parsing phase for handle correctly ${PV}
|
||||
if strings.HasSuffix(ans.Dep.Name, "-") {
|
||||
ans.Dep.Name = ans.Dep.Name[:len(ans.Dep.Name)-1]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ans, nil
|
||||
}
|
||||
|
||||
func (d *GentooDependency) String() string {
|
||||
if d.Dep != nil {
|
||||
return fmt.Sprintf("%s", d.Dep)
|
||||
} else {
|
||||
return fmt.Sprintf("%s %d %s", d.Use, d.UseCondition, d.SubDeps)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *GentooDependency) GetDepsList() []*GentooDependency {
|
||||
ans := make([]*GentooDependency, 0)
|
||||
|
||||
if len(d.SubDeps) > 0 {
|
||||
for _, d2 := range d.SubDeps {
|
||||
list := d2.GetDepsList()
|
||||
ans = append(ans, list...)
|
||||
}
|
||||
}
|
||||
|
||||
if d.Dep != nil {
|
||||
ans = append(ans, d)
|
||||
}
|
||||
|
||||
return ans
|
||||
}
|
||||
|
||||
func (d *GentooDependency) AddSubDependency(pkg, use string) (*GentooDependency, error) {
|
||||
ans, err := NewGentooDependency(pkg, use)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.SubDeps = append(d.SubDeps, ans)
|
||||
|
||||
return ans, nil
|
||||
}
|
||||
|
||||
func (r *GentooRDEPEND) GetDependencies() []*GentooDependency {
|
||||
ans := make([]*GentooDependency, 0)
|
||||
|
||||
for _, d := range r.Dependencies {
|
||||
list := d.GetDepsList()
|
||||
ans = append(ans, list...)
|
||||
}
|
||||
|
||||
// the same dependency could be available in multiple use flags.
|
||||
// It's needed avoid duplicate.
|
||||
m := make(map[string]*GentooDependency, 0)
|
||||
|
||||
for _, p := range ans {
|
||||
m[p.String()] = p
|
||||
}
|
||||
|
||||
ans = make([]*GentooDependency, 0)
|
||||
for _, p := range m {
|
||||
ans = append(ans, p)
|
||||
}
|
||||
|
||||
return ans
|
||||
}
|
||||
|
||||
func ParseRDEPEND(rdepend string) (*GentooRDEPEND, error) {
|
||||
var lastdep []*GentooDependency = make([]*GentooDependency, 0)
|
||||
var pendingDep = false
|
||||
var orDep = false
|
||||
var dep *GentooDependency
|
||||
var err error
|
||||
|
||||
ans := &GentooRDEPEND{
|
||||
Dependencies: make([]*GentooDependency, 0),
|
||||
}
|
||||
|
||||
if rdepend != "" {
|
||||
rdepends := strings.Split(rdepend, "\n")
|
||||
for _, rr := range rdepends {
|
||||
rr = strings.TrimSpace(rr)
|
||||
if rr == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(rr, "|| (") {
|
||||
orDep = true
|
||||
continue
|
||||
}
|
||||
|
||||
if orDep {
|
||||
rr = strings.TrimSpace(rr)
|
||||
if rr == ")" {
|
||||
orDep = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Index(rr, "?") > 0 {
|
||||
// use flag present
|
||||
|
||||
if pendingDep {
|
||||
dep, err = lastdep[len(lastdep)-1].AddSubDependency("", rr[:strings.Index(rr, "?")])
|
||||
if err != nil {
|
||||
Debug("Ignoring subdependency ", rr[:strings.Index(rr, "?")])
|
||||
}
|
||||
} else {
|
||||
dep, err = NewGentooDependency("", rr[:strings.Index(rr, "?")])
|
||||
if err != nil {
|
||||
Debug("Ignoring dep", rr)
|
||||
} else {
|
||||
ans.Dependencies = append(ans.Dependencies, dep)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Index(rr, ")") < 0 {
|
||||
pendingDep = true
|
||||
lastdep = append(lastdep, dep)
|
||||
}
|
||||
|
||||
if strings.Index(rr, "|| (") >= 0 {
|
||||
// Ignore dep in or
|
||||
continue
|
||||
}
|
||||
|
||||
fields := strings.Split(rr[strings.Index(rr, "?")+1:], " ")
|
||||
for _, f := range fields {
|
||||
f = strings.TrimSpace(f)
|
||||
if f == ")" || f == "(" || f == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = dep.AddSubDependency(f, "")
|
||||
if err != nil {
|
||||
Debug("Ignoring subdependency ", f)
|
||||
}
|
||||
}
|
||||
|
||||
} else if pendingDep {
|
||||
fields := strings.Split(rr, " ")
|
||||
for _, f := range fields {
|
||||
f = strings.TrimSpace(f)
|
||||
if f == ")" || f == "(" || f == "" {
|
||||
continue
|
||||
}
|
||||
_, err = lastdep[len(lastdep)-1].AddSubDependency(f, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Index(rr, ")") >= 0 {
|
||||
lastdep = lastdep[:len(lastdep)-1]
|
||||
if len(lastdep) == 0 {
|
||||
pendingDep = false
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
rr = strings.TrimSpace(rr)
|
||||
// Check if there multiple deps in single row
|
||||
|
||||
fields := strings.Split(rr, " ")
|
||||
if len(fields) > 1 {
|
||||
for _, rrr := range fields {
|
||||
rrr = strings.TrimSpace(rrr)
|
||||
if rrr == "" {
|
||||
continue
|
||||
}
|
||||
dep, err := NewGentooDependency(rrr, "")
|
||||
if err != nil {
|
||||
Debug("Ignoring dep", rr)
|
||||
} else {
|
||||
ans.Dependencies = append(ans.Dependencies, dep)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dep, err := NewGentooDependency(rr, "")
|
||||
if err != nil {
|
||||
Debug("Ignoring dep", rr)
|
||||
} else {
|
||||
ans.Dependencies = append(ans.Dependencies, dep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ans, nil
|
||||
}
|
||||
|
||||
func SourceFile(ctx context.Context, path string, pkg *_gentoo.GentooPackage) (map[string]expand.Variable, error) {
|
||||
content, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not open: %v", err)
|
||||
}
|
||||
scontent := string(content)
|
||||
|
||||
// Add default Genoo Variables
|
||||
ebuild := fmt.Sprintf("P=%s\n", pkg.GetP()) +
|
||||
fmt.Sprintf("PN=%s\n", pkg.GetPN()) +
|
||||
fmt.Sprintf("PV=%s\n", pkg.GetPV()) +
|
||||
fmt.Sprintf("PVR=%s\n", pkg.GetPVR())
|
||||
|
||||
// Disable inherit
|
||||
scontent = strings.ReplaceAll(scontent, "inherit", "#inherit")
|
||||
// Disable function from eclass (TODO: check how fix better this)
|
||||
scontent = strings.ReplaceAll(scontent, "need_apache", "#need_apache")
|
||||
scontent = strings.ReplaceAll(scontent, "want_apache", "#want_apache")
|
||||
|
||||
regexFuncs := regexp.MustCompile(
|
||||
"[a-zA-Z]+.*[_][a-z]+[(][)][\\s]{",
|
||||
)
|
||||
matches := regexFuncs.FindAllIndex([]byte(scontent), -1)
|
||||
// Drop section after functions (src_*, *() {)
|
||||
if len(matches) > 0 {
|
||||
ebuild = ebuild + scontent[:matches[0][0]]
|
||||
} else {
|
||||
ebuild = ebuild + scontent
|
||||
}
|
||||
|
||||
// [[ ${PV} == "9999" ]] is not supported. Workaround but we need a better solution.
|
||||
regexDoubleBrakets := regexp.MustCompile(
|
||||
//"[[][[].*",
|
||||
"^[[][[].*",
|
||||
//"^.*\[\[.*\]\]",
|
||||
)
|
||||
matchDB := regexDoubleBrakets.FindAllIndex([]byte(ebuild), -1)
|
||||
if len(matchDB) > 0 {
|
||||
ebuild = ebuild[:matchDB[0][0]] + "#" + ebuild[matchDB[0][0]:]
|
||||
}
|
||||
|
||||
//fmt.Println("EBUILD ", ebuild)
|
||||
|
||||
file, err := syntax.NewParser().Parse(strings.NewReader(ebuild), path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse: %v", err)
|
||||
}
|
||||
return shell.SourceNode(ctx, file)
|
||||
}
|
||||
|
||||
// ScanEbuild returns a list of packages (always one with SimpleEbuildParser) decoded from an ebuild.
|
||||
func (ep *SimpleEbuildParser) ScanEbuild(path string) (pkg.Packages, error) {
|
||||
Debug("Starting parsing of ebuild", path)
|
||||
|
||||
pkgstr := filepath.Base(path)
|
||||
paths := strings.Split(filepath.Dir(path), "/")
|
||||
pkgstr = paths[len(paths)-2] + "/" + strings.Replace(pkgstr, ".ebuild", "", -1)
|
||||
|
||||
gp, err := _gentoo.ParsePackageStr(pkgstr)
|
||||
if err != nil {
|
||||
return pkg.Packages{}, errors.New("Error on parsing package string")
|
||||
}
|
||||
|
||||
pack := &pkg.DefaultPackage{
|
||||
Name: gp.Name,
|
||||
Version: fmt.Sprintf("%s%s", gp.Version, gp.VersionSuffix),
|
||||
Category: gp.Category,
|
||||
Uri: make([]string, 0),
|
||||
}
|
||||
|
||||
Debug("Prepare package ", pack.Category+"/"+pack.Name+"-"+pack.Version)
|
||||
|
||||
// Adding a timeout of 60secs, as with some bash files it can hang indefinetly
|
||||
timeout, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer cancel()
|
||||
vars, err := SourceFile(timeout, path, gp)
|
||||
if err != nil {
|
||||
Error("Error on source file ", pack.Name, ": ", err)
|
||||
return pkg.Packages{}, err
|
||||
}
|
||||
|
||||
// Retrieve slot
|
||||
slot, ok := vars["SLOT"]
|
||||
if ok && slot.String() != "0" {
|
||||
pack.SetCategory(fmt.Sprintf("%s-%s", gp.Category, slot.String()))
|
||||
}
|
||||
|
||||
// TODO: Handle this a bit better
|
||||
iuse, ok := vars["IUSE"]
|
||||
if ok {
|
||||
uses := strings.Split(strings.TrimSpace(iuse.String()), " ")
|
||||
for _, u := range uses {
|
||||
pack.AddUse(u)
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve package description
|
||||
descr, ok := vars["DESCRIPTION"]
|
||||
if ok {
|
||||
pack.SetDescription(descr.String())
|
||||
}
|
||||
// Retrieve package license
|
||||
license, ok := vars["LICENSE"]
|
||||
if ok {
|
||||
pack.SetLicense(license.String())
|
||||
}
|
||||
uri, ok := vars["SRC_URI"]
|
||||
if ok {
|
||||
// TODO: handle mirror:
|
||||
uris := strings.Split(uri.String(), "\n")
|
||||
for _, u := range uris {
|
||||
u = strings.TrimSpace(u)
|
||||
|
||||
if u == "" {
|
||||
continue
|
||||
}
|
||||
if match, _ := regexp.Match(uriRegex, []byte(u)); match {
|
||||
if strings.Index(u, "(") >= 0 {
|
||||
regexUri := regexp.MustCompile("(http|ftp|mirror).*[ ]")
|
||||
matches := regexUri.FindAllIndex([]byte(u), -1)
|
||||
if len(matches) > 0 {
|
||||
u = u[matches[0][0]:matches[0][1]]
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
pack.AddURI(u)
|
||||
Debug("Add uri ", u)
|
||||
} else {
|
||||
Debug("Skip uri ", u)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rdepend, ok := vars["RDEPEND"]
|
||||
if ok {
|
||||
gRDEPEND, err := ParseRDEPEND(rdepend.String())
|
||||
if err != nil {
|
||||
Warning("Error on parsing RDEPEND for package ", pack.Category+"/"+pack.Name, err)
|
||||
return pkg.Packages{pack}, nil
|
||||
// return pkg.Packages{}, err
|
||||
}
|
||||
|
||||
pack.PackageConflicts = []*pkg.DefaultPackage{}
|
||||
pack.PackageRequires = []*pkg.DefaultPackage{}
|
||||
|
||||
// TODO: See how handle use flags enabled.
|
||||
// and if it's correct get list of deps directly.
|
||||
for _, d := range gRDEPEND.GetDependencies() {
|
||||
|
||||
//TODO: Resolve to db or create a new one.
|
||||
//TODO: handle SLOT too.
|
||||
dep := &pkg.DefaultPackage{
|
||||
Name: d.Dep.Name,
|
||||
Version: d.Dep.Version + d.Dep.VersionSuffix,
|
||||
Category: d.Dep.Category,
|
||||
}
|
||||
Debug(fmt.Sprintf("For package %s found dep: %s/%s %s",
|
||||
gp, dep.Category, dep.Name, dep.Version))
|
||||
if d.Dep.Condition == _gentoo.PkgCondNot {
|
||||
pack.PackageConflicts = append(pack.PackageConflicts, dep)
|
||||
} else {
|
||||
pack.PackageRequires = append(pack.PackageRequires, dep)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Debug("Finished processing ebuild", path, "deps ", len(pack.PackageRequires))
|
||||
|
||||
//TODO: Deps and conflicts
|
||||
return pkg.Packages{pack}, nil
|
||||
}
|
@@ -1,669 +0,0 @@
|
||||
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package gentoo_test
|
||||
|
||||
import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
_gentoo "github.com/Sabayon/pkgs-checker/pkg/gentoo"
|
||||
. "github.com/mudler/luet/pkg/tree/builder/gentoo"
|
||||
)
|
||||
|
||||
var _ = Describe("GentooBuilder", func() {
|
||||
|
||||
Context("Parse RDEPEND1", func() {
|
||||
|
||||
rdepend := `
|
||||
app-crypt/sbsigntools
|
||||
x11-themes/sabayon-artwork-grub
|
||||
sys-boot/os-prober
|
||||
app-arch/xz-utils
|
||||
>=sys-libs/ncurses-5.2-r5:0=
|
||||
`
|
||||
gr, err := ParseRDEPEND(rdepend)
|
||||
It("Check error", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
It("Check gr", func() {
|
||||
Expect(gr).ShouldNot(BeNil())
|
||||
})
|
||||
|
||||
It("Check deps #", func() {
|
||||
Expect(len(gr.Dependencies)).Should(Equal(5))
|
||||
})
|
||||
|
||||
It("Check dep1", func() {
|
||||
Expect(*gr.Dependencies[0]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sbsigntools",
|
||||
Category: "app-crypt",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep2", func() {
|
||||
Expect(*gr.Dependencies[1]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sabayon-artwork-grub",
|
||||
Category: "x11-themes",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep5", func() {
|
||||
Expect(*gr.Dependencies[4]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "ncurses",
|
||||
Category: "sys-libs",
|
||||
Slot: "0=",
|
||||
Version: "5.2",
|
||||
VersionSuffix: "-r5",
|
||||
Condition: _gentoo.PkgCondGreaterEqual,
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Context("Parse RDEPEND2", func() {
|
||||
|
||||
rdepend := `
|
||||
app-crypt/sbsigntools
|
||||
x11-themes/sabayon-artwork-grub
|
||||
sys-boot/os-prober
|
||||
app-arch/xz-utils
|
||||
>=sys-libs/ncurses-5.2-r5:0=
|
||||
mount? ( sys-fs/fuse )
|
||||
`
|
||||
gr, err := ParseRDEPEND(rdepend)
|
||||
It("Check error", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
It("Check gr", func() {
|
||||
Expect(gr).ShouldNot(BeNil())
|
||||
})
|
||||
|
||||
It("Check deps #", func() {
|
||||
Expect(len(gr.Dependencies)).Should(Equal(6))
|
||||
})
|
||||
|
||||
It("Check dep1", func() {
|
||||
Expect(*gr.Dependencies[0]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sbsigntools",
|
||||
Category: "app-crypt",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep2", func() {
|
||||
Expect(*gr.Dependencies[1]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sabayon-artwork-grub",
|
||||
Category: "x11-themes",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep5", func() {
|
||||
Expect(*gr.Dependencies[4]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "ncurses",
|
||||
Category: "sys-libs",
|
||||
Slot: "0=",
|
||||
Version: "5.2",
|
||||
VersionSuffix: "-r5",
|
||||
Condition: _gentoo.PkgCondGreaterEqual,
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep6", func() {
|
||||
Expect(*gr.Dependencies[5]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "mount",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: []*GentooDependency{
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "fuse",
|
||||
Category: "sys-fs",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Dep: nil,
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Context("Parse RDEPEND3", func() {
|
||||
|
||||
rdepend := `
|
||||
app-crypt/sbsigntools
|
||||
x11-themes/sabayon-artwork-grub
|
||||
sys-boot/os-prober
|
||||
app-arch/xz-utils
|
||||
>=sys-libs/ncurses-5.2-r5:0=
|
||||
mount? ( sys-fs/fuse =sys-apps/pmount-0.9.99_alpha-r5:= )
|
||||
`
|
||||
gr, err := ParseRDEPEND(rdepend)
|
||||
It("Check error", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
It("Check gr", func() {
|
||||
Expect(gr).ShouldNot(BeNil())
|
||||
})
|
||||
|
||||
It("Check deps #", func() {
|
||||
Expect(len(gr.Dependencies)).Should(Equal(6))
|
||||
})
|
||||
|
||||
It("Check dep1", func() {
|
||||
Expect(*gr.Dependencies[0]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sbsigntools",
|
||||
Category: "app-crypt",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep2", func() {
|
||||
Expect(*gr.Dependencies[1]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sabayon-artwork-grub",
|
||||
Category: "x11-themes",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep5", func() {
|
||||
Expect(*gr.Dependencies[4]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "ncurses",
|
||||
Category: "sys-libs",
|
||||
Slot: "0=",
|
||||
Version: "5.2",
|
||||
VersionSuffix: "-r5",
|
||||
Condition: _gentoo.PkgCondGreaterEqual,
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep6", func() {
|
||||
Expect(*gr.Dependencies[5]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "mount",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: []*GentooDependency{
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "fuse",
|
||||
Category: "sys-fs",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "pmount",
|
||||
Category: "sys-apps",
|
||||
Condition: _gentoo.PkgCondEqual,
|
||||
Version: "0.9.99",
|
||||
VersionSuffix: "_alpha-r5",
|
||||
Slot: "=",
|
||||
},
|
||||
},
|
||||
},
|
||||
Dep: nil,
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Context("Parse RDEPEND4", func() {
|
||||
|
||||
rdepend := `
|
||||
app-crypt/sbsigntools
|
||||
x11-themes/sabayon-artwork-grub
|
||||
sys-boot/os-prober
|
||||
app-arch/xz-utils
|
||||
>=sys-libs/ncurses-5.2-r5:0=
|
||||
!mount? ( sys-fs/fuse =sys-apps/pmount-0.9.99_alpha-r5:= )
|
||||
`
|
||||
gr, err := ParseRDEPEND(rdepend)
|
||||
It("Check error", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
It("Check gr", func() {
|
||||
Expect(gr).ShouldNot(BeNil())
|
||||
})
|
||||
|
||||
It("Check deps #", func() {
|
||||
Expect(len(gr.Dependencies)).Should(Equal(6))
|
||||
})
|
||||
|
||||
It("Check dep1", func() {
|
||||
Expect(*gr.Dependencies[0]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sbsigntools",
|
||||
Category: "app-crypt",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep2", func() {
|
||||
Expect(*gr.Dependencies[1]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sabayon-artwork-grub",
|
||||
Category: "x11-themes",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep5", func() {
|
||||
Expect(*gr.Dependencies[4]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "ncurses",
|
||||
Category: "sys-libs",
|
||||
Slot: "0=",
|
||||
Version: "5.2",
|
||||
VersionSuffix: "-r5",
|
||||
Condition: _gentoo.PkgCondGreaterEqual,
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep6", func() {
|
||||
Expect(*gr.Dependencies[5]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "mount",
|
||||
UseCondition: _gentoo.PkgCondNot,
|
||||
SubDeps: []*GentooDependency{
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "fuse",
|
||||
Category: "sys-fs",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "pmount",
|
||||
Category: "sys-apps",
|
||||
Condition: _gentoo.PkgCondEqual,
|
||||
Version: "0.9.99",
|
||||
VersionSuffix: "_alpha-r5",
|
||||
Slot: "=",
|
||||
},
|
||||
},
|
||||
},
|
||||
Dep: nil,
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Context("Parse RDEPEND5", func() {
|
||||
|
||||
rdepend := `
|
||||
app-crypt/sbsigntools
|
||||
>=sys-libs/ncurses-5.2-r5:0=
|
||||
mount? (
|
||||
sys-fs/fuse
|
||||
=sys-apps/pmount-0.9.99_alpha-r5:=
|
||||
)
|
||||
`
|
||||
gr, err := ParseRDEPEND(rdepend)
|
||||
It("Check error", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
It("Check gr", func() {
|
||||
Expect(gr).ShouldNot(BeNil())
|
||||
})
|
||||
|
||||
It("Check deps #", func() {
|
||||
Expect(len(gr.Dependencies)).Should(Equal(3))
|
||||
})
|
||||
|
||||
It("Check dep1", func() {
|
||||
Expect(*gr.Dependencies[0]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sbsigntools",
|
||||
Category: "app-crypt",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep2", func() {
|
||||
Expect(*gr.Dependencies[1]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "ncurses",
|
||||
Category: "sys-libs",
|
||||
Slot: "0=",
|
||||
Version: "5.2",
|
||||
VersionSuffix: "-r5",
|
||||
Condition: _gentoo.PkgCondGreaterEqual,
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep3", func() {
|
||||
Expect(*gr.Dependencies[2]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "mount",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: []*GentooDependency{
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "fuse",
|
||||
Category: "sys-fs",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "pmount",
|
||||
Category: "sys-apps",
|
||||
Condition: _gentoo.PkgCondEqual,
|
||||
Version: "0.9.99",
|
||||
VersionSuffix: "_alpha-r5",
|
||||
Slot: "=",
|
||||
},
|
||||
},
|
||||
},
|
||||
Dep: nil,
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Context("Parse RDEPEND6", func() {
|
||||
|
||||
rdepend := `
|
||||
app-crypt/sbsigntools
|
||||
>=sys-libs/ncurses-5.2-r5:0=
|
||||
mount? (
|
||||
sys-fs/fuse
|
||||
=sys-apps/pmount-0.9.99_alpha-r5:= )
|
||||
`
|
||||
gr, err := ParseRDEPEND(rdepend)
|
||||
It("Check error", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
It("Check gr", func() {
|
||||
Expect(gr).ShouldNot(BeNil())
|
||||
})
|
||||
|
||||
It("Check deps #", func() {
|
||||
Expect(len(gr.Dependencies)).Should(Equal(3))
|
||||
})
|
||||
|
||||
It("Check dep1", func() {
|
||||
Expect(*gr.Dependencies[0]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sbsigntools",
|
||||
Category: "app-crypt",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Parse RDEPEND7", func() {
|
||||
|
||||
rdepend := `
|
||||
app-crypt/sbsigntools
|
||||
>=sys-libs/ncurses-5.2-r5:0=
|
||||
mount? (
|
||||
sys-fs/fuse
|
||||
=sys-apps/pmount-0.9.99_alpha-r5:=
|
||||
ext2? (
|
||||
sys-fs/genext2fs
|
||||
)
|
||||
)
|
||||
`
|
||||
gr, err := ParseRDEPEND(rdepend)
|
||||
It("Check error", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
It("Check gr", func() {
|
||||
Expect(gr).ShouldNot(BeNil())
|
||||
})
|
||||
|
||||
It("Check deps #", func() {
|
||||
Expect(len(gr.Dependencies)).Should(Equal(3))
|
||||
})
|
||||
|
||||
It("Check dep1", func() {
|
||||
Expect(*gr.Dependencies[0]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "sbsigntools",
|
||||
Category: "app-crypt",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep2", func() {
|
||||
Expect(*gr.Dependencies[1]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "ncurses",
|
||||
Category: "sys-libs",
|
||||
Slot: "0=",
|
||||
Version: "5.2",
|
||||
VersionSuffix: "-r5",
|
||||
Condition: _gentoo.PkgCondGreaterEqual,
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
It("Check dep3", func() {
|
||||
Expect(*gr.Dependencies[2]).Should(Equal(
|
||||
GentooDependency{
|
||||
Use: "mount",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: []*GentooDependency{
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "fuse",
|
||||
Category: "sys-fs",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "pmount",
|
||||
Category: "sys-apps",
|
||||
Condition: _gentoo.PkgCondEqual,
|
||||
Version: "0.9.99",
|
||||
VersionSuffix: "_alpha-r5",
|
||||
Slot: "=",
|
||||
},
|
||||
},
|
||||
&GentooDependency{
|
||||
Use: "ext2",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: []*GentooDependency{
|
||||
&GentooDependency{
|
||||
Use: "",
|
||||
UseCondition: _gentoo.PkgCondInvalid,
|
||||
SubDeps: make([]*GentooDependency, 0),
|
||||
Dep: &_gentoo.GentooPackage{
|
||||
Name: "genext2fs",
|
||||
Category: "sys-fs",
|
||||
Slot: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Dep: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Context("Simple test", func() {
|
||||
for _, dbType := range []MemoryDB{InMemory, BoltDB} {
|
||||
It("parses correctly deps", func() {
|
||||
gb := NewGentooBuilder(&SimpleEbuildParser{}, 20, dbType)
|
||||
tree, err := gb.Generate("../../../../tests/fixtures/overlay")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer func() {
|
||||
Expect(tree.Clean()).ToNot(HaveOccurred())
|
||||
}()
|
||||
|
||||
Expect(len(tree.GetPackages())).To(Equal(10))
|
||||
|
||||
for _, p := range tree.World() {
|
||||
|
||||
Expect(p.GetName()).To(ContainSubstring("pinentry"))
|
||||
Expect(p.GetVersion()).To(ContainSubstring("1."))
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
})
|
@@ -74,39 +74,92 @@ func (r *CompilerRecipe) Load(path string) error {
|
||||
return errors.Wrap(err, "Error on walk path "+currentpath)
|
||||
}
|
||||
|
||||
if info.Name() != DefinitionFile {
|
||||
if info.Name() != DefinitionFile && info.Name() != CollectionFile {
|
||||
return nil // Skip with no errors
|
||||
}
|
||||
|
||||
pack, err := ReadDefinitionFile(currentpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Path is set only internally when tree is loaded from disk
|
||||
pack.SetPath(filepath.Dir(currentpath))
|
||||
switch info.Name() {
|
||||
case DefinitionFile:
|
||||
|
||||
// Instead of rdeps, have a different tree for build deps.
|
||||
compileDefPath := pack.Rel(CompilerDefinitionFile)
|
||||
if helpers.Exists(compileDefPath) {
|
||||
dat, err := ioutil.ReadFile(compileDefPath)
|
||||
pack, err := ReadDefinitionFile(currentpath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err,
|
||||
"Error reading file "+CompilerDefinitionFile+" from "+
|
||||
filepath.Dir(currentpath))
|
||||
return err
|
||||
}
|
||||
// Path is set only internally when tree is loaded from disk
|
||||
pack.SetPath(filepath.Dir(currentpath))
|
||||
|
||||
// Instead of rdeps, have a different tree for build deps.
|
||||
compileDefPath := pack.Rel(CompilerDefinitionFile)
|
||||
if helpers.Exists(compileDefPath) {
|
||||
|
||||
dat, err := helpers.RenderFiles(compileDefPath, currentpath, "")
|
||||
if err != nil {
|
||||
return errors.Wrap(err,
|
||||
"Error templating file "+CompilerDefinitionFile+" from "+
|
||||
filepath.Dir(currentpath))
|
||||
}
|
||||
|
||||
packbuild, err := pkg.DefaultPackageFromYaml([]byte(dat))
|
||||
if err != nil {
|
||||
return errors.Wrap(err,
|
||||
"Error reading yaml "+CompilerDefinitionFile+" from "+
|
||||
filepath.Dir(currentpath))
|
||||
}
|
||||
pack.Requires(packbuild.GetRequires())
|
||||
pack.Conflicts(packbuild.GetConflicts())
|
||||
}
|
||||
|
||||
_, err = r.Database.CreatePackage(&pack)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error creating package "+pack.GetName())
|
||||
}
|
||||
|
||||
case CollectionFile:
|
||||
dat, err := ioutil.ReadFile(currentpath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading file "+currentpath)
|
||||
}
|
||||
packs, err := pkg.DefaultPackagesFromYaml(dat)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading yaml "+currentpath)
|
||||
}
|
||||
packsRaw, err := pkg.GetRawPackages(dat)
|
||||
|
||||
for _, pack := range packs {
|
||||
pack.SetPath(filepath.Dir(currentpath))
|
||||
|
||||
// Instead of rdeps, have a different tree for build deps.
|
||||
compileDefPath := pack.Rel(CompilerDefinitionFile)
|
||||
if helpers.Exists(compileDefPath) {
|
||||
|
||||
raw := packsRaw.Find(pack.GetName(), pack.GetCategory(), pack.GetVersion())
|
||||
buildyaml, err := ioutil.ReadFile(compileDefPath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading file "+currentpath)
|
||||
}
|
||||
dat, err := helpers.RenderHelm(string(buildyaml), raw, map[string]interface{}{})
|
||||
if err != nil {
|
||||
return errors.Wrap(err,
|
||||
"Error templating file "+CompilerDefinitionFile+" from "+
|
||||
filepath.Dir(currentpath))
|
||||
}
|
||||
|
||||
packbuild, err := pkg.DefaultPackageFromYaml([]byte(dat))
|
||||
if err != nil {
|
||||
return errors.Wrap(err,
|
||||
"Error reading yaml "+CompilerDefinitionFile+" from "+
|
||||
filepath.Dir(currentpath))
|
||||
}
|
||||
pack.Requires(packbuild.GetRequires())
|
||||
pack.Conflicts(packbuild.GetConflicts())
|
||||
}
|
||||
|
||||
_, err = r.Database.CreatePackage(&pack)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error creating package "+pack.GetName())
|
||||
}
|
||||
}
|
||||
packbuild, err := pkg.DefaultPackageFromYaml(dat)
|
||||
if err != nil {
|
||||
return errors.Wrap(err,
|
||||
"Error reading yaml "+CompilerDefinitionFile+" from "+
|
||||
filepath.Dir(currentpath))
|
||||
}
|
||||
pack.Requires(packbuild.GetRequires())
|
||||
pack.Conflicts(packbuild.GetConflicts())
|
||||
}
|
||||
|
||||
_, err = r.Database.CreatePackage(&pack)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error creating package "+pack.GetName())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@@ -85,7 +85,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() != DefinitionFile {
|
||||
if info.Name() != DefinitionFile && info.Name() != CollectionFile {
|
||||
return nil // Skip with no errors
|
||||
}
|
||||
|
||||
@@ -93,16 +93,35 @@ func (r *InstallerRecipe) Load(path string) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading file "+currentpath)
|
||||
}
|
||||
pack, err := pkg.DefaultPackageFromYaml(dat)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading yaml "+currentpath)
|
||||
}
|
||||
|
||||
// Path is set only internally when tree is loaded from disk
|
||||
pack.SetPath(filepath.Dir(currentpath))
|
||||
_, err = r.Database.CreatePackage(&pack)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error creating package "+pack.GetName())
|
||||
switch info.Name() {
|
||||
case DefinitionFile:
|
||||
pack, err := pkg.DefaultPackageFromYaml(dat)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading yaml "+currentpath)
|
||||
}
|
||||
|
||||
// Path is set only internally when tree is loaded from disk
|
||||
pack.SetPath(filepath.Dir(currentpath))
|
||||
_, err = r.Database.CreatePackage(&pack)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error creating package "+pack.GetName())
|
||||
}
|
||||
|
||||
case CollectionFile:
|
||||
packs, err := pkg.DefaultPackagesFromYaml(dat)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading yaml "+currentpath)
|
||||
}
|
||||
for _, p := range packs {
|
||||
// Path is set only internally when tree is loaded from disk
|
||||
p.SetPath(filepath.Dir(currentpath))
|
||||
_, err = r.Database.CreatePackage(&p)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error creating package "+p.GetName())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@@ -34,6 +34,7 @@ import (
|
||||
|
||||
const (
|
||||
DefinitionFile = "definition.yaml"
|
||||
CollectionFile = "collection.yaml"
|
||||
)
|
||||
|
||||
func NewGeneralRecipe(db pkg.PackageDatabase) Builder { return &Recipe{Database: db} }
|
||||
@@ -94,7 +95,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() != DefinitionFile {
|
||||
if info.Name() != DefinitionFile && info.Name() != CollectionFile {
|
||||
return nil // Skip with no errors
|
||||
}
|
||||
|
||||
@@ -102,16 +103,34 @@ func (r *Recipe) Load(path string) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading file "+currentpath)
|
||||
}
|
||||
pack, err := pkg.DefaultPackageFromYaml(dat)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading yaml "+currentpath)
|
||||
}
|
||||
|
||||
// Path is set only internally when tree is loaded from disk
|
||||
pack.SetPath(filepath.Dir(currentpath))
|
||||
_, err = r.Database.CreatePackage(&pack)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error creating package "+pack.GetName())
|
||||
switch info.Name() {
|
||||
case DefinitionFile:
|
||||
pack, err := pkg.DefaultPackageFromYaml(dat)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading yaml "+currentpath)
|
||||
}
|
||||
|
||||
// Path is set only internally when tree is loaded from disk
|
||||
pack.SetPath(filepath.Dir(currentpath))
|
||||
_, err = r.Database.CreatePackage(&pack)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error creating package "+pack.GetName())
|
||||
}
|
||||
case CollectionFile:
|
||||
packs, err := pkg.DefaultPackagesFromYaml(dat)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error reading yaml "+currentpath)
|
||||
}
|
||||
for _, p := range packs {
|
||||
// Path is set only internally when tree is loaded from disk
|
||||
p.SetPath(filepath.Dir(currentpath))
|
||||
_, err = r.Database.CreatePackage(&p)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error creating package "+p.GetName())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@@ -1,136 +0,0 @@
|
||||
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Recipe is a builder imeplementation.
|
||||
|
||||
// It reads a Tree and spit it in human readable form (YAML), called recipe,
|
||||
// It also loads a tree (recipe) from a YAML (to a db, e.g. BoltDB), allowing to query it
|
||||
// with the solver, using the package object.
|
||||
package tree_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
pkg "github.com/mudler/luet/pkg/package"
|
||||
"github.com/mudler/luet/pkg/solver"
|
||||
gentoo "github.com/mudler/luet/pkg/tree/builder/gentoo"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
. "github.com/mudler/luet/pkg/tree"
|
||||
)
|
||||
|
||||
type FakeParser struct {
|
||||
}
|
||||
|
||||
var _ = Describe("Recipe", func() {
|
||||
for _, dbType := range []gentoo.MemoryDB{gentoo.InMemory, gentoo.BoltDB} {
|
||||
Context("Tree generation and storing", func() {
|
||||
It("parses and writes a tree", func() {
|
||||
tmpdir, err := ioutil.TempDir("", "tree")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
gb := gentoo.NewGentooBuilder(&gentoo.SimpleEbuildParser{}, 20, dbType)
|
||||
tree, err := gb.Generate("../../tests/fixtures/overlay")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer func() {
|
||||
Expect(tree.Clean()).ToNot(HaveOccurred())
|
||||
}()
|
||||
|
||||
Expect(len(tree.GetPackages())).To(Equal(10))
|
||||
|
||||
generalRecipe := NewGeneralRecipe(tree)
|
||||
err = generalRecipe.Save(tmpdir)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Context("Reloading trees", func() {
|
||||
It("writes and reads back the same tree", func() {
|
||||
tmpdir, err := ioutil.TempDir("", "tree")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
gb := gentoo.NewGentooBuilder(&gentoo.SimpleEbuildParser{}, 20, dbType)
|
||||
tree, err := gb.Generate("../../tests/fixtures/overlay")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer func() {
|
||||
Expect(tree.Clean()).ToNot(HaveOccurred())
|
||||
}()
|
||||
|
||||
Expect(len(tree.GetPackages())).To(Equal(10))
|
||||
|
||||
generalRecipe := NewGeneralRecipe(tree)
|
||||
err = generalRecipe.Save(tmpdir)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
db := pkg.NewInMemoryDatabase(false)
|
||||
generalRecipe = NewGeneralRecipe(db)
|
||||
|
||||
generalRecipe.WithDatabase(nil)
|
||||
Expect(generalRecipe.GetDatabase()).To(BeNil())
|
||||
|
||||
err = generalRecipe.Load(tmpdir)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(10))
|
||||
|
||||
for _, p := range tree.World() {
|
||||
Expect(p.GetName()).To(ContainSubstring("pinentry"))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Context("Simple solving with the fixture tree", func() {
|
||||
It("writes and reads back the same tree", func() {
|
||||
tmpdir, err := ioutil.TempDir("", "tree")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmpdir) // clean up
|
||||
|
||||
gb := gentoo.NewGentooBuilder(&gentoo.SimpleEbuildParser{}, 20, dbType)
|
||||
tree, err := gb.Generate("../../tests/fixtures/overlay")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer func() {
|
||||
Expect(tree.Clean()).ToNot(HaveOccurred())
|
||||
}()
|
||||
|
||||
Expect(len(tree.GetPackages())).To(Equal(10))
|
||||
|
||||
pack, err := tree.FindPackage(&pkg.DefaultPackage{
|
||||
Name: "pinentry",
|
||||
Version: "1.0.0-r2",
|
||||
Category: "app-crypt",
|
||||
}) // Note: the definition depends on pinentry-base without an explicit version
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
s := solver.NewSolver(solver.Options{Type: solver.SingleCoreSimple}, pkg.NewInMemoryDatabase(false), tree, tree)
|
||||
solution, err := s.Install([]pkg.Package{pack})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(solution)).To(Equal(14))
|
||||
|
||||
var allSol string
|
||||
for _, sol := range solution {
|
||||
allSol = allSol + "\n" + sol.ToString()
|
||||
}
|
||||
|
||||
Expect(allSol).To(ContainSubstring("app-crypt/pinentry-base 1.0.0 installed"))
|
||||
Expect(allSol).To(ContainSubstring("app-crypt/pinentry 1.1.0-r2 not installed"))
|
||||
Expect(allSol).To(ContainSubstring("app-crypt/pinentry 1.0.0-r2 installed"))
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
7
tests/fixtures/build_values/build.yaml
vendored
Normal file
7
tests/fixtures/build_values/build.yaml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
image: quay.io/mocaccino/extra
|
||||
steps:
|
||||
- touch /{{.Values.name}}
|
||||
- touch /build-extra-{{.Values.foo}}
|
||||
- touch /{{.Values.name}}-{{.Values.bb}}
|
||||
|
||||
unpack: true
|
13
tests/fixtures/build_values/collection.yaml
vendored
Normal file
13
tests/fixtures/build_values/collection.yaml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
packages:
|
||||
- name: "a"
|
||||
category: "distro"
|
||||
version: "0.1"
|
||||
foo: "baz"
|
||||
- name: "b"
|
||||
category: "distro"
|
||||
version: "0.3"
|
||||
foo: "f"
|
||||
- name: "c"
|
||||
category: "distro"
|
||||
version: "0.3"
|
||||
foo: "bar"
|
2
tests/fixtures/build_values/finalize.yaml
vendored
Normal file
2
tests/fixtures/build_values/finalize.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
install:
|
||||
- touch /finalize-{{.Values.name}}
|
4
tests/fixtures/build_values/pack/build.yaml
vendored
Normal file
4
tests/fixtures/build_values/pack/build.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
image: quay.io/mocaccino/extra
|
||||
steps:
|
||||
- touch /{{.Values.name}}
|
||||
- touch /{{.Values.name}}-{{.Values.bb}}
|
3
tests/fixtures/build_values/pack/definition.yaml
vendored
Normal file
3
tests/fixtures/build_values/pack/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
name: foo
|
||||
category: test
|
||||
version: "1.1"
|
2
tests/fixtures/buildable/cat/b/build.yaml
vendored
2
tests/fixtures/buildable/cat/b/build.yaml
vendored
@@ -2,8 +2,8 @@ image: "alpine"
|
||||
prelude:
|
||||
- echo foo > /test
|
||||
- echo bar > /test2
|
||||
- chmod +x generate.sh
|
||||
steps:
|
||||
- echo artifact5 > /test5
|
||||
- echo artifact6 > /test6
|
||||
- chmod +x generate.sh
|
||||
- ./generate.sh
|
@@ -2,8 +2,8 @@ image: "alpine"
|
||||
prelude:
|
||||
- echo foo > /test
|
||||
- echo bar > /test2
|
||||
- chmod +x generate.sh
|
||||
steps:
|
||||
- echo artifact5 > /test5
|
||||
- echo artifact6 > /test6
|
||||
- chmod +x generate.sh
|
||||
- ./generate.sh
|
6
tests/fixtures/collections/build.yaml
vendored
Normal file
6
tests/fixtures/collections/build.yaml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
image: quay.io/mocaccino/extra
|
||||
steps:
|
||||
- touch /{{.Values.name}}
|
||||
- touch /build-extra-{{.Values.foo}}
|
||||
|
||||
unpack: true
|
13
tests/fixtures/collections/collection.yaml
vendored
Normal file
13
tests/fixtures/collections/collection.yaml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
packages:
|
||||
- name: "a"
|
||||
category: "distro"
|
||||
version: "0.1"
|
||||
foo: "baz"
|
||||
- name: "b"
|
||||
category: "distro"
|
||||
version: "0.3"
|
||||
foo: "f"
|
||||
- name: "c"
|
||||
category: "distro"
|
||||
version: "0.3"
|
||||
foo: "bar"
|
2
tests/fixtures/collections/finalize.yaml
vendored
Normal file
2
tests/fixtures/collections/finalize.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
install:
|
||||
- touch /finalize-{{.Values.name}}
|
2
tests/fixtures/expansion/cat/b/build.yaml
vendored
2
tests/fixtures/expansion/cat/b/build.yaml
vendored
@@ -2,8 +2,8 @@ image: "alpine"
|
||||
prelude:
|
||||
- echo foo > /test
|
||||
- echo bar > /test2
|
||||
- chmod +x generate.sh
|
||||
steps:
|
||||
- echo artifact5 > /test5
|
||||
- echo artifact6 > /test6
|
||||
- chmod +x generate.sh
|
||||
- ./generate.sh
|
@@ -1,10 +1,10 @@
|
||||
image: "alpine"
|
||||
prelude:
|
||||
- mkdir /foo
|
||||
- chmod +x generate.sh
|
||||
steps:
|
||||
- echo artifact5 > /foo/test5
|
||||
- echo artifact6 > /foo/test6
|
||||
- chmod +x generate.sh
|
||||
- ./generate.sh
|
||||
package_dir: /foo
|
||||
includes:
|
||||
|
3
tests/fixtures/plugin/test-foo
vendored
Executable file
3
tests/fixtures/plugin/test-foo
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
echo "$1" >> $EVENT_FILE
|
||||
echo "$2" >> $PAYLOAD_FILE
|
@@ -1,6 +1,6 @@
|
||||
|
||||
steps:
|
||||
- tar xvf a-test-1.0.package.* -C ./
|
||||
- ls -liah /a
|
||||
- mv a /b
|
||||
requires:
|
||||
- name: "a"
|
||||
|
5
tests/fixtures/simple_dep/a/build.yaml
vendored
Normal file
5
tests/fixtures/simple_dep/a/build.yaml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
image: "alpine"
|
||||
prelude:
|
||||
- echo a > /a-prelude
|
||||
steps:
|
||||
- echo a > /a
|
3
tests/fixtures/simple_dep/a/definition.yaml
vendored
Normal file
3
tests/fixtures/simple_dep/a/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
category: "test"
|
||||
name: "a"
|
||||
version: "1.2"
|
9
tests/fixtures/simple_dep/b/build.yaml
vendored
Normal file
9
tests/fixtures/simple_dep/b/build.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
requires:
|
||||
- category: "test"
|
||||
name: "a"
|
||||
version: ">=0"
|
||||
|
||||
prelude:
|
||||
- echo b > /b-prelude
|
||||
steps:
|
||||
- echo b > /b
|
3
tests/fixtures/simple_dep/b/definition.yaml
vendored
Normal file
3
tests/fixtures/simple_dep/b/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
category: "test"
|
||||
name: "b"
|
||||
version: "1.1"
|
7
tests/fixtures/simple_dep/c/build.yaml
vendored
Normal file
7
tests/fixtures/simple_dep/c/build.yaml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
requires:
|
||||
- category: "test"
|
||||
name: "a"
|
||||
version: ">=0"
|
||||
steps:
|
||||
- echo c > /c
|
||||
|
9
tests/fixtures/simple_dep/c/definition.yaml
vendored
Normal file
9
tests/fixtures/simple_dep/c/definition.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
category: "test"
|
||||
name: "c"
|
||||
version: "1.0"
|
||||
# Boom?
|
||||
|
||||
requires:
|
||||
- category: "test"
|
||||
name: "a"
|
||||
version: ">=0.1"
|
2
tests/fixtures/templatedfinalizers/alpine/build.yaml
vendored
Normal file
2
tests/fixtures/templatedfinalizers/alpine/build.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
image: "alpine"
|
||||
unpack: true
|
3
tests/fixtures/templatedfinalizers/alpine/definition.yaml
vendored
Normal file
3
tests/fixtures/templatedfinalizers/alpine/definition.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
category: "seed"
|
||||
name: "alpine"
|
||||
version: "1.0"
|
2
tests/fixtures/templatedfinalizers/alpine/finalize.yaml
vendored
Normal file
2
tests/fixtures/templatedfinalizers/alpine/finalize.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
install:
|
||||
- echo "{{.Values.name}}" > /tmp/foo
|
2
tests/fixtures/upgrade/cat/b-1.1/build.yaml
vendored
2
tests/fixtures/upgrade/cat/b-1.1/build.yaml
vendored
@@ -2,8 +2,8 @@ image: "alpine"
|
||||
prelude:
|
||||
- echo foo > /test
|
||||
- echo bar > /test2
|
||||
- chmod +x generate.sh
|
||||
steps:
|
||||
- echo artifact5 > /newc
|
||||
- echo artifact6 > /newnewc
|
||||
- chmod +x generate.sh
|
||||
- ./generate.sh
|
||||
|
2
tests/fixtures/upgrade/cat/b/build.yaml
vendored
2
tests/fixtures/upgrade/cat/b/build.yaml
vendored
@@ -2,8 +2,8 @@ image: "alpine"
|
||||
prelude:
|
||||
- echo foo > /test
|
||||
- echo bar > /test2
|
||||
- chmod +x generate.sh
|
||||
steps:
|
||||
- echo artifact5 > /test5
|
||||
- echo artifact6 > /test6
|
||||
- chmod +x generate.sh
|
||||
- ./generate.sh
|
@@ -2,8 +2,8 @@ image: "alpine"
|
||||
prelude:
|
||||
- echo foo > /test
|
||||
- echo bar > /test2
|
||||
- chmod +x generate.sh
|
||||
steps:
|
||||
- echo artifact5 > /newc
|
||||
- echo artifact6 > /newnewc
|
||||
- chmod +x generate.sh
|
||||
- ./generate.sh
|
||||
|
@@ -2,8 +2,8 @@ image: "alpine"
|
||||
prelude:
|
||||
- echo foo > /test
|
||||
- echo bar > /test2
|
||||
- chmod +x generate.sh
|
||||
steps:
|
||||
- echo artifact5 > /test5
|
||||
- echo artifact6 > /test6
|
||||
- chmod +x generate.sh
|
||||
- ./generate.sh
|
@@ -2,8 +2,8 @@ image: "alpine"
|
||||
prelude:
|
||||
- echo foo > /test
|
||||
- echo bar > /test2
|
||||
- chmod +x generate.sh
|
||||
steps:
|
||||
- echo artifact5 > /newc
|
||||
- echo artifact6 > /newnewc
|
||||
- chmod +x generate.sh
|
||||
- ./generate.sh
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user