Skip to content

Refactoring of LibraryManager libraries directory handling. #2477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions commands/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,11 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
for _, pack := range pme.GetPackages() {
for _, platform := range pack.Platforms {
if platformRelease := pme.GetInstalledPlatformRelease(platform); platformRelease != nil {
lm.AddPlatformReleaseLibrariesDir(platformRelease, libraries.PlatformBuiltIn)
lm.AddLibrariesDir(&librariesmanager.LibrariesDir{
PlatformRelease: platformRelease,
Path: platformRelease.GetLibrariesDir(),
Location: libraries.PlatformBuiltIn,
})
}
}
}
Expand All @@ -324,11 +328,17 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
if profile == nil {
// Add directories of libraries bundled with IDE
if bundledLibsDir := configuration.IDEBuiltinLibrariesDir(configuration.Settings); bundledLibsDir != nil {
lm.AddLibrariesDir(bundledLibsDir, libraries.IDEBuiltIn)
lm.AddLibrariesDir(&librariesmanager.LibrariesDir{
Path: bundledLibsDir,
Location: libraries.IDEBuiltIn,
})
}

// Add libraries directory from config file
lm.AddLibrariesDir(configuration.LibrariesDir(configuration.Settings), libraries.User)
lm.AddLibrariesDir(&librariesmanager.LibrariesDir{
Path: configuration.LibrariesDir(configuration.Settings),
Location: libraries.User,
})
} else {
// Load libraries required for profile
for _, libraryRef := range profile.Libraries {
Expand Down Expand Up @@ -368,7 +378,10 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
taskCallback(&rpc.TaskProgress{Completed: true})
}

lm.AddLibrariesDir(libRoot, libraries.User)
lm.AddLibrariesDir(&librariesmanager.LibrariesDir{
Path: libRoot,
Location: libraries.User,
})
}
}

Expand Down Expand Up @@ -412,11 +425,7 @@ func UpdateLibrariesIndex(ctx context.Context, req *rpc.UpdateLibrariesIndexRequ
}
defer tmp.RemoveAll()

