Skip to content

Commit 0381aa5

Browse files
authored
Library update/install with --no-overwrite will perform the update if it's possible to keep already installed dependencies at their current version (#2431)
* Updated semver library * Improved behaviour of 'lib install --no-overwrite' flag Previously the --no-overwrite flag would fail to install if a library dependency was already installed but not at the latest version. After this change the already present library may be accepted as a dependency if it match the version constraints of the installed library. * Fixed integration test * Added integration test * Always use 'installed' version if available * Allow a bit more time for slow CI
1 parent af0cc74 commit 0381aa5

File tree

14 files changed

+423
-319
lines changed

14 files changed

+423
-319
lines changed

.licenses/go/go.bug.st/relaxed-semver.dep.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: go.bug.st/relaxed-semver
3-
version: v0.11.0
3+
version: v0.12.0
44
type: go
55
summary:
66
homepage: https://pkg.go.dev/go.bug.st/relaxed-semver

arduino/libraries/librariesindex/index.go

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type Library struct {
4444
type Release struct {
4545
Author string
4646
Version *semver.Version
47-
Dependencies []semver.Dependency
47+
Dependencies []*Dependency
4848
Maintainer string
4949
Sentence string
5050
Paragraph string
@@ -85,7 +85,7 @@ func (r *Release) GetVersion() *semver.Version {
8585
}
8686

8787
// GetDependencies returns the dependencies of this library.
88-
func (r *Release) GetDependencies() []semver.Dependency {
88+
func (r *Release) GetDependencies() []*Dependency {
8989
return r.Dependencies
9090
}
9191

@@ -144,31 +144,31 @@ func (idx *Index) FindLibraryUpdate(lib *libraries.Library) *Release {
144144
return nil
145145
}
146146

147-
// ResolveDependencies returns the dependencies of a library release.
148-
func (idx *Index) ResolveDependencies(lib *Release) []*Release {
149-
// Box lib index *Release to be digested by dep-resolver
150-
// (TODO: There is a better use of golang interfaces to avoid this?)
151-
allReleases := map[string]semver.Releases{}
152-
for _, indexLib := range idx.Libraries {
153-
releases := semver.Releases{}
147+
// ResolveDependencies resolve the dependencies of a library release and returns a
148+
// possible solution (the set of library releases to install together with the library).
149+
// An optional "override" releases may be passed if we want to exclude the same
150+
// libraries from the index (for example if we want to keep an installed library).
151+
func (idx *Index) ResolveDependencies(lib *Release, overrides []*Release) []*Release {
152+
resolver := semver.NewResolver[*Release, *Dependency]()
153+
154+
overridden := map[string]bool{}
155+
for _, override := range overrides {
156+
resolver.AddRelease(override)
157+
overridden[override.GetName()] = true
158+
}
159+
160+
// Create and populate the library resolver
161+
for libName, indexLib := range idx.Libraries {
162+
if _, ok := overridden[libName]; ok {
163+
continue
164+
}
154165
for _, indexLibRelease := range indexLib.Releases {
155-
releases = append(releases, indexLibRelease)
166+
resolver.AddRelease(indexLibRelease)
156167
}
157-
allReleases[indexLib.Name] = releases
158168
}
159169

160170
// Perform lib resolution
161-
archive := &semver.Archive{
162-
Releases: allReleases,
163-
}
164-
deps := archive.Resolve(lib)
165-
166-
// Unbox resolved deps back into *Release
167-
res := []*Release{}
168-
for _, dep := range deps {
169-
res = append(res, dep.(*Release))
170-
}
171-
return res
171+
return resolver.Resolve(lib)
172172
}
173173

174174
// Versions returns an array of all versions available of the library

arduino/libraries/librariesindex/index_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func TestIndexer(t *testing.T) {
9090
rtcInexistent2 := index.FindLibraryUpdate(&libraries.Library{Name: "RTCZero-blah", Version: semver.MustParse("1.0.0")})
9191
require.Nil(t, rtcInexistent2)
9292

93-
resolve1 := index.ResolveDependencies(alp.Releases["1.2.1"])
93+
resolve1 := index.ResolveDependencies(alp.Releases["1.2.1"], nil)
9494
require.Len(t, resolve1, 2)
9595
require.Contains(t, resolve1, alp.Releases["1.2.1"])
9696
require.Contains(t, resolve1, rtc.Releases["1.6.0"])
@@ -108,7 +108,7 @@ func TestIndexer(t *testing.T) {
108108
require.NotNil(t, http040)
109109
require.Equal(t, "[email protected]", http040.String())
110110

111-
resolve2 := index.ResolveDependencies(oauth010)
111+
resolve2 := index.ResolveDependencies(oauth010, nil)
112112
require.Len(t, resolve2, 4)
113113
require.Contains(t, resolve2, oauth010)
114114
require.Contains(t, resolve2, eccx135)

arduino/libraries/librariesindex/json.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ func (indexLib *indexRelease) extractReleaseIn(library *Library) {
126126
}
127127
}
128128

129-
func (indexLib *indexRelease) extractDependencies() []semver.Dependency {
130-
res := []semver.Dependency{}
129+
func (indexLib *indexRelease) extractDependencies() []*Dependency {
130+
res := []*Dependency{}
131131
if indexLib.Dependencies == nil || len(indexLib.Dependencies) == 0 {
132132
return res
133133
}

arduino/libraries/librariesmanager/librariesmanager.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,20 @@ func (lm *LibrariesManager) FindByReference(libRef *librariesindex.Reference, in
225225
return alternatives.FilterByVersionAndInstallLocation(libRef.Version, installLocation)
226226
}
227227

228+
// FindAllInstalled returns all the installed libraries
229+
func (lm *LibrariesManager) FindAllInstalled() libraries.List {
230+
var res libraries.List
231+
for _, libAlternatives := range lm.Libraries {
232+
for _, libRelease := range libAlternatives {
233+
if libRelease.InstallDir == nil {
234+
continue
235+
}
236+
res.Add(libRelease)
237+
}
238+
}
239+
return res
240+
}
241+
228242
func (lm *LibrariesManager) clearLibraries() {
229243
for k := range lm.Libraries {
230244
delete(lm.Libraries, k)

commands/lib/install.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa
4747
}
4848
} else {
4949
res, err := LibraryResolveDependencies(ctx, &rpc.LibraryResolveDependenciesRequest{
50-
Instance: req.GetInstance(),
51-
Name: req.GetName(),
52-
Version: req.GetVersion(),
50+
Instance: req.GetInstance(),
51+
Name: req.GetName(),
52+
Version: req.GetVersion(),
53+
DoNotUpdateInstalledLibraries: req.GetNoOverwrite(),
5354
})
5455
if err != nil {
5556
return err

commands/lib/resolve_deps.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ import (
2222

2323
"github.com/arduino/arduino-cli/arduino"
2424
"github.com/arduino/arduino-cli/arduino/libraries"
25+
"github.com/arduino/arduino-cli/arduino/libraries/librariesindex"
2526
"github.com/arduino/arduino-cli/commands/internal/instances"
2627
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
28+
semver "go.bug.st/relaxed-semver"
2729
)
2830

2931
// LibraryResolveDependencies FIXMEDOC
@@ -46,7 +48,21 @@ func LibraryResolveDependencies(ctx context.Context, req *rpc.LibraryResolveDepe
4648
}
4749

4850
// Resolve all dependencies...
49-
deps := lm.Index.ResolveDependencies(reqLibRelease)
51+
var overrides []*librariesindex.Release
52+
if req.GetDoNotUpdateInstalledLibraries() {
53+
libs := lm.FindAllInstalled()
54+
libs = libs.FilterByVersionAndInstallLocation(nil, libraries.User)
55+
for _, lib := range libs {
56+
release := lm.Index.FindRelease(&librariesindex.Reference{
57+
Name: lib.Name,
58+
Version: lib.Version,
59+
})
60+
if release != nil {
61+
overrides = append(overrides, release)
62+
}
63+
}
64+
}
65+
deps := lm.Index.ResolveDependencies(reqLibRelease, overrides)
5066

5167
// If no solution has been found
5268
if len(deps) == 0 {
@@ -65,14 +81,19 @@ func LibraryResolveDependencies(ctx context.Context, req *rpc.LibraryResolveDepe
6581
res := []*rpc.LibraryDependencyStatus{}
6682
for _, dep := range deps {
6783
// ...and add information on currently installed versions of the libraries
68-
installed := ""
84+
var installed *semver.Version
85+
required := dep.GetVersion()
6986
if installedLib, has := installedLibs[dep.GetName()]; has {
70-
installed = installedLib.Version.String()
87+
installed = installedLib.Version
88+
if installed != nil && required != nil && installed.Equal(required) {
89+
// avoid situations like installed=0.53 and required=0.53.0
90+
required = installed
91+
}
7192
}
7293
res = append(res, &rpc.LibraryDependencyStatus{
7394
Name: dep.GetName(),
74-
VersionRequired: dep.GetVersion().String(),
75-
VersionInstalled: installed,
95+
VersionRequired: required.String(),
96+
VersionInstalled: installed.String(),
7697
})
7798
}
7899
sort.Slice(res, func(i, j int) bool {

commands/lib/search.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func getLibraryParameters(rel *librariesindex.Release) *rpc.LibraryRelease {
118118
}
119119
}
120120

121-
func getLibraryDependenciesParameter(deps []semver.Dependency) []*rpc.LibraryDependency {
121+
func getLibraryDependenciesParameter(deps []*librariesindex.Dependency) []*rpc.LibraryDependency {
122122
res := []*rpc.LibraryDependency{}
123123
for _, dep := range deps {
124124
res = append(res, &rpc.LibraryDependency{

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ require (
3636
github.com/xeipuuv/gojsonschema v1.2.0
3737
go.bug.st/cleanup v1.0.0
3838
go.bug.st/downloader/v2 v2.1.1
39-
go.bug.st/relaxed-semver v0.11.0
39+
go.bug.st/relaxed-semver v0.12.0
4040
go.bug.st/serial v1.6.1
4141
go.bug.st/testifyjson v1.1.1
4242
golang.org/x/term v0.14.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,8 @@ go.bug.st/cleanup v1.0.0/go.mod h1:EqVmTg2IBk4znLbPD28xne3abjsJftMdqqJEjhn70bk=
455455
go.bug.st/downloader/v2 v2.1.1 h1:nyqbUizo3E2IxCCm4YFac4FtSqqFpqWP+Aae5GCMuw4=
456456
go.bug.st/downloader/v2 v2.1.1/go.mod h1:VZW2V1iGKV8rJL2ZEGIDzzBeKowYv34AedJz13RzVII=
457457
go.bug.st/relaxed-semver v0.9.0/go.mod h1:ug0/W/RPYUjliE70Ghxg77RDHmPxqpo7SHV16ijss7Q=
458-
go.bug.st/relaxed-semver v0.11.0 h1:ngzpUlBEZ5F9hJnMZP55LIFbgX3bCztBBufMhJViAsY=
459-
go.bug.st/relaxed-semver v0.11.0/go.mod h1:rqPEm+790OTQlAdfSJSHWwpKOg3A8UyvAWMZxYkQivc=
458+
go.bug.st/relaxed-semver v0.12.0 h1:se8v3lTdAAFp68+/RS/0Y/nFdnpdzkP5ICY04SPau4E=
459+
go.bug.st/relaxed-semver v0.12.0/go.mod h1:Cpcbiig6Omwlq6bS7i3MQWiqS7W7HDd8CAnZFC40Cl0=
460460
go.bug.st/serial v1.3.2/go.mod h1:jDkjqASf/qSjmaOxHSHljwUQ6eHo/ZX/bxJLQqSlvZg=
461461
go.bug.st/serial v1.6.1 h1:VSSWmUxlj1T/YlRo2J104Zv3wJFrjHIl/T3NeruWAHY=
462462
go.bug.st/serial v1.6.1/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=

0 commit comments

Comments
 (0)