mirror of
https://github.com/mudler/luet.git
synced 2025-09-01 23:37:07 +00:00
Compare commits
15 Commits
cli_fixups
...
0.32.5
Author | SHA1 | Date | |
---|---|---|---|
|
d5d21653d7 | ||
|
913462b81c | ||
|
aeb686f426 | ||
|
f98cd401be | ||
|
70f99b6bb7 | ||
|
cfbd8bf708 | ||
|
4cb21a3e02 | ||
|
3a31639897 | ||
|
bac9bac25f | ||
|
ce95b3ada4 | ||
|
49d8c2b972 | ||
|
2b3a1555f0 | ||
|
03e72653c7 | ||
|
264bf53fe7 | ||
|
edd2275bf5 |
6
Makefile
6
Makefile
@@ -81,6 +81,12 @@ test-docker:
|
||||
--workdir /go/src/github.com/mudler/luet -ti golang:latest \
|
||||
bash -c "make test"
|
||||
|
||||
.PHONY: test-integration-docker
|
||||
test-integration-docker:
|
||||
docker run -v $(ROOT_DIR):/go/src/github.com/mudler/luet -v /var/run/docker.sock:/var/run/docker.sock \
|
||||
--workdir /go/src/github.com/mudler/luet -ti golang:latest \
|
||||
bash -c "apt-get update && apt-get install docker.io && make test-integration"
|
||||
|
||||
multiarch-build:
|
||||
goreleaser build --snapshot --rm-dist
|
||||
|
||||
|
@@ -30,7 +30,7 @@ var cfgFile string
|
||||
var Verbose bool
|
||||
|
||||
const (
|
||||
LuetCLIVersion = "0.32.1"
|
||||
LuetCLIVersion = "0.32.5"
|
||||
LuetEnvPrefix = "LUET"
|
||||
)
|
||||
|
||||
|
2
go.mod
2
go.mod
@@ -28,6 +28,7 @@ require (
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/ipfs/go-log/v2 v2.4.0
|
||||
github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3
|
||||
github.com/kendru/darwin/go/depgraph v0.0.0-20220319173517-8abc3541da93
|
||||
github.com/klauspost/compress v1.15.1
|
||||
github.com/klauspost/pgzip v1.2.5
|
||||
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
|
||||
@@ -49,7 +50,6 @@ require (
|
||||
github.com/otiai10/copy v1.2.1-0.20200916181228-26f84a0b1578
|
||||
github.com/pelletier/go-toml v1.9.4
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible
|
||||
github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pterm/pterm v0.12.32-0.20211002183613-ada9ef6790c3
|
||||
github.com/rancher-sandbox/gofilecache v0.0.0-20210330135715-becdeff5df15
|
||||
|
4
go.sum
4
go.sum
@@ -927,6 +927,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kendru/darwin/go/depgraph v0.0.0-20220319173517-8abc3541da93 h1:bnXl8jWYsxRiO4Jc70GDKH2KhB4yRDlFAxjGng4v8+0=
|
||||
github.com/kendru/darwin/go/depgraph v0.0.0-20220319173517-8abc3541da93/go.mod h1:VOfm8h1NySetVlpHDSnbpCMsvCgYaU+YDn4XezUy2+4=
|
||||
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/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
@@ -1201,8 +1203,6 @@ github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw=
|
||||
github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f h1:WyCn68lTiytVSkk7W1K9nBiSGTSRlUOdyTnSjwrIlok=
|
||||
github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f/go.mod h1:/iRjX3DdSK956SzsUdV55J+wIsQ+2IBWmBrB4RvZfk4=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
@@ -30,7 +30,7 @@ import (
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
*logger.Logger
|
||||
types.Logger
|
||||
context.Context
|
||||
types.GarbageCollector
|
||||
Config *types.LuetConfig
|
||||
@@ -51,7 +51,7 @@ func (c *Context) GetAnnotation(s string) interface{} {
|
||||
type ContextOption func(c *Context) error
|
||||
|
||||
// WithLogger sets the logger
|
||||
func WithLogger(l *logger.Logger) ContextOption {
|
||||
func WithLogger(l types.Logger) ContextOption {
|
||||
return func(c *Context) error {
|
||||
c.Logger = l
|
||||
return nil
|
||||
@@ -122,13 +122,14 @@ func (c *Context) WithLoggingContext(name string) types.Context {
|
||||
ctxCopy.Config = &configCopy
|
||||
ctxCopy.annotations = ctx.annotations
|
||||
|
||||
ctxCopy.Logger, _ = c.Logger.Copy(logger.WithContext(name))
|
||||
ctxCopy.Logger, _ = c.Logger.Copy()
|
||||
ctxCopy.Logger.SetContext(name)
|
||||
|
||||
return ctxCopy
|
||||
}
|
||||
|
||||
// Copy returns a context copy with a reset logging context
|
||||
func (c *Context) Copy() types.Context {
|
||||
func (c *Context) Clone() types.Context {
|
||||
return c.WithLoggingContext("")
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,7 @@ package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"runtime"
|
||||
@@ -25,6 +26,7 @@ import (
|
||||
|
||||
log "github.com/ipfs/go-log/v2"
|
||||
"github.com/kyokomi/emoji"
|
||||
"github.com/mudler/luet/pkg/api/core/types"
|
||||
"github.com/pterm/pterm"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
@@ -114,18 +116,19 @@ func New(opts ...LoggerOptions) (*Logger, error) {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (l *Logger) Copy(opts ...LoggerOptions) (*Logger, error) {
|
||||
// Copy returns a copy of the logger
|
||||
func (l *Logger) Copy() (types.Logger, error) {
|
||||
c := *l
|
||||
copy := &c
|
||||
for _, o := range opts {
|
||||
if err := o(copy); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return copy, nil
|
||||
}
|
||||
|
||||
// SetContext sets the logger context, used to prefix log lines
|
||||
func (l *Logger) SetContext(name string) {
|
||||
l.context = name
|
||||
}
|
||||
|
||||
func joinMsg(args ...interface{}) (message string) {
|
||||
for _, m := range args {
|
||||
message += " " + fmt.Sprintf("%v", m)
|
||||
@@ -252,7 +255,7 @@ func (l *Logger) Tracef(t string, args ...interface{}) {
|
||||
|
||||
func (l *Logger) Fatal(args ...interface{}) {
|
||||
l.send(log.LevelFatal, "", args...)
|
||||
panic("fatal error")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func (l *Logger) Info(args ...interface{}) {
|
||||
|
@@ -21,7 +21,6 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/gookit/color"
|
||||
"github.com/mudler/luet/pkg/api/core/logger"
|
||||
. "github.com/mudler/luet/pkg/api/core/logger"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
@@ -84,11 +83,12 @@ var _ = Describe("Context and logging", func() {
|
||||
|
||||
It("returns copies with logged context", func() {
|
||||
l, err := New(WithLevel("debug"))
|
||||
l, _ = l.Copy(logger.WithContext("bazzz"))
|
||||
l2, _ := l.Copy()
|
||||
l2.SetContext("bazzz")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(captureStdout(func(w io.Writer) {
|
||||
l.Debug("bar")
|
||||
l2.Debug("bar")
|
||||
})).To(ContainSubstring("(bazzz) bar"))
|
||||
})
|
||||
|
||||
|
@@ -6,8 +6,8 @@ import (
|
||||
"sort"
|
||||
"unicode"
|
||||
|
||||
"github.com/kendru/darwin/go/depgraph"
|
||||
"github.com/mudler/topsort"
|
||||
"github.com/philopon/go-toposort"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -30,51 +30,37 @@ func (a *PackageAssert) String() string {
|
||||
return fmt.Sprintf("%s/%s %s %s", a.Package.GetCategory(), a.Package.GetName(), a.Package.GetVersion(), msg)
|
||||
}
|
||||
|
||||
func (assertions PackagesAssertions) EnsureOrder() PackagesAssertions {
|
||||
func (assertions PackagesAssertions) EnsureOrder(definitiondb PackageDatabase) (PackagesAssertions, error) {
|
||||
|
||||
allAssertions := assertions
|
||||
orderedAssertions := PackagesAssertions{}
|
||||
unorderedAssertions := PackagesAssertions{}
|
||||
fingerprints := []string{}
|
||||
|
||||
tmpMap := map[string]PackageAssert{}
|
||||
g := depgraph.New()
|
||||
|
||||
for _, a := range assertions {
|
||||
tmpMap[a.Package.GetFingerPrint()] = a
|
||||
fingerprints = append(fingerprints, a.Package.GetFingerPrint())
|
||||
unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered
|
||||
|
||||
if a.Value {
|
||||
unorderedAssertions = append(unorderedAssertions, a) // Build a list of the ones that must be ordered
|
||||
} else {
|
||||
orderedAssertions = append(orderedAssertions, a) // Keep last the ones which are not meant to be installed
|
||||
}
|
||||
tmpMap[a.Package.GetPackageName()] = a
|
||||
}
|
||||
|
||||
sort.Sort(unorderedAssertions)
|
||||
|
||||
// Build a topological graph
|
||||
graph := toposort.NewGraph(len(unorderedAssertions))
|
||||
graph.AddNodes(fingerprints...)
|
||||
for _, a := range unorderedAssertions {
|
||||
for _, a := range allAssertions {
|
||||
for _, req := range a.Package.GetRequires() {
|
||||
graph.AddEdge(a.Package.GetFingerPrint(), req.GetFingerPrint())
|
||||
if def, err := definitiondb.FindPackage(req); err == nil { // Provides: Get a chance of being override here
|
||||
req = def
|
||||
}
|
||||
g.DependOn(a.Package.GetPackageName(), req.GetPackageName())
|
||||
}
|
||||
}
|
||||
result, ok := graph.Toposort()
|
||||
if !ok {
|
||||
panic("Cycle found")
|
||||
}
|
||||
for _, res := range result {
|
||||
a, ok := tmpMap[res]
|
||||
if !ok {
|
||||
panic("fail")
|
||||
// continue
|
||||
|
||||
for _, res := range g.TopoSortedLayers() {
|
||||
for _, r := range res {
|
||||
a, ok := tmpMap[r]
|
||||
if ok {
|
||||
orderedAssertions = append(orderedAssertions, a)
|
||||
}
|
||||
}
|
||||
orderedAssertions = append(orderedAssertions, a)
|
||||
// orderedAssertions = append(PackagesAssertions{a}, orderedAssertions...) // push upfront
|
||||
}
|
||||
//helpers.ReverseAny(orderedAssertions)
|
||||
return orderedAssertions
|
||||
// helpers.ReverseAny(orderedAssertions)
|
||||
return orderedAssertions, nil
|
||||
}
|
||||
|
||||
// SearchByName searches a string matching a package in the assetion list
|
||||
|
116
pkg/api/core/types/assertion_test.go
Normal file
116
pkg/api/core/types/assertion_test.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright © 2021 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 types_test
|
||||
|
||||
import (
|
||||
types "github.com/mudler/luet/pkg/api/core/types"
|
||||
"github.com/mudler/luet/pkg/database"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Assertions", func() {
|
||||
Context("Ordering", func() {
|
||||
It("orders them correctly", func() {
|
||||
foo := &types.Package{Name: "foo", PackageRequires: []*types.Package{{Name: "bar"}}}
|
||||
assertions := types.PackagesAssertions{
|
||||
{Package: foo},
|
||||
{Package: &types.Package{Name: "baz", PackageRequires: []*types.Package{{Name: "bar"}}}},
|
||||
{Package: &types.Package{Name: "bar", PackageRequires: []*types.Package{{}}}},
|
||||
}
|
||||
|
||||
ordered_old, err := assertions.Order(database.NewInMemoryDatabase(false), foo.GetFingerPrint())
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
Expect(ordered_old[0].Package.Name).To(Equal("bar"))
|
||||
|
||||
ordered, err := assertions.EnsureOrder(database.NewInMemoryDatabase(false))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(len(ordered)).To(Equal(3))
|
||||
|
||||
Expect(ordered[0].Package.Name).To(Equal("bar"))
|
||||
})
|
||||
|
||||
It("errors on cycles", func() {
|
||||
foo := &types.Package{Name: "foo", PackageRequires: []*types.Package{{Name: "bar"}}}
|
||||
assertions := types.PackagesAssertions{
|
||||
{Package: foo},
|
||||
{Package: &types.Package{Name: "baz", PackageRequires: []*types.Package{{Name: "bar"}}}},
|
||||
{Package: &types.Package{Name: "bar", PackageRequires: []*types.Package{{Name: "baz"}}}},
|
||||
}
|
||||
|
||||
_, err := assertions.Order(database.NewInMemoryDatabase(false), foo.GetFingerPrint())
|
||||
Expect(err).Should(HaveOccurred())
|
||||
|
||||
_, err = assertions.EnsureOrder(database.NewInMemoryDatabase(false))
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
|
||||
It("orders them correctly", func() {
|
||||
foo := &types.Package{Name: "foo", PackageRequires: []*types.Package{{Name: "bar"}}}
|
||||
assertions := types.PackagesAssertions{
|
||||
{Package: foo},
|
||||
{Package: &types.Package{Name: "baz2", PackageRequires: []*types.Package{{Name: "foobaz"}}}},
|
||||
{Package: &types.Package{Name: "baz", PackageRequires: []*types.Package{{Name: "bar"}}}},
|
||||
{Package: &types.Package{Name: "bar", PackageRequires: []*types.Package{{}}}},
|
||||
{Package: &types.Package{Name: "foobaz", PackageRequires: []*types.Package{{}}}},
|
||||
}
|
||||
|
||||
ordered_old, err := assertions.Order(database.NewInMemoryDatabase(false), foo.GetFingerPrint())
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
Expect(ordered_old[0].Package.Name).To(Equal("bar"))
|
||||
Expect(ordered_old[1].Package.Name).ToNot(Equal("foobaz"))
|
||||
|
||||
ordered, err := assertions.EnsureOrder(database.NewInMemoryDatabase(false))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(len(ordered)).To(Equal(5))
|
||||
|
||||
Expect(ordered[0].Package.Name).To(Equal("bar"))
|
||||
Expect(ordered[1].Package.Name).To(Equal("foobaz"))
|
||||
})
|
||||
|
||||
It("orders them correctly", func() {
|
||||
foo := &types.Package{Name: "foo", PackageRequires: []*types.Package{{Name: "bar"}}}
|
||||
assertions := types.PackagesAssertions{
|
||||
{Package: foo},
|
||||
{Package: &types.Package{Name: "bazbaz2", PackageRequires: []*types.Package{{Name: "baz2"}}}},
|
||||
{Package: &types.Package{Name: "baz2", PackageRequires: []*types.Package{{Name: "foobaz"}, {Name: "baz"}}}},
|
||||
{Package: &types.Package{Name: "baz", PackageRequires: []*types.Package{{Name: "bar"}}}},
|
||||
{Package: &types.Package{Name: "bar", PackageRequires: []*types.Package{{}}}},
|
||||
{Package: &types.Package{Name: "foobaz", PackageRequires: []*types.Package{{}}}},
|
||||
}
|
||||
|
||||
ordered_old, err := assertions.Order(database.NewInMemoryDatabase(false), foo.GetFingerPrint())
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
Expect(ordered_old[0].Package.Name).To(Equal("bar"))
|
||||
Expect(ordered_old[1].Package.Name).ToNot(Equal("foobaz"))
|
||||
|
||||
ordered, err := assertions.EnsureOrder(database.NewInMemoryDatabase(false))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(len(ordered)).To(Equal(6))
|
||||
|
||||
Expect(ordered[0].Package.Name).To(Or(Equal("foobaz"), Equal("bar")))
|
||||
Expect(ordered[1].Package.Name).To(Or(Equal("foobaz"), Equal("bar")))
|
||||
Expect(ordered[2].Package.Name).To(Or(Equal("foo"), Equal("baz")))
|
||||
Expect(ordered[3].Package.Name).To(Or(Equal("foo"), Equal("baz")))
|
||||
Expect(ordered[4].Package.Name).To(Equal("baz2"))
|
||||
Expect(ordered[5].Package.Name).To(Equal("bazbaz2"))
|
||||
|
||||
})
|
||||
})
|
||||
})
|
@@ -19,7 +19,7 @@ type Context interface {
|
||||
Logger
|
||||
GarbageCollector
|
||||
GetConfig() LuetConfig
|
||||
Copy() Context
|
||||
Clone() Context
|
||||
// SetAnnotation sets generic annotations to hold in a context
|
||||
SetAnnotation(s string, i interface{})
|
||||
|
||||
|
@@ -33,7 +33,8 @@ type Logger interface {
|
||||
Fatalf(string, ...interface{})
|
||||
Panicf(string, ...interface{})
|
||||
Tracef(string, ...interface{})
|
||||
|
||||
Copy() (Logger, error)
|
||||
SetContext(string)
|
||||
SpinnerStop()
|
||||
Spinner()
|
||||
Ask() bool
|
||||
|
@@ -22,6 +22,8 @@ import (
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/mudler/luet/pkg/api/core/types"
|
||||
box "github.com/mudler/luet/pkg/box"
|
||||
fileHelper "github.com/mudler/luet/pkg/helpers/file"
|
||||
"github.com/mudler/luet/pkg/tree"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -90,3 +92,52 @@ func NewLuetFinalizerFromYaml(data []byte) (*LuetFinalizer, error) {
|
||||
}
|
||||
return &p, err
|
||||
}
|
||||
|
||||
func OrderFinalizers(allRepos types.PackageDatabase, toInstall map[string]ArtifactMatch, solution types.PackagesAssertions) ([]*types.Package, error) {
|
||||
var toFinalize []*types.Package
|
||||
|
||||
populate := func(ordered types.PackagesAssertions) error {
|
||||
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
|
||||
}
|
||||
treePackage, err := installed.Repository.GetTree().GetDatabase().FindPackage(ass.Package)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error getting package "+ass.Package.HumanReadableString())
|
||||
}
|
||||
|
||||
toFinalize = append(toFinalize, treePackage)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(toInstall) == 1 {
|
||||
for _, w := range toInstall {
|
||||
if fileHelper.Exists(w.Package.Rel(tree.FinalizerFile)) {
|
||||
// Finalizers needs to run in order and in sequence.
|
||||
ordered, err := solution.Order(allRepos, w.Package.GetFingerPrint())
|
||||
if err != nil {
|
||||
return toFinalize, errors.Wrap(err, "While order a solution for "+w.Package.HumanReadableString())
|
||||
}
|
||||
if err := populate(ordered); err != nil {
|
||||
return toFinalize, err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assertions, err := solution.EnsureOrder(allRepos)
|
||||
if err != nil {
|
||||
return toFinalize, err
|
||||
}
|
||||
|
||||
if err := populate(assertions); err != nil {
|
||||
return toFinalize, err
|
||||
}
|
||||
}
|
||||
|
||||
return toFinalize, nil
|
||||
}
|
||||
|
@@ -638,7 +638,7 @@ func (l *LuetInstaller) download(syncedRepos Repositories, toDownload map[string
|
||||
|
||||
var wg = new(sync.WaitGroup)
|
||||
|
||||
ctx := l.Options.Context.Copy()
|
||||
ctx := l.Options.Context.Clone()
|
||||
|
||||
// Check if the terminal is big enough to display a progress bar
|
||||
// https://github.com/pterm/pterm/blob/4c725e56bfd9eb38e1c7b9dec187b50b93baa8bd/progressbar_printer.go#L190
|
||||
@@ -816,33 +816,7 @@ func (l *LuetInstaller) computeInstall(o Option, syncedRepos Repositories, cp ty
|
||||
func (l *LuetInstaller) getFinalizers(allRepos types.PackageDatabase, solution types.PackagesAssertions, toInstall map[string]ArtifactMatch, nodeps bool) ([]*types.Package, error) {
|
||||
var toFinalize []*types.Package
|
||||
if !nodeps {
|
||||
// TODO: Lower those errors as l.Options.Context.Warning
|
||||
for _, w := range toInstall {
|
||||
if !fileHelper.Exists(w.Package.Rel(tree.FinalizerFile)) {
|
||||
continue
|
||||
}
|
||||
// Finalizers needs to run in order and in sequence.
|
||||
ordered, err := solution.Order(allRepos, w.Package.GetFingerPrint())
|
||||
if err != nil {
|
||||
return toFinalize, errors.Wrap(err, "While order a solution for "+w.Package.HumanReadableString())
|
||||
}
|
||||
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 toFinalize, errors.Wrap(err, "Error getting package "+ass.Package.HumanReadableString())
|
||||
}
|
||||
|
||||
toFinalize = append(toFinalize, treePackage)
|
||||
}
|
||||
}
|
||||
}
|
||||
return OrderFinalizers(allRepos, toInstall, solution)
|
||||
} else {
|
||||
for _, c := range toInstall {
|
||||
if !fileHelper.Exists(c.Package.Rel(tree.FinalizerFile)) {
|
||||
|
@@ -457,6 +457,14 @@ func (r *LuetSystemRepository) SetVerify(p bool) {
|
||||
r.LuetRepository.Verify = p
|
||||
}
|
||||
|
||||
func (r *LuetSystemRepository) GetReferenceID() string {
|
||||
return r.LuetRepository.ReferenceID
|
||||
}
|
||||
|
||||
func (r *LuetSystemRepository) SetReferenceID(ref string) {
|
||||
r.LuetRepository.ReferenceID = ref
|
||||
}
|
||||
|
||||
func (r *LuetSystemRepository) GetBackend() compiler.CompilerBackend {
|
||||
return r.Backend
|
||||
}
|
||||
@@ -1051,6 +1059,7 @@ func (r *LuetSystemRepository) fill(r2 *LuetSystemRepository) {
|
||||
r2.SetPriority(r.GetPriority())
|
||||
r2.SetName(r.GetName())
|
||||
r2.SetVerify(r.GetVerify())
|
||||
r2.SetReferenceID(r.GetReferenceID())
|
||||
}
|
||||
|
||||
func (r *LuetSystemRepository) Serialize() (*LuetSystemRepositoryMetadata, LuetSystemRepository) {
|
||||
|
232
vendor/github.com/kendru/darwin/go/depgraph/depgraph.go
generated
vendored
Normal file
232
vendor/github.com/kendru/darwin/go/depgraph/depgraph.go
generated
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
package depgraph
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// A node in this graph is just a string, so a nodeset is a map whose
|
||||
// keys are the nodes that are present.
|
||||
type nodeset map[string]struct{}
|
||||
|
||||
// depmap tracks the nodes that have some dependency relationship to
|
||||
// some other node, represented by the key of the map.
|
||||
type depmap map[string]nodeset
|
||||
|
||||
type Graph struct {
|
||||
nodes nodeset
|
||||
|
||||
// Maintain dependency relationships in both directions. These
|
||||
// data structures are the edges of the graph.
|
||||
|
||||
// `dependencies` tracks child -> parents.
|
||||
dependencies depmap
|
||||
// `dependents` tracks parent -> children.
|
||||
dependents depmap
|
||||
// Keep track of the nodes of the graph themselves.
|
||||
}
|
||||
|
||||
func New() *Graph {
|
||||
return &Graph{
|
||||
dependencies: make(depmap),
|
||||
dependents: make(depmap),
|
||||
nodes: make(nodeset),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) DependOn(child, parent string) error {
|
||||
if child == parent {
|
||||
return errors.New("self-referential dependencies not allowed")
|
||||
}
|
||||
|
||||
if g.DependsOn(parent, child) {
|
||||
return errors.New("circular dependencies not allowed")
|
||||
}
|
||||
|
||||
// Add nodes.
|
||||
g.nodes[parent] = struct{}{}
|
||||
g.nodes[child] = struct{}{}
|
||||
|
||||
// Add edges.
|
||||
addNodeToNodeset(g.dependents, parent, child)
|
||||
addNodeToNodeset(g.dependencies, child, parent)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Graph) DependsOn(child, parent string) bool {
|
||||
deps := g.Dependencies(child)
|
||||
_, ok := deps[parent]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (g *Graph) HasDependent(parent, child string) bool {
|
||||
deps := g.Dependents(parent)
|
||||
_, ok := deps[child]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (g *Graph) Leaves() []string {
|
||||
leaves := make([]string, 0)
|
||||
|
||||
for node := range g.nodes {
|
||||
if _, ok := g.dependencies[node]; !ok {
|
||||
leaves = append(leaves, node)
|
||||
}
|
||||
}
|
||||
|
||||
return leaves
|
||||
}
|
||||
|
||||
// TopoSortedLayers returns a slice of all of the graph nodes in topological sort order. That is,
|
||||
// if `B` depends on `A`, then `A` is guaranteed to come before `B` in the sorted output.
|
||||
// The graph is guaranteed to be cycle-free because cycles are detected while building the
|
||||
// graph. Additionally, the output is grouped into "layers", which are guaranteed to not have
|
||||
// any dependencies within each layer. This is useful, e.g. when building an execution plan for
|
||||
// some DAG, in which case each element within each layer could be executed in parallel. If you
|
||||
// do not need this layered property, use `Graph.TopoSorted()`, which flattens all elements.
|
||||
func (g *Graph) TopoSortedLayers() [][]string {
|
||||
layers := [][]string{}
|
||||
|
||||
// Copy the graph
|
||||
shrinkingGraph := g.clone()
|
||||
for {
|
||||
leaves := shrinkingGraph.Leaves()
|
||||
if len(leaves) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
layers = append(layers, leaves)
|
||||
for _, leafNode := range leaves {
|
||||
shrinkingGraph.remove(leafNode)
|
||||
}
|
||||
}
|
||||
|
||||
return layers
|
||||
}
|
||||
|
||||
func removeFromDepmap(dm depmap, key, node string) {
|
||||
nodes := dm[key]
|
||||
if len(nodes) == 1 {
|
||||
// The only element in the nodeset must be `node`, so we
|
||||
// can delete the entry entirely.
|
||||
delete(dm, key)
|
||||
} else {
|
||||
// Otherwise, remove the single node from the nodeset.
|
||||
delete(nodes, node)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) remove(node string) {
|
||||
// Remove edges from things that depend on `node`.
|
||||
for dependent := range g.dependents[node] {
|
||||
removeFromDepmap(g.dependencies, dependent, node)
|
||||
}
|
||||
delete(g.dependents, node)
|
||||
|
||||
// Remove all edges from node to the things it depends on.
|
||||
for dependency := range g.dependencies[node] {
|
||||
removeFromDepmap(g.dependents, dependency, node)
|
||||
}
|
||||
delete(g.dependencies, node)
|
||||
|
||||
// Finally, remove the node itself.
|
||||
delete(g.nodes, node)
|
||||
}
|
||||
|
||||
// TopoSorted returns all the nodes in the graph is topological sort order.
|
||||
// See also `Graph.TopoSortedLayers()`.
|
||||
func (g *Graph) TopoSorted() []string {
|
||||
nodeCount := 0
|
||||
layers := g.TopoSortedLayers()
|
||||
for _, layer := range layers {
|
||||
nodeCount += len(layer)
|
||||
}
|
||||
|
||||
allNodes := make([]string, 0, nodeCount)
|
||||
for _, layer := range layers {
|
||||
for _, node := range layer {
|
||||
allNodes = append(allNodes, node)
|
||||
}
|
||||
}
|
||||
|
||||
return allNodes
|
||||
}
|
||||
|
||||
func (g *Graph) Dependencies(child string) nodeset {
|
||||
return g.buildTransitive(child, g.immediateDependencies)
|
||||
}
|
||||
|
||||
func (g *Graph) immediateDependencies(node string) nodeset {
|
||||
return g.dependencies[node]
|
||||
}
|
||||
|
||||
func (g *Graph) Dependents(parent string) nodeset {
|
||||
return g.buildTransitive(parent, g.immediateDependents)
|
||||
}
|
||||
|
||||
func (g *Graph) immediateDependents(node string) nodeset {
|
||||
return g.dependents[node]
|
||||
}
|
||||
|
||||
func (g *Graph) clone() *Graph {
|
||||
return &Graph{
|
||||
dependencies: copyDepmap(g.dependencies),
|
||||
dependents: copyDepmap(g.dependents),
|
||||
nodes: copyNodeset(g.nodes),
|
||||
}
|
||||
}
|
||||
|
||||
// buildTransitive starts at `root` and continues calling `nextFn` to keep discovering more nodes until
|
||||
// the graph cannot produce any more. It returns the set of all discovered nodes.
|
||||
func (g *Graph) buildTransitive(root string, nextFn func(string) nodeset) nodeset {
|
||||
if _, ok := g.nodes[root]; !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make(nodeset)
|
||||
searchNext := []string{root}
|
||||
for len(searchNext) > 0 {
|
||||
// List of new nodes from this layer of the dependency graph. This is
|
||||
// assigned to `searchNext` at the end of the outer "discovery" loop.
|
||||
discovered := []string{}
|
||||
for _, node := range searchNext {
|
||||
// For each node to discover, find the next nodes.
|
||||
for nextNode := range nextFn(node) {
|
||||
// If we have not seen the node before, add it to the output as well
|
||||
// as the list of nodes to traverse in the next iteration.
|
||||
if _, ok := out[nextNode]; !ok {
|
||||
out[nextNode] = struct{}{}
|
||||
discovered = append(discovered, nextNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
searchNext = discovered
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func copyNodeset(s nodeset) nodeset {
|
||||
out := make(nodeset, len(s))
|
||||
for k, v := range s {
|
||||
out[k] = v
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func copyDepmap(m depmap) depmap {
|
||||
out := make(depmap, len(m))
|
||||
for k, v := range m {
|
||||
out[k] = copyNodeset(v)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func addNodeToNodeset(dm depmap, key, node string) {
|
||||
nodes, ok := dm[key]
|
||||
if !ok {
|
||||
nodes = make(nodeset)
|
||||
dm[key] = nodes
|
||||
}
|
||||
nodes[node] = struct{}{}
|
||||
}
|
5
vendor/github.com/kendru/darwin/go/depgraph/go.mod
generated
vendored
Normal file
5
vendor/github.com/kendru/darwin/go/depgraph/go.mod
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module github.com/kendru/darwin/go/depgraph
|
||||
|
||||
go 1.16
|
||||
|
||||
require github.com/stretchr/testify v1.7.0
|
11
vendor/github.com/kendru/darwin/go/depgraph/go.sum
generated
vendored
Normal file
11
vendor/github.com/kendru/darwin/go/depgraph/go.sum
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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=
|
6
vendor/github.com/philopon/go-toposort/.travis.yml
generated
vendored
6
vendor/github.com/philopon/go-toposort/.travis.yml
generated
vendored
@@ -1,6 +0,0 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- master
|
7
vendor/github.com/philopon/go-toposort/LICENSE
generated
vendored
7
vendor/github.com/philopon/go-toposort/LICENSE
generated
vendored
@@ -1,7 +0,0 @@
|
||||
Copyright 2017 Hirotomo Moriwaki
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
53
vendor/github.com/philopon/go-toposort/README.md
generated
vendored
53
vendor/github.com/philopon/go-toposort/README.md
generated
vendored
@@ -1,53 +0,0 @@
|
||||
go-toposort
|
||||
==
|
||||
[](https://travis-ci.org/philopon/go-toposort)
|
||||
[](https://godoc.org/github.com/philopon/go-toposort)
|
||||
|
||||
deterministic topological sort implementation for golang
|
||||
|
||||
Example
|
||||
--
|
||||
|
||||
```.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
toposort "github.com/philopon/go-toposort"
|
||||
)
|
||||
|
||||
func main() {
|
||||
graph := toposort.NewGraph(8)
|
||||
graph.AddNodes("2", "3", "5", "7", "8", "9", "10", "11")
|
||||
|
||||
graph.AddEdge("7", "8")
|
||||
graph.AddEdge("7", "11")
|
||||
|
||||
graph.AddEdge("5", "11")
|
||||
|
||||
graph.AddEdge("3", "8")
|
||||
graph.AddEdge("3", "10")
|
||||
|
||||
graph.AddEdge("11", "2")
|
||||
graph.AddEdge("11", "9")
|
||||
graph.AddEdge("11", "10")
|
||||
|
||||
graph.AddEdge("8", "9")
|
||||
|
||||
result, ok := graph.Toposort()
|
||||
if !ok {
|
||||
panic("cycle detected")
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
[3 5 7 8 11 2 9 10]
|
||||
```
|
||||
|
||||
License
|
||||
--
|
||||
MIT
|
101
vendor/github.com/philopon/go-toposort/toposort.go
generated
vendored
101
vendor/github.com/philopon/go-toposort/toposort.go
generated
vendored
@@ -1,101 +0,0 @@
|
||||
package toposort
|
||||
|
||||
type Graph struct {
|
||||
nodes []string
|
||||
outputs map[string]map[string]int
|
||||
inputs map[string]int
|
||||
}
|
||||
|
||||
func NewGraph(cap int) *Graph {
|
||||
return &Graph{
|
||||
nodes: make([]string, 0, cap),
|
||||
inputs: make(map[string]int),
|
||||
outputs: make(map[string]map[string]int),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) AddNode(name string) bool {
|
||||
g.nodes = append(g.nodes, name)
|
||||
|
||||
if _, ok := g.outputs[name]; ok {
|
||||
return false
|
||||
}
|
||||
g.outputs[name] = make(map[string]int)
|
||||
g.inputs[name] = 0
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *Graph) AddNodes(names ...string) bool {
|
||||
for _, name := range names {
|
||||
if ok := g.AddNode(name); !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *Graph) AddEdge(from, to string) bool {
|
||||
m, ok := g.outputs[from]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
m[to] = len(m) + 1
|
||||
g.inputs[to]++
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *Graph) unsafeRemoveEdge(from, to string) {
|
||||
delete(g.outputs[from], to)
|
||||
g.inputs[to]--
|
||||
}
|
||||
|
||||
func (g *Graph) RemoveEdge(from, to string) bool {
|
||||
if _, ok := g.outputs[from]; !ok {
|
||||
return false
|
||||
}
|
||||
g.unsafeRemoveEdge(from, to)
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *Graph) Toposort() ([]string, bool) {
|
||||
L := make([]string, 0, len(g.nodes))
|
||||
S := make([]string, 0, len(g.nodes))
|
||||
|
||||
for _, n := range g.nodes {
|
||||
if g.inputs[n] == 0 {
|
||||
S = append(S, n)
|
||||
}
|
||||
}
|
||||
|
||||
for len(S) > 0 {
|
||||
var n string
|
||||
n, S = S[0], S[1:]
|
||||
L = append(L, n)
|
||||
|
||||
ms := make([]string, len(g.outputs[n]))
|
||||
for m, i := range g.outputs[n] {
|
||||
ms[i-1] = m
|
||||
}
|
||||
|
||||
for _, m := range ms {
|
||||
g.unsafeRemoveEdge(n, m)
|
||||
|
||||
if g.inputs[m] == 0 {
|
||||
S = append(S, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
N := 0
|
||||
for _, v := range g.inputs {
|
||||
N += v
|
||||
}
|
||||
|
||||
if N > 0 {
|
||||
return L, false
|
||||
}
|
||||
|
||||
return L, true
|
||||
}
|
6
vendor/modules.txt
vendored
6
vendor/modules.txt
vendored
@@ -257,6 +257,9 @@ github.com/ipfs/go-log/v2
|
||||
# github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3
|
||||
## explicit
|
||||
github.com/jinzhu/copier
|
||||
# github.com/kendru/darwin/go/depgraph v0.0.0-20220319173517-8abc3541da93
|
||||
## explicit
|
||||
github.com/kendru/darwin/go/depgraph
|
||||
# github.com/klauspost/compress v1.15.1
|
||||
## explicit
|
||||
github.com/klauspost/compress
|
||||
@@ -368,9 +371,6 @@ github.com/pelletier/go-toml
|
||||
# github.com/peterbourgon/diskv v2.0.1+incompatible
|
||||
## explicit
|
||||
github.com/peterbourgon/diskv
|
||||
# github.com/philopon/go-toposort v0.0.0-20170620085441-9be86dbd762f
|
||||
## explicit
|
||||
github.com/philopon/go-toposort
|
||||
# github.com/pkg/errors v0.9.1
|
||||
## explicit
|
||||
github.com/pkg/errors
|
||||
|
Reference in New Issue
Block a user