Skip to content

Commit 51573f2

Browse files
authored
[skip-changelog] refactoring: Added LibrariesManager.Clone() / Auto-scan libs on LibrariesManager.Build() (#2491)
* Added LibrariesManager.Clone() / Auto-scan libraries on LibrariesManager.Build() * Ensure AddLibrariesDir do not share input parameters * Fixed wrong loop... ooops
1 parent 2972ed8 commit 51573f2

File tree

5 files changed

+72
-54
lines changed

5 files changed

+72
-54
lines changed

Diff for: commands/instances.go

+8-13
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
308308
for _, pack := range pme.GetPackages() {
309309
for _, platform := range pack.Platforms {
310310
if platformRelease := pme.GetInstalledPlatformRelease(platform); platformRelease != nil {
311-
lmb.AddLibrariesDir(&librariesmanager.LibrariesDir{
311+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
312312
PlatformRelease: platformRelease,
313313
Path: platformRelease.GetLibrariesDir(),
314314
Location: libraries.PlatformBuiltIn,
@@ -336,14 +336,14 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
336336
if profile == nil {
337337
// Add directories of libraries bundled with IDE
338338
if bundledLibsDir := configuration.IDEBuiltinLibrariesDir(configuration.Settings); bundledLibsDir != nil {
339-
lmb.AddLibrariesDir(&librariesmanager.LibrariesDir{
339+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
340340
Path: bundledLibsDir,
341341
Location: libraries.IDEBuiltIn,
342342
})
343343
}
344344

345345
// Add libraries directory from config file
346-
lmb.AddLibrariesDir(&librariesmanager.LibrariesDir{
346+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
347347
Path: configuration.LibrariesDir(configuration.Settings),
348348
Location: libraries.User,
349349
})
@@ -383,23 +383,18 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
383383
taskCallback(&rpc.TaskProgress{Completed: true})
384384
}
385385

386-
lmb.AddLibrariesDir(&librariesmanager.LibrariesDir{
386+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
387387
Path: libRoot,
388388
Location: libraries.User,
389389
})
390390
}
391391
}
392392

393-
lm := lmb.Build()
393+
lm, libsLoadingWarnings := lmb.Build()
394394
_ = instances.SetLibraryManager(instance, lm) // should never fail
395-
396-
{
397-
lmi, release := lm.NewInstaller()
398-
for _, status := range lmi.RescanLibraries() {
399-
logrus.WithError(status.Err()).Warnf("Error loading library")
400-
// TODO: report as warning: responseError(err)
401-
}
402-
release()
395+
for _, status := range libsLoadingWarnings {
396+
logrus.WithError(status.Err()).Warnf("Error loading library")
397+
// TODO: report as warning: responseError(err)
403398
}
404399

405400
// Refreshes the locale used, this will change the

Diff for: commands/internal/instances/instances.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,12 @@ func Create(dataDir, packagesDir, downloadsDir *paths.Path, extraUserAgent ...st
126126
}
127127
tempDir := dataDir.Join("tmp")
128128

129+
pm := packagemanager.NewBuilder(dataDir, packagesDir, downloadsDir, tempDir, userAgent).Build()
130+
lm, _ := librariesmanager.NewBuilder().Build()
131+
129132
instance := &coreInstance{
130-
pm: packagemanager.NewBuilder(dataDir, packagesDir, downloadsDir, tempDir, userAgent).Build(),
131-
lm: librariesmanager.NewBuilder().Build(),
133+
pm: pm,
134+
lm: lm,
132135
li: librariesindex.EmptyIndex,
133136
}
134137

Diff for: internal/arduino/builder/internal/detector/detector.go

+16-20
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ func LibrariesLoader(
598598
if useCachedLibrariesResolution {
599599
// Since we are using the cached libraries resolution
600600
// the library manager is not needed.
601-
lm = librariesmanager.NewBuilder().Build()
601+
lm, _ = librariesmanager.NewBuilder().Build()
602602
}
603603
if librariesManager == nil {
604604
lmb := librariesmanager.NewBuilder()
@@ -608,20 +608,20 @@ func LibrariesLoader(
608608
if err := builtInLibrariesFolders.ToAbs(); err != nil {
609609
return nil, nil, nil, err
610610
}
611-
lmb.AddLibrariesDir(&librariesmanager.LibrariesDir{
611+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
612612
Path: builtInLibrariesFolders,
613613
Location: libraries.IDEBuiltIn,
614614
})
615615
}
616616

617617
if actualPlatform != targetPlatform {
618-
lmb.AddLibrariesDir(&librariesmanager.LibrariesDir{
618+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
619619
PlatformRelease: actualPlatform,
620620
Path: actualPlatform.GetLibrariesDir(),
621621
Location: libraries.ReferencedPlatformBuiltIn,
622622
})
623623
}
624-
lmb.AddLibrariesDir(&librariesmanager.LibrariesDir{
624+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
625625
PlatformRelease: targetPlatform,
626626
Path: targetPlatform.GetLibrariesDir(),
627627
Location: libraries.PlatformBuiltIn,
@@ -632,35 +632,31 @@ func LibrariesLoader(
632632
return nil, nil, nil, err
633633
}
634634
for _, folder := range librariesFolders {
635-
lmb.AddLibrariesDir(&librariesmanager.LibrariesDir{
635+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
636636
Path: folder,
637637
Location: libraries.User, // XXX: Should be libraries.Unmanaged?
638638
})
639639
}
640640

641641
for _, dir := range libraryDirs {
642-
lmb.AddLibrariesDir(&librariesmanager.LibrariesDir{
642+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
643643
Path: dir,
644644
Location: libraries.Unmanaged,
645645
IsSingleLibrary: true,
646646
})
647647
}
648648

649-
lm = lmb.Build()
650-
651-
{
652-
lmi, release := lm.NewInstaller()
653-
for _, status := range lmi.RescanLibraries() {
654-
// With the refactoring of the initialization step of the CLI we changed how
655-
// errors are returned when loading platforms and libraries, that meant returning a list of
656-
// errors instead of a single one to enhance the experience for the user.
657-
// I have no intention right now to start a refactoring of the legacy package too, so
658-
// here's this shitty solution for now.
659-
// When we're gonna refactor the legacy package this will be gone.
660-
verboseOut.Write([]byte(status.Message()))
661-
}
662-
release()
649+
newLm, libsLoadingWarnings := lmb.Build()
650+
for _, status := range libsLoadingWarnings {
651+
// With the refactoring of the initialization step of the CLI we changed how
652+
// errors are returned when loading platforms and libraries, that meant returning a list of
653+
// errors instead of a single one to enhance the experience for the user.
654+
// I have no intention right now to start a refactoring of the legacy package too, so
655+
// here's this shitty solution for now.
656+
// When we're gonna refactor the legacy package this will be gone.
657+
verboseOut.Write([]byte(status.Message()))
663658
}
659+
lm = newLm
664660
}
665661

666662
allLibs := lm.FindAllInstalled()

Diff for: internal/arduino/libraries/librariesmanager/librariesmanager.go

+29-13
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ type LibrariesDir struct {
6565
Location libraries.LibraryLocation
6666
PlatformRelease *cores.PlatformRelease
6767
IsSingleLibrary bool // true if Path points directly to a library instad of a dir of libraries
68+
scanned bool
6869
}
6970

7071
var tr = i18n.Tr
@@ -95,14 +96,19 @@ func NewBuilder() *Builder {
9596
}
9697
}
9798

98-
// NewBuilder creates a Builder with the same configuration of this
99-
// LibrariesManager. A "commit" function callback is returned: calling
100-
// this function will write the new configuration into this LibrariesManager.
101-
func (lm *LibrariesManager) NewBuilder() (*Builder, func()) {
99+
// Clone creates a Builder starting with a copy of the same configuration
100+
// of this LibrariesManager. At the moment of the Build() only the added
101+
// libraries directories will be scanned, keeping the existing directories
102+
// "cached" to optimize scan. If you need to do a full rescan you must use
103+
// the RescanLibraries method of the Installer.
104+
func (lm *LibrariesManager) Clone() *Builder {
102105
lmb := NewBuilder()
103-
return lmb, func() {
104-
lmb.BuildIntoExistingLibrariesManager(lm)
106+
lmb.librariesDir = append(lmb.librariesDir, lm.librariesDir...)
107+
for libName, libAlternatives := range lm.libraries {
108+
// TODO: Maybe we should deep clone libAlternatives...
109+
lmb.libraries[libName] = append(lmb.libraries[libName], libAlternatives...)
105110
}
111+
return lmb
106112
}
107113

108114
// NewExplorer returns a new Explorer. The returned function must be called
@@ -120,10 +126,18 @@ func (lm *LibrariesManager) NewInstaller() (*Installer, func()) {
120126
}
121127

122128
// Build builds a new LibrariesManager.
123-
func (lmb *Builder) Build() *LibrariesManager {
129+
func (lmb *Builder) Build() (*LibrariesManager, []*status.Status) {
130+
var statuses []*status.Status
124131
res := &LibrariesManager{}
132+
for _, dir := range lmb.librariesDir {
133+
if !dir.scanned {
134+
if errs := lmb.loadLibrariesFromDir(dir); len(errs) > 0 {
135+
statuses = append(statuses, errs...)
136+
}
137+
}
138+
}
125139
lmb.BuildIntoExistingLibrariesManager(res)
126-
return res
140+
return res, statuses
127141
}
128142

129143
// BuildIntoExistingLibrariesManager will overwrite the given LibrariesManager instead
@@ -138,7 +152,7 @@ func (lmb *Builder) BuildIntoExistingLibrariesManager(old *LibrariesManager) {
138152
// AddLibrariesDir adds path to the list of directories
139153
// to scan when searching for libraries. If a path is already
140154
// in the list it is ignored.
141-
func (lmb *Builder) AddLibrariesDir(libDir *LibrariesDir) {
155+
func (lmb *Builder) AddLibrariesDir(libDir LibrariesDir) {
142156
if libDir.Path == nil {
143157
return
144158
}
@@ -151,7 +165,7 @@ func (lmb *Builder) AddLibrariesDir(libDir *LibrariesDir) {
151165
WithField("location", libDir.Location.String()).
152166
WithField("isSingleLibrary", libDir.IsSingleLibrary).
153167
Info("Adding libraries dir")
154-
lmb.librariesDir = append(lmb.librariesDir, libDir)
168+
lmb.librariesDir = append(lmb.librariesDir, &libDir)
155169
}
156170

157171
// RescanLibraries reload all installed libraries in the system.
@@ -184,9 +198,11 @@ func (lm *LibrariesManager) getLibrariesDir(installLocation libraries.LibraryLoc
184198

185199
// loadLibrariesFromDir loads all libraries in the given directory. Returns
186200
// nil if the directory doesn't exists.
187-
func (lmi *Installer) loadLibrariesFromDir(librariesDir *LibrariesDir) []*status.Status {
201+
func (lm *LibrariesManager) loadLibrariesFromDir(librariesDir *LibrariesDir) []*status.Status {
188202
statuses := []*status.Status{}
189203

204+
librariesDir.scanned = true
205+
190206
var libDirs paths.PathList
191207
if librariesDir.IsSingleLibrary {
192208
libDirs.Add(librariesDir.Path)
@@ -212,9 +228,9 @@ func (lmi *Installer) loadLibrariesFromDir(librariesDir *LibrariesDir) []*status
212228
continue
213229
}
214230
library.ContainerPlatform = librariesDir.PlatformRelease
215-
alternatives := lmi.libraries[library.Name]
231+
alternatives := lm.libraries[library.Name]
216232
alternatives.Add(library)
217-
lmi.libraries[library.Name] = alternatives
233+
lm.libraries[library.Name] = alternatives
218234
}
219235

220236
return statuses

Diff for: internal/arduino/libraries/librariesmanager/librariesmanager_test.go

+14-6
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,25 @@ import (
2121
"github.com/stretchr/testify/require"
2222
)
2323

24-
func Test_RescanLibrariesCallClear(t *testing.T) {
24+
func TestLibrariesBuilderScanCloneRescan(t *testing.T) {
2525
lmb := NewBuilder()
2626
lmb.libraries["testLibA"] = libraries.List{}
2727
lmb.libraries["testLibB"] = libraries.List{}
28-
lm := lmb.Build()
28+
lm, warns := lmb.Build()
29+
require.Empty(t, warns)
30+
require.Len(t, lm.libraries, 2)
2931

32+
// Cloning should keep existing libraries
33+
lm2, warns2 := lm.Clone().Build()
34+
require.Empty(t, warns2)
35+
require.Len(t, lm2.libraries, 2)
36+
37+
// Full rescan should update libs
3038
{
31-
lmi, release := lm.NewInstaller()
32-
lmi.RescanLibraries()
39+
lmi2, release := lm2.NewInstaller()
40+
lmi2.RescanLibraries()
3341
release()
3442
}
35-
36-
require.Len(t, lm.libraries, 0)
43+
require.Len(t, lm.libraries, 2) // Ensure deep-coping worked as expected...
44+
require.Len(t, lm2.libraries, 0)
3745
}

0 commit comments

Comments
 (0)