indexResource := resources.IndexResource{
URL: librariesmanager.LibraryIndexWithSignatureArchiveURL,
EnforceSignatureVerification: true,
}
if err := indexResource.Download(lm.IndexFile.Parent(), downloadCB); err != nil {
if err := globals.LibrariesIndexResource.Download(lm.IndexFile.Parent(), downloadCB); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion commands/lib/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func LibraryDownload(ctx context.Context, req *rpc.LibraryDownloadRequest, downl

logrus.Info("Preparing download")

lib, err := findLibraryIndexRelease(lm, req)
lib, err := findLibraryIndexRelease(lm.Index, req)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion commands/lib/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa
// Find the libReleasesToInstall to install
libReleasesToInstall := map[*librariesindex.Release]*librariesmanager.LibraryInstallPlan{}
for _, lib := range toInstall {
libRelease, err := findLibraryIndexRelease(lm, &rpc.LibraryInstallRequest{
libRelease, err := findLibraryIndexRelease(lm.Index, &rpc.LibraryInstallRequest{
Name: lib.GetName(),
Version: lib.GetVersionRequired(),
})
Expand Down
2 changes: 1 addition & 1 deletion commands/lib/resolve_deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func LibraryResolveDependencies(ctx context.Context, req *rpc.LibraryResolveDepe
}

// Search the requested lib
reqLibRelease, err := findLibraryIndexRelease(lm, req)
reqLibRelease, err := findLibraryIndexRelease(lm.Index, req)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion commands/lib/uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func LibraryUninstall(ctx context.Context, req *rpc.LibraryUninstallRequest, tas
return err
}

ref, err := createLibIndexReference(lm, req)
ref, err := createLibIndexReference(req)
if err != nil {
return &cmderrors.InvalidLibraryError{Cause: err}
}
Expand Down
9 changes: 4 additions & 5 deletions commands/lib/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@ import (
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/commands/cmderrors"
"github.com/arduino/arduino-cli/internal/arduino/libraries/librariesindex"
"github.com/arduino/arduino-cli/internal/arduino/libraries/librariesmanager"
)

type libraryReferencer interface {
commands.Versioned
GetName() string
}

func createLibIndexReference(lm *librariesmanager.LibrariesManager, req libraryReferencer) (*librariesindex.Reference, error) {
func createLibIndexReference(req libraryReferencer) (*librariesindex.Reference, error) {
version, err := commands.ParseVersion(req)
if err != nil {
return nil, &cmderrors.InvalidVersionError{Cause: err}
Expand All @@ -36,12 +35,12 @@ func createLibIndexReference(lm *librariesmanager.LibrariesManager, req libraryR
return &librariesindex.Reference{Name: req.GetName(), Version: version}, nil
}

func findLibraryIndexRelease(lm *librariesmanager.LibrariesManager, req libraryReferencer) (*librariesindex.Release, error) {
ref, err := createLibIndexReference(lm, req)
func findLibraryIndexRelease(li *librariesindex.Index, req libraryReferencer) (*librariesindex.Release, error) {
ref, err := createLibIndexReference(req)
if err != nil {
return nil, err
}
lib := lm.Index.FindRelease(ref)
lib := li.FindRelease(ref)
if lib == nil {
return nil, &cmderrors.LibraryNotFoundError{Library: ref.String()}
}
Expand Down
37 changes: 26 additions & 11 deletions internal/arduino/builder/internal/detector/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -608,20 +608,42 @@ func LibrariesLoader(
if err := builtInLibrariesFolders.ToAbs(); err != nil {
return nil, nil, nil, err
}
lm.AddLibrariesDir(builtInLibrariesFolders, libraries.IDEBuiltIn)
lm.AddLibrariesDir(&librariesmanager.LibrariesDir{
Path: builtInLibrariesFolders,
Location: libraries.IDEBuiltIn,
})
}

if actualPlatform != targetPlatform {
lm.AddPlatformReleaseLibrariesDir(actualPlatform, libraries.ReferencedPlatformBuiltIn)
lm.AddLibrariesDir(&librariesmanager.LibrariesDir{
PlatformRelease: actualPlatform,
Path: actualPlatform.GetLibrariesDir(),
Location: libraries.ReferencedPlatformBuiltIn,
})
}
lm.AddPlatformReleaseLibrariesDir(targetPlatform, libraries.PlatformBuiltIn)
lm.AddLibrariesDir(&librariesmanager.LibrariesDir{
PlatformRelease: targetPlatform,
Path: targetPlatform.GetLibrariesDir(),
Location: libraries.PlatformBuiltIn,
})

librariesFolders := otherLibrariesDirs
if err := librariesFolders.ToAbs(); err != nil {
return nil, nil, nil, err
}
for _, folder := range librariesFolders {
lm.AddLibrariesDir(folder, libraries.User)
lm.AddLibrariesDir(&librariesmanager.LibrariesDir{
Path: folder,
Location: libraries.User, // XXX: Should be libraries.Unmanaged?
})
}

for _, dir := range libraryDirs {
lm.AddLibrariesDir(&librariesmanager.LibrariesDir{
Path: dir,
Location: libraries.Unmanaged,
IsSingleLibrary: true,
})
}

for _, status := range lm.RescanLibraries() {
Expand All @@ -633,13 +655,6 @@ func LibrariesLoader(
// When we're gonna refactor the legacy package this will be gone.
verboseOut.Write([]byte(status.Message()))
}

for _, dir := range libraryDirs {
// Libraries specified this way have top priority
if err := lm.LoadLibraryFromDir(dir, libraries.Unmanaged); err != nil {
return nil, nil, nil, err
}
}
}

resolver := librariesresolver.NewCppResolver()
Expand Down
15 changes: 15 additions & 0 deletions internal/arduino/globals/globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@

package globals

import (
"net/url"

"github.com/arduino/arduino-cli/internal/arduino/resources"
)

var (
// MainFileValidExtension is the extension that must be used for files in new sketches
MainFileValidExtension = ".ino"
Expand Down Expand Up @@ -63,4 +69,13 @@ var (

// DefaultIndexURL is the default index url
DefaultIndexURL = "https://downloads.arduino.cc/packages/package_index.tar.bz2"

// LibrariesIndexURL is the URL where to get the libraries index.
LibrariesIndexURL, _ = url.Parse("https://downloads.arduino.cc/libraries/library_index.tar.bz2")

// LibrariesIndexResource is the IndexResource to get the libraries index.
LibrariesIndexResource = resources.IndexResource{
URL: LibrariesIndexURL,
EnforceSignatureVerification: true,
}
)
32 changes: 0 additions & 32 deletions internal/arduino/libraries/librariesmanager/download.go

This file was deleted.

87 changes: 29 additions & 58 deletions internal/arduino/libraries/librariesmanager/librariesmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type LibrariesDir struct {
Path *paths.Path
Location libraries.LibraryLocation
PlatformRelease *cores.PlatformRelease
IsSingleLibrary bool // true if Path points directly to a library instad of a dir of libraries
}

var tr = i18n.Tr
Expand Down Expand Up @@ -102,46 +103,28 @@ func (lm *LibrariesManager) LoadIndex() error {
// AddLibrariesDir adds path to the list of directories
// to scan when searching for libraries. If a path is already
// in the list it is ignored.
func (lm *LibrariesManager) AddLibrariesDir(path *paths.Path, location libraries.LibraryLocation) {
for _, dir := range lm.LibrariesDir {
if dir.Path.EquivalentTo(path) {
return
}
}
logrus.WithField("dir", path).WithField("location", location.String()).Info("Adding libraries dir")
lm.LibrariesDir = append(lm.LibrariesDir, &LibrariesDir{
Path: path,
Location: location,
})
}

// AddPlatformReleaseLibrariesDir add the libraries directory in the
// specified PlatformRelease to the list of directories to scan when
// searching for libraries.
func (lm *LibrariesManager) AddPlatformReleaseLibrariesDir(plaftormRelease *cores.PlatformRelease, location libraries.LibraryLocation) {
path := plaftormRelease.GetLibrariesDir()
if path == nil {
func (lm *LibrariesManager) AddLibrariesDir(libDir *LibrariesDir) {
if libDir.Path == nil {
return
}
for _, dir := range lm.LibrariesDir {
if dir.Path.EquivalentTo(path) {
if dir.Path.EquivalentTo(libDir.Path) {
return
}
}
logrus.WithField("dir", path).WithField("location", location.String()).Info("Adding libraries dir")
lm.LibrariesDir = append(lm.LibrariesDir, &LibrariesDir{
Path: path,
Location: location,
PlatformRelease: plaftormRelease,
})
logrus.WithField("dir", libDir.Path).
WithField("location", libDir.Location.String()).
WithField("isSingleLibrary", libDir.IsSingleLibrary).
Info("Adding libraries dir")
lm.LibrariesDir = append(lm.LibrariesDir, libDir)
}

// RescanLibraries reload all installed libraries in the system.
func (lm *LibrariesManager) RescanLibraries() []*status.Status {
lm.clearLibraries()
statuses := []*status.Status{}
for _, dir := range lm.LibrariesDir {
if errs := lm.LoadLibrariesFromDir(dir); len(errs) > 0 {
if errs := lm.loadLibrariesFromDir(dir); len(errs) > 0 {
statuses = append(statuses, errs...)
}
}
Expand All @@ -164,22 +147,29 @@ func (lm *LibrariesManager) getLibrariesDir(installLocation libraries.LibraryLoc
}
}

// LoadLibrariesFromDir loads all libraries in the given directory. Returns
// loadLibrariesFromDir loads all libraries in the given directory. Returns
// nil if the directory doesn't exists.
func (lm *LibrariesManager) LoadLibrariesFromDir(librariesDir *LibrariesDir) []*status.Status {
func (lm *LibrariesManager) loadLibrariesFromDir(librariesDir *LibrariesDir) []*status.Status {
statuses := []*status.Status{}
subDirs, err := librariesDir.Path.ReadDir()
if os.IsNotExist(err) {
return statuses
}
if err != nil {
s := status.Newf(codes.FailedPrecondition, tr("reading dir %[1]s: %[2]s"), librariesDir.Path, err)
return append(statuses, s)

var libDirs paths.PathList
if librariesDir.IsSingleLibrary {
libDirs.Add(librariesDir.Path)
} else {
d, err := librariesDir.Path.ReadDir()
if os.IsNotExist(err) {
return statuses
}
if err != nil {
s := status.Newf(codes.FailedPrecondition, tr("reading dir %[1]s: %[2]s"), librariesDir.Path, err)
return append(statuses, s)
}
d.FilterDirs()
d.FilterOutHiddenFiles()
libDirs = d
}
subDirs.FilterDirs()
subDirs.FilterOutHiddenFiles()

for _, subDir := range subDirs {
for _, subDir := range libDirs {
library, err := libraries.Load(subDir, librariesDir.Location)
if err != nil {
s := status.Newf(codes.Internal, tr("loading library from %[1]s: %[2]s"), subDir, err)
Expand All @@ -195,25 +185,6 @@ func (lm *LibrariesManager) LoadLibrariesFromDir(librariesDir *LibrariesDir) []*
return statuses
}

// LoadLibraryFromDir loads one single library from the libRootDir.
// libRootDir must point to the root of a valid library.
// An error is returned if the path doesn't exist or loading of the library fails.
func (lm *LibrariesManager) LoadLibraryFromDir(libRootDir *paths.Path, location libraries.LibraryLocation) error {
if libRootDir.NotExist() {
return fmt.Errorf(tr("library path does not exist: %s"), libRootDir)
}

library, err := libraries.Load(libRootDir, location)
if err != nil {
return fmt.Errorf(tr("loading library from %[1]s: %[2]s"), libRootDir, err)
}

alternatives := lm.Libraries[library.Name]
alternatives.Add(library)
lm.Libraries[library.Name] = alternatives
return nil
}

// FindByReference return the installed libraries matching the Reference
// name and version or, if the version is nil, the libraries installed
// in the installLocation.
Expand Down