diff --git a/arduino/cores/packagemanager/loader.go b/arduino/cores/packagemanager/loader.go index f70111519e9..16bee8d7fd3 100644 --- a/arduino/cores/packagemanager/loader.go +++ b/arduino/cores/packagemanager/loader.go @@ -28,56 +28,46 @@ import ( "github.com/arduino/arduino-cli/configuration" "github.com/arduino/go-paths-helper" properties "github.com/arduino/go-properties-orderedmap" + "github.com/pkg/errors" semver "go.bug.st/relaxed-semver" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) // LoadHardware read all plaforms from the configured paths -func (pm *PackageManager) LoadHardware() []*status.Status { - statuses := []*status.Status{} - dirs := configuration.HardwareDirectories(configuration.Settings) - if errs := pm.LoadHardwareFromDirectories(dirs); len(errs) > 0 { - statuses = append(statuses, errs...) - } +func (pm *PackageManager) LoadHardware() []error { + hardwareDirs := configuration.HardwareDirectories(configuration.Settings) + merr := pm.LoadHardwareFromDirectories(hardwareDirs) - dirs = configuration.BundleToolsDirectories(configuration.Settings) - if errs := pm.LoadToolsFromBundleDirectories(dirs); len(errs) > 0 { - statuses = append(statuses, errs...) - } - return statuses + bundleToolDirs := configuration.BundleToolsDirectories(configuration.Settings) + merr = append(merr, pm.LoadToolsFromBundleDirectories(bundleToolDirs)...) + + return merr } // LoadHardwareFromDirectories load plaforms from a set of directories -func (pm *PackageManager) LoadHardwareFromDirectories(hardwarePaths paths.PathList) []*status.Status { - statuses := []*status.Status{} +func (pm *PackageManager) LoadHardwareFromDirectories(hardwarePaths paths.PathList) []error { + var merr []error for _, path := range hardwarePaths { - if errs := pm.LoadHardwareFromDirectory(path); len(errs) > 0 { - statuses = append(statuses, errs...) - } + merr = append(merr, pm.LoadHardwareFromDirectory(path)...) } - return statuses + return merr } // LoadHardwareFromDirectory read a plaform from the path passed as parameter -func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []*status.Status { +func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error { + var merr []error pm.Log.Infof("Loading hardware from: %s", path) - statuses := []*status.Status{} if err := path.ToAbs(); err != nil { - s := status.Newf(codes.FailedPrecondition, tr("find abs path: %s"), err) - return append(statuses, s) + return append(merr, fmt.Errorf("%s: %w", tr("finding absolute path of %s", path), err)) } if path.IsNotDir() { - s := status.Newf(codes.FailedPrecondition, tr("%s is not a directory"), path) - return append(statuses, s) + return append(merr, errors.New(tr("%s is not a directory", path))) } // Scan subdirs packagersPaths, err := path.ReadDir() if err != nil { - s := status.Newf(codes.FailedPrecondition, tr("reading %[1]s directory: %[2]s"), path, err) - return append(statuses, s) + return append(merr, fmt.Errorf("%s: %w", tr("reading directory %s", path), err)) } packagersPaths.FilterOutHiddenFiles() packagersPaths.FilterDirs() @@ -106,8 +96,7 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []*status. // Follow symlinks err := packagerPath.FollowSymLink() // ex: .arduino15/packages/arduino/ if err != nil { - s := status.Newf(codes.Internal, tr("following possible symlink %[1]s: %[2]s"), path, err) - statuses = append(statuses, s) + merr = append(merr, fmt.Errorf("%s: %w", tr("following symlink %s", path), err)) continue } @@ -132,18 +121,14 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []*status. } targetPackage := pm.Packages.GetOrCreatePackage(packager) - if errs := pm.loadPlatforms(targetPackage, architectureParentPath); len(errs) > 0 { - statuses = append(statuses, errs...) - } + merr = append(merr, pm.loadPlatforms(targetPackage, architectureParentPath)...) // Check if we have tools to load, the directory structure is as follows: // - PACKAGER/tools/TOOL-NAME/TOOL-VERSION/... (ex: arduino/tools/bossac/1.7.0/...) toolsSubdirPath := packagerPath.Join("tools") if toolsSubdirPath.IsDir() { pm.Log.Infof("Checking existence of 'tools' path: %s", toolsSubdirPath) - if errs := pm.loadToolsFromPackage(targetPackage, toolsSubdirPath); len(errs) > 0 { - statuses = append(statuses, errs...) - } + merr = append(merr, pm.loadToolsFromPackage(targetPackage, toolsSubdirPath)...) } // If the Package does not contain Platforms or Tools we remove it since does not contain anything valuable if len(targetPackage.Platforms) == 0 && len(targetPackage.Tools) == 0 { @@ -151,21 +136,20 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []*status. } } - return statuses + return merr } // loadPlatforms load plaftorms from the specified directory assuming that they belongs // to the targetPackage object passed as parameter. // A list of gRPC Status error is returned for each Platform failed to load. -func (pm *PackageManager) loadPlatforms(targetPackage *cores.Package, packageDir *paths.Path) []*status.Status { +func (pm *PackageManager) loadPlatforms(targetPackage *cores.Package, packageDir *paths.Path) []error { pm.Log.Infof("Loading package %s from: %s", targetPackage.Name, packageDir) - statuses := []*status.Status{} + var merr []error platformsDirs, err := packageDir.ReadDir() if err != nil { - s := status.Newf(codes.FailedPrecondition, tr("reading directory %[1]s: %[2]s"), packageDir, err) - return append(statuses, s) + return append(merr, fmt.Errorf("%s: %w", tr("reading directory %s", packageDir), err)) } // A platform can only be inside a directory, thus we skip everything else. @@ -178,20 +162,20 @@ func (pm *PackageManager) loadPlatforms(targetPackage *cores.Package, packageDir continue } if err := pm.loadPlatform(targetPackage, platformPath); err != nil { - statuses = append(statuses, err) + merr = append(merr, err) } } - return statuses + return merr } // loadPlatform loads a single platform and all its installed releases given a platformPath. // platformPath must be a directory. // Returns a gRPC Status error in case of failures. -func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, platformPath *paths.Path) *status.Status { +func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, platformPath *paths.Path) error { // This is not a platform if platformPath.IsNotDir() { - return status.Newf(codes.NotFound, tr("path is not a platform directory: %s"), platformPath) + return errors.New(tr("path is not a platform directory: %s", platformPath)) } architecture := platformPath.Base() @@ -202,14 +186,14 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, platformPat // We identify them by checking where is the bords.txt file possibleBoardTxtPath := platformPath.Join("boards.txt") if exist, err := possibleBoardTxtPath.ExistCheck(); err != nil { - return status.Newf(codes.FailedPrecondition, tr("looking for boards.txt in %[1]s: %[2]s"), possibleBoardTxtPath, err) + return fmt.Errorf("%s: %w", tr("looking for boards.txt in %s", possibleBoardTxtPath), err) } else if exist { // case: ARCHITECTURE/boards.txt platformTxtPath := platformPath.Join("platform.txt") platformProperties, err := properties.SafeLoad(platformTxtPath.String()) if err != nil { - return status.Newf(codes.FailedPrecondition, tr("loading platform.txt: %v"), err) + return fmt.Errorf("%s: %w", tr("loading platform.txt"), err) } version := semver.MustParse(platformProperties.Get("version")) @@ -229,7 +213,7 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, platformPat // Parse the bundled index and merge to the general index index, err := pm.LoadPackageIndexFromFile(packageBundledIndexPath) if err != nil { - return status.Newf(codes.FailedPrecondition, tr("parsing IDE bundled index: %s"), err) + return fmt.Errorf("%s: %w", tr("parsing IDE bundled index"), err) } // Now export the bundled index in a temporary core.Packages to retrieve the bundled package version @@ -258,7 +242,7 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, platformPat pm.Log.Infof("Package is built-in") } if err := pm.loadPlatformRelease(release, platformPath); err != nil { - return status.Newf(codes.FailedPrecondition, tr("loading platform release %[1]s: %[2]s"), release, err) + return fmt.Errorf("%s: %w", tr("loading platform release %s", release), err) } pm.Log.WithField("platform", release).Infof("Loaded platform") @@ -268,25 +252,25 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, platformPat versionDirs, err := platformPath.ReadDir() if err != nil { - return status.Newf(codes.FailedPrecondition, tr("reading dir %[1]s: %[2]s"), platformPath, err) + return fmt.Errorf("%s: %w", tr("reading directory %s", platformPath), err) } versionDirs.FilterDirs() versionDirs.FilterOutHiddenFiles() for _, versionDir := range versionDirs { if exist, err := versionDir.Join("boards.txt").ExistCheck(); err != nil { - return status.Newf(codes.FailedPrecondition, tr("opening boards.txt: %s"), err) + return fmt.Errorf("%s: %w", tr("opening boards.txt"), err) } else if !exist { continue } version, err := semver.Parse(versionDir.Base()) if err != nil { - return status.Newf(codes.FailedPrecondition, tr("invalid version dir %[1]s: %[2]s"), versionDir, err) + return fmt.Errorf("%s: %w", tr("invalid version directory %s", versionDir), err) } platform := targetPackage.GetOrCreatePlatform(architecture) release := platform.GetOrCreateRelease(version) if err := pm.loadPlatformRelease(release, versionDir); err != nil { - return status.Newf(codes.FailedPrecondition, tr("loading platform release %[1]s: %[2]s"), release, err) + return fmt.Errorf("%s: %w", tr("loading platform release %s", release), err) } pm.Log.WithField("platform", release).Infof("Loaded platform") } @@ -605,14 +589,14 @@ func convertUploadToolsToPluggableDiscovery(props *properties.Map) { props.Merge(propsToAdd) } -func (pm *PackageManager) loadToolsFromPackage(targetPackage *cores.Package, toolsPath *paths.Path) []*status.Status { +func (pm *PackageManager) loadToolsFromPackage(targetPackage *cores.Package, toolsPath *paths.Path) []error { pm.Log.Infof("Loading tools from dir: %s", toolsPath) - statuses := []*status.Status{} + var merr []error + toolsPaths, err := toolsPath.ReadDir() if err != nil { - s := status.Newf(codes.FailedPrecondition, tr("reading directory %[1]s: %[2]s"), toolsPath, err) - return append(statuses, s) + return append(merr, fmt.Errorf("%s: %w", tr("reading directory %s", toolsPath), err)) } toolsPaths.FilterDirs() toolsPaths.FilterOutHiddenFiles() @@ -620,11 +604,10 @@ func (pm *PackageManager) loadToolsFromPackage(targetPackage *cores.Package, too name := toolPath.Base() tool := targetPackage.GetOrCreateTool(name) if err = pm.loadToolReleasesFromTool(tool, toolPath); err != nil { - s := status.Newf(codes.FailedPrecondition, tr("loading tool release in %[1]s: %[2]s"), toolPath, err) - statuses = append(statuses, s) + merr = append(merr, fmt.Errorf("%s: %w", tr("loading tool release in %s", toolPath), err)) } } - return statuses + return merr } func (pm *PackageManager) loadToolReleasesFromTool(tool *cores.Tool, toolPath *paths.Path) error { @@ -649,14 +632,14 @@ func (pm *PackageManager) loadToolReleasesFromTool(tool *cores.Tool, toolPath *p } // LoadToolsFromBundleDirectories FIXMEDOC -func (pm *PackageManager) LoadToolsFromBundleDirectories(dirs paths.PathList) []*status.Status { - statuses := []*status.Status{} +func (pm *PackageManager) LoadToolsFromBundleDirectories(dirs paths.PathList) []error { + var merr []error for _, dir := range dirs { if err := pm.LoadToolsFromBundleDirectory(dir); err != nil { - statuses = append(statuses, status.Newf(codes.FailedPrecondition, tr("loading bundled tools from %[1]s: %[2]s"), dir, err)) + merr = append(merr, fmt.Errorf("%s: %w", tr("loading bundled tools from %s", dir), err)) } } - return statuses + return merr } // LoadToolsFromBundleDirectory FIXMEDOC @@ -730,49 +713,44 @@ func (pm *PackageManager) LoadToolsFromBundleDirectory(toolsPath *paths.Path) er // * A PluggableDiscovery instance can't be created // * Tools required by the PlatformRelease cannot be found // * Command line to start PluggableDiscovery has malformed or mismatched quotes -func (pm *PackageManager) LoadDiscoveries() []*status.Status { - statuses := []*status.Status{} +func (pm *PackageManager) LoadDiscoveries() []error { + var merr []error for _, platform := range pm.InstalledPlatformReleases() { - statuses = append(statuses, pm.loadDiscoveries(platform)...) - } - if st := pm.loadBuiltinDiscoveries(); len(st) > 0 { - statuses = append(statuses, st...) + merr = append(merr, pm.loadDiscoveries(platform)...) } - return statuses + merr = append(merr, pm.loadBuiltinDiscoveries()...) + return merr } // loadDiscovery loads the discovery tool with id, if it cannot be found a non-nil status is returned -func (pm *PackageManager) loadDiscovery(id string) *status.Status { +func (pm *PackageManager) loadDiscovery(id string) error { tool := pm.GetTool(id) if tool == nil { - return status.Newf(codes.FailedPrecondition, tr("discovery not found: %s"), id) + return errors.New(tr("discovery %s not found", id)) } toolRelease := tool.GetLatestInstalled() if toolRelease == nil { - return status.Newf(codes.FailedPrecondition, tr("discovery not installed: %s"), id) + return errors.New(tr("discovery %s not installed", id)) } discoveryPath := toolRelease.InstallDir.Join(tool.Name).String() - d, err := discovery.New(id, discoveryPath) - if err != nil { - return status.Newf(codes.FailedPrecondition, tr("creating discovery: %s"), err) - } + d := discovery.New(id, discoveryPath) pm.discoveryManager.Add(d) return nil } // loadBuiltinDiscoveries loads the discovery tools that are part of the builtin package -func (pm *PackageManager) loadBuiltinDiscoveries() []*status.Status { - statuses := []*status.Status{} +func (pm *PackageManager) loadBuiltinDiscoveries() []error { + var merr []error for _, id := range []string{"builtin:serial-discovery", "builtin:mdns-discovery"} { - if st := pm.loadDiscovery(id); st != nil { - statuses = append(statuses, st) + if err := pm.loadDiscovery(id); err != nil { + merr = append(merr, err) } } - return statuses + return merr } -func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []*status.Status { - statuses := []*status.Status{} +func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []error { + var merr []error discoveryProperties := release.Properties.SubTree("pluggable_discovery") if discoveryProperties.Size() == 0 { @@ -790,8 +768,8 @@ func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []*sta // // If both indexed and unindexed properties are found the unindexed are ignored for _, id := range discoveryProperties.ExtractSubIndexLists("required") { - if st := pm.loadDiscovery(id); st != nil { - statuses = append(statuses, st) + if err := pm.loadDiscovery(id); err != nil { + merr = append(merr, err) } } @@ -807,7 +785,7 @@ func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []*sta var err error tools, err = pm.FindToolsRequiredFromPlatformRelease(release) if err != nil { - statuses = append(statuses, status.New(codes.Internal, err.Error())) + merr = append(merr, err) } } @@ -817,7 +795,7 @@ func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []*sta for discoveryID, props := range discoveryIDs { pattern, ok := props.GetOk("pattern") if !ok { - statuses = append(statuses, status.Newf(codes.FailedPrecondition, tr("can't find pattern for discovery with id %s"), discoveryID)) + merr = append(merr, errors.New(tr("can't find pattern for discovery with id %s", discoveryID))) continue } configuration := release.Properties.Clone() @@ -830,13 +808,12 @@ func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []*sta cmd := configuration.ExpandPropsInString(pattern) if cmdArgs, err := properties.SplitQuotedString(cmd, `"'`, true); err != nil { - statuses = append(statuses, status.New(codes.Internal, err.Error())) - } else if d, err := discovery.New(discoveryID, cmdArgs...); err != nil { - statuses = append(statuses, status.New(codes.Internal, err.Error())) + merr = append(merr, err) } else { + d := discovery.New(discoveryID, cmdArgs...) pm.discoveryManager.Add(d) } } - return statuses + return merr } diff --git a/arduino/cores/packagemanager/loader_test.go b/arduino/cores/packagemanager/loader_test.go index ecb9b892140..2666bf62dd8 100644 --- a/arduino/cores/packagemanager/loader_test.go +++ b/arduino/cores/packagemanager/loader_test.go @@ -140,10 +140,10 @@ func TestLoadDiscoveries(t *testing.T) { "pluggable_discovery.required": "arduino:ble-discovery", }) - errs := packageManager.LoadDiscoveries() - require.Len(t, errs, 2) - require.Equal(t, errs[0].Message(), "discovery not found: builtin:serial-discovery") - require.Equal(t, errs[1].Message(), "discovery not found: builtin:mdns-discovery") + err := packageManager.LoadDiscoveries() + require.Len(t, err, 2) + require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found") + require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found") discoveries := packageManager.DiscoveryManager().IDs() require.Len(t, discoveries, 1) require.Contains(t, discoveries, "arduino:ble-discovery") @@ -155,10 +155,10 @@ func TestLoadDiscoveries(t *testing.T) { "pluggable_discovery.required.1": "arduino:serial-discovery", }) - errs = packageManager.LoadDiscoveries() - require.Len(t, errs, 2) - require.Equal(t, errs[0].Message(), "discovery not found: builtin:serial-discovery") - require.Equal(t, errs[1].Message(), "discovery not found: builtin:mdns-discovery") + err = packageManager.LoadDiscoveries() + require.Len(t, err, 2) + require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found") + require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found") discoveries = packageManager.DiscoveryManager().IDs() require.Len(t, discoveries, 2) require.Contains(t, discoveries, "arduino:ble-discovery") @@ -172,10 +172,10 @@ func TestLoadDiscoveries(t *testing.T) { "pluggable_discovery.teensy.pattern": "\"{runtime.tools.teensy_ports.path}/hardware/tools/teensy_ports\" -J2", }) - errs = packageManager.LoadDiscoveries() - require.Len(t, errs, 2) - require.Equal(t, errs[0].Message(), "discovery not found: builtin:serial-discovery") - require.Equal(t, errs[1].Message(), "discovery not found: builtin:mdns-discovery") + err = packageManager.LoadDiscoveries() + require.Len(t, err, 2) + require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found") + require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found") discoveries = packageManager.DiscoveryManager().IDs() require.Len(t, discoveries, 3) require.Contains(t, discoveries, "arduino:ble-discovery") @@ -191,10 +191,10 @@ func TestLoadDiscoveries(t *testing.T) { "pluggable_discovery.teensy.pattern": "\"{runtime.tools.teensy_ports.path}/hardware/tools/teensy_ports\" -J2", }) - errs = packageManager.LoadDiscoveries() - require.Len(t, errs, 2) - require.Equal(t, errs[0].Message(), "discovery not found: builtin:serial-discovery") - require.Equal(t, errs[1].Message(), "discovery not found: builtin:mdns-discovery") + err = packageManager.LoadDiscoveries() + require.Len(t, err, 2) + require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found") + require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found") discoveries = packageManager.DiscoveryManager().IDs() require.Len(t, discoveries, 3) require.Contains(t, discoveries, "arduino:ble-discovery") diff --git a/arduino/discovery/discovery.go b/arduino/discovery/discovery.go index 1ce6310f156..f20c1533d97 100644 --- a/arduino/discovery/discovery.go +++ b/arduino/discovery/discovery.go @@ -126,14 +126,13 @@ type Event struct { } // New create and connect to the given pluggable discovery -func New(id string, args ...string) (*PluggableDiscovery, error) { - disc := &PluggableDiscovery{ +func New(id string, args ...string) *PluggableDiscovery { + return &PluggableDiscovery{ id: id, processArgs: args, state: Dead, cachedPorts: map[string]*Port{}, } - return disc, nil } // GetID returns the identifier for this discovery diff --git a/arduino/discovery/discovery_client/main.go b/arduino/discovery/discovery_client/main.go index 8a78765f63c..2f033a604a3 100644 --- a/arduino/discovery/discovery_client/main.go +++ b/arduino/discovery/discovery_client/main.go @@ -32,11 +32,7 @@ func main() { discoveries := []*discovery.PluggableDiscovery{} discEvent := make(chan *discovery.Event) for _, discCmd := range os.Args[1:] { - disc, err := discovery.New("", discCmd) - if err != nil { - log.Fatal("Error initializing discovery:", err) - } - + disc := discovery.New("", discCmd) if err := disc.Run(); err != nil { log.Fatal("Error starting discovery:", err) } diff --git a/arduino/discovery/discovery_test.go b/arduino/discovery/discovery_test.go index f0e9c03bcc4..27791da6c89 100644 --- a/arduino/discovery/discovery_test.go +++ b/arduino/discovery/discovery_test.go @@ -32,8 +32,7 @@ func TestDiscoveryStdioHandling(t *testing.T) { require.NoError(t, builder.Run()) // Run cat and test if streaming json works as expected - disc, err := New("test", "testdata/cat/cat") // copy stdin to stdout - require.NoError(t, err) + disc := New("test", "testdata/cat/cat") // copy stdin to stdout err = disc.runProcess() require.NoError(t, err) diff --git a/arduino/errors.go b/arduino/errors.go index 379e69e19b9..b1de65205dd 100644 --- a/arduino/errors.go +++ b/arduino/errors.go @@ -338,6 +338,24 @@ func (e *PlatformNotFoundError) Unwrap() error { return e.Cause } +// PlatformLoadingError is returned when a platform has fatal errors that prevents loading +type PlatformLoadingError struct { + Cause error +} + +func (e *PlatformLoadingError) Error() string { + return composeErrorMsg(tr("Error loading hardware platform"), e.Cause) +} + +// ToRPCStatus converts the error into a *status.Status +func (e *PlatformLoadingError) ToRPCStatus() *status.Status { + return status.New(codes.FailedPrecondition, e.Error()) +} + +func (e *PlatformLoadingError) Unwrap() error { + return e.Cause +} + // LibraryNotFoundError is returned when a platform is not found type LibraryNotFoundError struct { Library string diff --git a/commands/instances.go b/commands/instances.go index f26cf07c4fa..cf336ceb48d 100644 --- a/commands/instances.go +++ b/commands/instances.go @@ -233,9 +233,10 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro // otherwise we wouldn't find them and reinstall them each time // and they would never get reloaded. for _, err := range instance.PackageManager.LoadHardware() { + s := &arduino.PlatformLoadingError{Cause: err} responseCallback(&rpc.InitResponse{ Message: &rpc.InitResponse_Error{ - Error: err.Proto(), + Error: s.ToRPCStatus().Proto(), }, }) } @@ -296,18 +297,20 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro // We installed at least one new tool after loading hardware // so we must reload again otherwise we would never found them. for _, err := range instance.PackageManager.LoadHardware() { + s := &arduino.PlatformLoadingError{Cause: err} responseCallback(&rpc.InitResponse{ Message: &rpc.InitResponse_Error{ - Error: err.Proto(), + Error: s.ToRPCStatus().Proto(), }, }) } } for _, err := range instance.PackageManager.LoadDiscoveries() { + s := &arduino.PlatformLoadingError{Cause: err} responseCallback(&rpc.InitResponse{ Message: &rpc.InitResponse_Error{ - Error: err.Proto(), + Error: s.ToRPCStatus().Proto(), }, }) } diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md index cbfb502cde1..54f5b40c5eb 100644 --- a/docs/UPGRADING.md +++ b/docs/UPGRADING.md @@ -2,6 +2,46 @@ Here you can find a list of migration guides to handle breaking changes between releases of the CLI. +## 0.22.0 + +### `packagemanager.Load*` functions now returns `error` instead of `*status.Status` + +The following functions signature: + +```go +func (pm *PackageManager) LoadHardware() []*status.Status { ... } +func (pm *PackageManager) LoadHardwareFromDirectories(hardwarePaths paths.PathList) []*status.Status { ... } +func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []*status.Status { ... } +func (pm *PackageManager) LoadToolsFromBundleDirectories(dirs paths.PathList) []*status.Status { ... } +func (pm *PackageManager) LoadDiscoveries() []*status.Status { ... } +``` + +have been changed to: + +```go +func (pm *PackageManager) LoadHardware() []error { ... } +func (pm *PackageManager) LoadHardwareFromDirectories(hardwarePaths paths.PathList) []error { ... } +func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error { ... } +func (pm *PackageManager) LoadToolsFromBundleDirectories(dirs paths.PathList) []error { ... } +func (pm *PackageManager) LoadDiscoveries() []error { ... } +``` + +These function no longer returns a gRPC status, so the errors can be handled as any other `error`. + +### Removed `error` return from `discovery.New(...)` function + +The `discovery.New(...)` function never fails, so the error has been removed, the old signature: + +```go +func New(id string, args ...string) (*PluggableDiscovery, error) { ... } +``` + +is now: + +```go +func New(id string, args ...string) *PluggableDiscovery { ... } +``` + ## 0.21.0 ### `packagemanager.NewPackageManager` function change diff --git a/legacy/builder/hardware_loader.go b/legacy/builder/hardware_loader.go index 61a0aca530f..9ea44e606a0 100644 --- a/legacy/builder/hardware_loader.go +++ b/legacy/builder/hardware_loader.go @@ -27,18 +27,16 @@ func (s *HardwareLoader) Run(ctx *types.Context) error { // This should happen only on legacy arduino-builder. // Hopefully this piece will be removed once the legacy package will be cleanedup. pm := packagemanager.NewPackageManager(nil, nil, nil, nil, "arduino-builder") - if errs := pm.LoadHardwareFromDirectories(ctx.HardwareDirs); len(errs) > 0 { + errs := pm.LoadHardwareFromDirectories(ctx.HardwareDirs) + if ctx.Verbose { // With the refactoring of the initialization step of the CLI we changed how // errors are returned when loading platforms and libraries, that meant returning a list of // errors instead of a single one to enhance the experience for the user. // I have no intention right now to start a refactoring of the legacy package too, so // here's this shitty solution for now. // When we're gonna refactor the legacy package this will be gone. - - if ctx.Verbose { - for _, err := range errs { - ctx.Info(tr("Error loading hardware platform: %[1]s", err.Message())) - } + for _, err := range errs { + ctx.Info(tr("Error loading hardware platform: %[1]s", err.Error())) } } ctx.PackageManager = pm diff --git a/test/test_core.py b/test/test_core.py index 6cb9e01f10a..a3f2b121840 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -759,7 +759,7 @@ def test_core_with_wrong_custom_board_options_is_loaded(run_command, data_dir): assert "arduino-beta-dev:platform_with_wrong_custom_board_options:altra" in boards # Verify warning is shown to user assert ( - "Error initializing instance: " + "Error initializing instance: Error loading hardware platform: " + "loading platform release arduino-beta-dev:platform_with_wrong_custom_board_options@4.2.0: " + "loading boards: " + "skipping loading of boards arduino-beta-dev:platform_with_wrong_custom_board_options:nessuno: " @@ -797,7 +797,7 @@ def test_core_with_missing_custom_board_options_is_loaded(run_command, data_dir) assert "arduino-beta-dev:platform_with_missing_custom_board_options:altra" in boards # Verify warning is shown to user assert ( - "Error initializing instance: " + "Error initializing instance: Error loading hardware platform: " + "loading platform release arduino-beta-dev:platform_with_missing_custom_board_options@4.2.0: " + "loading boards: " + "skipping loading of boards arduino-beta-dev:platform_with_missing_custom_board_options:nessuno: "