diff --git a/arduino/cores/cores.go b/arduino/cores/cores.go index 0c836c20f8d..c3e09adac79 100644 --- a/arduino/cores/cores.go +++ b/arduino/cores/cores.go @@ -75,6 +75,7 @@ type PlatformRelease struct { PluggableDiscoveryAware bool `json:"-"` // true if the Platform supports pluggable discovery (no compatibility layer required) Monitors map[string]*MonitorDependency `json:"-"` MonitorsDevRecipes map[string]string `json:"-"` + Compatible bool `json:"-"` // true if at all ToolDependencies are available for the current OS/ARCH. } // BoardManifest contains information about a board. These metadata are usually @@ -229,6 +230,21 @@ func (platform *Platform) GetLatestRelease() *PlatformRelease { return platform.FindReleaseWithVersion(latestVersion) } +// GetLatestCompatibleRelease returns the latest compatible release of this platform, or nil if no +// compatible releases are available. +func (platform *Platform) GetLatestCompatibleRelease() *PlatformRelease { + var maximum *PlatformRelease + for _, release := range platform.Releases { + if !release.IsCompatible() { + continue + } + if maximum == nil || release.Version.GreaterThan(maximum.Version) { + maximum = release + } + } + return maximum +} + // GetAllReleases returns all the releases of this platform, or an empty // slice if no releases are available func (platform *Platform) GetAllReleases() []*PlatformRelease { @@ -249,6 +265,18 @@ func (platform *Platform) GetAllReleasesVersions() []*semver.Version { return versions } +// GetAllCompatibleReleasesVersions returns all the version numbers in this Platform Package that contains compatible tools. +func (platform *Platform) GetAllCompatibleReleasesVersions() []*semver.Version { + versions := []*semver.Version{} + for _, release := range platform.Releases { + if !release.IsCompatible() { + continue + } + versions = append(versions, release.Version) + } + return versions +} + // latestReleaseVersion obtains latest version number, or nil if no release available func (platform *Platform) latestReleaseVersion() *semver.Version { // TODO: Cache latest version using a field in Platform @@ -266,6 +294,18 @@ func (platform *Platform) latestReleaseVersion() *semver.Version { return max } +// latestCompatibleReleaseVersion obtains latest version number, for platforms that contains compatible tools, or nil if no release available +func (platform *Platform) latestCompatibleReleaseVersion() *semver.Version { + versions := platform.GetAllCompatibleReleasesVersions() + var maxVer *semver.Version + for _, v := range versions { + if maxVer == nil || v.GreaterThan(maxVer) { + maxVer = v + } + } + return maxVer +} + // GetAllInstalled returns all installed PlatformRelease func (platform *Platform) GetAllInstalled() []*PlatformRelease { res := []*PlatformRelease{} @@ -422,3 +462,9 @@ func (release *PlatformRelease) HasMetadata() bool { installedJSONPath := release.InstallDir.Join("installed.json") return installedJSONPath.Exist() } + +// IsCompatible returns true if all the tools dependencies of a PlatformRelease +// are available in the current OS/ARCH. +func (release *PlatformRelease) IsCompatible() bool { + return release.Compatible +} diff --git a/arduino/cores/packagemanager/download.go b/arduino/cores/packagemanager/download.go index f3a5877c8a6..43d13c11ea0 100644 --- a/arduino/cores/packagemanager/download.go +++ b/arduino/cores/packagemanager/download.go @@ -87,9 +87,9 @@ func (pme *Explorer) FindPlatformReleaseDependencies(item *PlatformReference) (* return nil, nil, fmt.Errorf(tr("required version %[1]s not found for platform %[2]s"), item.PlatformVersion, platform.String()) } } else { - release = platform.GetLatestRelease() + release = platform.GetLatestCompatibleRelease() if release == nil { - return nil, nil, fmt.Errorf(tr("platform %s has no available releases"), platform.String()) + return nil, nil, fmt.Errorf(tr("platform is not available for your OS")) } } diff --git a/arduino/cores/packagemanager/install_uninstall.go b/arduino/cores/packagemanager/install_uninstall.go index 0d8332cb2be..2f396894fa5 100644 --- a/arduino/cores/packagemanager/install_uninstall.go +++ b/arduino/cores/packagemanager/install_uninstall.go @@ -53,7 +53,7 @@ func (pme *Explorer) DownloadAndInstallPlatformUpgrades( if installed == nil { return nil, &arduino.PlatformNotFoundError{Platform: platformRef.String()} } - latest := platform.GetLatestRelease() + latest := platform.GetLatestCompatibleRelease() if !latest.Version.GreaterThan(installed.Version) { return installed, &arduino.PlatformAlreadyAtTheLatestVersionError{Platform: platformRef.String()} } diff --git a/arduino/cores/packagemanager/package_manager.go b/arduino/cores/packagemanager/package_manager.go index 1d6ac17aac0..1f2b380e08a 100644 --- a/arduino/cores/packagemanager/package_manager.go +++ b/arduino/cores/packagemanager/package_manager.go @@ -121,6 +121,42 @@ func (pmb *Builder) Build() *PackageManager { } } +// calculate Compatible PlatformRelease +func (pmb *Builder) calculateCompatibleReleases() { + for _, op := range pmb.packages { + for _, p := range op.Platforms { + for _, pr := range p.Releases { + platformHasAllCompatibleTools := func() bool { + for _, td := range pr.ToolDependencies { + if td == nil { + return false + } + + _, ok := pmb.packages[td.ToolPackager] + if !ok { + return false + } + tool := pmb.packages[td.ToolPackager].Tools[td.ToolName] + if tool == nil { + return false + } + tr := tool.Releases[td.ToolVersion.NormalizedString()] + if tr == nil { + return false + } + + if tr.GetCompatibleFlavour() == nil { + return false + } + } + return true + } + pr.Compatible = platformHasAllCompatibleTools() + } + } + } +} + // NewBuilder creates a Builder with the same configuration // of this PackageManager. A "commit" function callback is returned: calling // this function will make the builder write the new configuration into this @@ -128,6 +164,7 @@ func (pmb *Builder) Build() *PackageManager { func (pm *PackageManager) NewBuilder() (builder *Builder, commit func()) { pmb := NewBuilder(pm.IndexDir, pm.PackagesDir, pm.DownloadDir, pm.tempDir, pm.userAgent) return pmb, func() { + pmb.calculateCompatibleReleases() pmb.BuildIntoExistingPackageManager(pm) } } diff --git a/arduino/cores/packagemanager/package_manager_test.go b/arduino/cores/packagemanager/package_manager_test.go index c02fa34eaa6..8a5fc877850 100644 --- a/arduino/cores/packagemanager/package_manager_test.go +++ b/arduino/cores/packagemanager/package_manager_test.go @@ -744,6 +744,7 @@ func TestFindToolsRequiredFromPlatformRelease(t *testing.T) { func TestFindPlatformReleaseDependencies(t *testing.T) { pmb := NewBuilder(nil, nil, nil, nil, "test") pmb.LoadPackageIndexFromFile(paths.New("testdata", "package_tooltest_index.json")) + pmb.calculateCompatibleReleases() pm := pmb.Build() pme, release := pm.NewExplorer() defer release() diff --git a/commands/board/search.go b/commands/board/search.go index 007867775e3..bd8702504d7 100644 --- a/commands/board/search.go +++ b/commands/board/search.go @@ -41,7 +41,7 @@ func Search(ctx context.Context, req *rpc.BoardSearchRequest) (*rpc.BoardSearchR foundBoards := []*rpc.BoardListItem{} for _, targetPackage := range pme.GetPackages() { for _, platform := range targetPackage.Platforms { - latestPlatformRelease := platform.GetLatestRelease() + latestPlatformRelease := platform.GetLatestCompatibleRelease() installedPlatformRelease := pme.GetInstalledPlatformRelease(platform) if latestPlatformRelease == nil && installedPlatformRelease == nil { diff --git a/commands/core.go b/commands/core.go index 14dc3360e4c..1881519ef38 100644 --- a/commands/core.go +++ b/commands/core.go @@ -74,5 +74,6 @@ func PlatformReleaseToRPC(platformRelease *cores.PlatformRelease) *rpc.PlatformR MissingMetadata: missingMetadata, Type: []string{platformRelease.Category}, Deprecated: platformRelease.Deprecated, + Compatible: platformRelease.IsCompatible(), } } diff --git a/commands/core/search.go b/commands/core/search.go index 7d0b5662f31..c0341b40a91 100644 --- a/commands/core/search.go +++ b/commands/core/search.go @@ -55,10 +55,7 @@ func PlatformSearch(req *rpc.PlatformSearchRequest) (*rpc.PlatformSearchResponse // Discard platforms with no releases latestRelease := platform.GetLatestRelease() - if latestRelease == nil { - continue - } - if latestRelease.Name == "" { + if latestRelease == nil || latestRelease.Name == "" { continue } @@ -86,41 +83,25 @@ func PlatformSearch(req *rpc.PlatformSearchRequest) (*rpc.PlatformSearchResponse out := []*rpc.PlatformSummary{} for _, platform := range res { rpcPlatformSummary := &rpc.PlatformSummary{ + Metadata: commands.PlatformToRPCPlatformMetadata(platform), Releases: map[string]*rpc.PlatformRelease{}, } - - rpcPlatformSummary.Metadata = commands.PlatformToRPCPlatformMetadata(platform) - - installed := pme.GetInstalledPlatformRelease(platform) - latest := platform.GetLatestRelease() - if installed != nil { + if installed := pme.GetInstalledPlatformRelease(platform); installed != nil { rpcPlatformSummary.InstalledVersion = installed.Version.String() } - if latest != nil { - rpcPlatformSummary.LatestVersion = latest.Version.String() + if latestCompatible := platform.GetLatestCompatibleRelease(); latestCompatible != nil { + rpcPlatformSummary.LatestVersion = latestCompatible.Version.String() } - if req.AllVersions { - for _, platformRelease := range platform.GetAllReleases() { - rpcPlatformRelease := commands.PlatformReleaseToRPC(platformRelease) - rpcPlatformSummary.Releases[rpcPlatformRelease.Version] = rpcPlatformRelease - } - } else { - if installed != nil { - rpcPlatformRelease := commands.PlatformReleaseToRPC(installed) - rpcPlatformSummary.Releases[installed.Version.String()] = rpcPlatformRelease - } - if latest != nil { - rpcPlatformRelease := commands.PlatformReleaseToRPC(latest) - rpcPlatformSummary.Releases[latest.Version.String()] = rpcPlatformRelease - } + for _, platformRelease := range platform.GetAllReleases() { + rpcPlatformRelease := commands.PlatformReleaseToRPC(platformRelease) + rpcPlatformSummary.Releases[rpcPlatformRelease.Version] = rpcPlatformRelease } out = append(out, rpcPlatformSummary) } // Sort result alphabetically and put deprecated platforms at the bottom sort.Slice(out, func(i, j int) bool { - return strings.ToLower(out[i].GetReleases()[out[i].GetLatestVersion()].Name) < - strings.ToLower(out[j].GetReleases()[out[j].GetLatestVersion()].Name) + return strings.ToLower(out[i].GetMetadata().GetId()) < strings.ToLower(out[j].GetMetadata().GetId()) }) sort.SliceStable(out, func(i, j int) bool { return !out[i].GetMetadata().Deprecated && out[j].GetMetadata().Deprecated diff --git a/commands/core/search_test.go b/commands/core/search_test.go index a695acbd6b4..ea3fdc4ef9d 100644 --- a/commands/core/search_test.go +++ b/commands/core/search_test.go @@ -43,9 +43,8 @@ func TestPlatformSearch(t *testing.T) { t.Run("SearchAllVersions", func(t *testing.T) { res, stat := PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: "retrokit", - AllVersions: true, + Instance: inst, + SearchArgs: "retrokit", }) require.Nil(t, stat) require.NotNil(t, res) @@ -61,64 +60,32 @@ func TestPlatformSearch(t *testing.T) { }, Releases: map[string]*rpc.PlatformRelease{ "1.0.5": { - Name: "RK002", - Type: []string{"Contributed"}, - Installed: false, - Version: "1.0.5", - Boards: []*rpc.Board{{Name: "RK002"}}, - Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, - }, - "1.0.6": { - Name: "RK002", - Type: []string{"Contributed"}, - Installed: false, - Version: "1.0.6", - Boards: []*rpc.Board{{Name: "RK002"}}, - Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Name: "RK002", + Type: []string{"Contributed"}, + Installed: false, + Version: "1.0.5", + Boards: []*rpc.Board{{Name: "RK002"}}, + Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Compatible: false, }, - }, - InstalledVersion: "", - LatestVersion: "1.0.6", - }) - }) - - t.Run("SearchNoAllVersions", func(t *testing.T) { - res, stat := PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: "retrokit", - AllVersions: false, - }) - require.Nil(t, stat) - require.NotNil(t, res) - require.Len(t, res.SearchOutput, 1) - require.Contains(t, res.SearchOutput, &rpc.PlatformSummary{ - Metadata: &rpc.PlatformMetadata{ - Id: "Retrokits-RK002:arm", - Maintainer: "Retrokits (www.retrokits.com)", - Website: "https://www.retrokits.com", - Email: "info@retrokits.com", - Indexed: true, - }, - Releases: map[string]*rpc.PlatformRelease{ "1.0.6": { - Name: "RK002", - Type: []string{"Contributed"}, - Installed: false, - Version: "1.0.6", - Boards: []*rpc.Board{{Name: "RK002"}}, - Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Name: "RK002", + Type: []string{"Contributed"}, + Installed: false, + Version: "1.0.6", + Boards: []*rpc.Board{{Name: "RK002"}}, + Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Compatible: false, }, }, InstalledVersion: "", - LatestVersion: "1.0.6", }) }) t.Run("SearchThePackageMaintainer", func(t *testing.T) { res, stat := PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: "Retrokits (www.retrokits.com)", - AllVersions: true, + Instance: inst, + SearchArgs: "Retrokits (www.retrokits.com)", }) require.Nil(t, stat) require.NotNil(t, res) @@ -133,32 +100,32 @@ func TestPlatformSearch(t *testing.T) { }, Releases: map[string]*rpc.PlatformRelease{ "1.0.5": { - Name: "RK002", - Type: []string{"Contributed"}, - Installed: false, - Version: "1.0.5", - Boards: []*rpc.Board{{Name: "RK002"}}, - Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Name: "RK002", + Type: []string{"Contributed"}, + Installed: false, + Version: "1.0.5", + Boards: []*rpc.Board{{Name: "RK002"}}, + Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Compatible: false, }, "1.0.6": { - Name: "RK002", - Type: []string{"Contributed"}, - Installed: false, - Version: "1.0.6", - Boards: []*rpc.Board{{Name: "RK002"}}, - Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Name: "RK002", + Type: []string{"Contributed"}, + Installed: false, + Version: "1.0.6", + Boards: []*rpc.Board{{Name: "RK002"}}, + Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Compatible: false, }, }, InstalledVersion: "", - LatestVersion: "1.0.6", }) }) t.Run("SearchPackageName", func(t *testing.T) { res, stat := PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: "Retrokits-RK002", - AllVersions: true, + Instance: inst, + SearchArgs: "Retrokits-RK002", }) require.Nil(t, stat) require.NotNil(t, res) @@ -173,32 +140,32 @@ func TestPlatformSearch(t *testing.T) { }, Releases: map[string]*rpc.PlatformRelease{ "1.0.5": { - Name: "RK002", - Type: []string{"Contributed"}, - Installed: false, - Version: "1.0.5", - Boards: []*rpc.Board{{Name: "RK002"}}, - Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Name: "RK002", + Type: []string{"Contributed"}, + Installed: false, + Version: "1.0.5", + Boards: []*rpc.Board{{Name: "RK002"}}, + Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Compatible: false, }, "1.0.6": { - Name: "RK002", - Type: []string{"Contributed"}, - Installed: false, - Version: "1.0.6", - Boards: []*rpc.Board{{Name: "RK002"}}, - Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Name: "RK002", + Type: []string{"Contributed"}, + Installed: false, + Version: "1.0.6", + Boards: []*rpc.Board{{Name: "RK002"}}, + Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Compatible: false, }, }, InstalledVersion: "", - LatestVersion: "1.0.6", }) }) t.Run("SearchPlatformName", func(t *testing.T) { res, stat := PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: "rk002", - AllVersions: true, + Instance: inst, + SearchArgs: "rk002", }) require.Nil(t, stat) require.NotNil(t, res) @@ -213,32 +180,32 @@ func TestPlatformSearch(t *testing.T) { }, Releases: map[string]*rpc.PlatformRelease{ "1.0.5": { - Name: "RK002", - Type: []string{"Contributed"}, - Installed: false, - Version: "1.0.5", - Boards: []*rpc.Board{{Name: "RK002"}}, - Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Name: "RK002", + Type: []string{"Contributed"}, + Installed: false, + Version: "1.0.5", + Boards: []*rpc.Board{{Name: "RK002"}}, + Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Compatible: false, }, "1.0.6": { - Name: "RK002", - Type: []string{"Contributed"}, - Installed: false, - Version: "1.0.6", - Boards: []*rpc.Board{{Name: "RK002"}}, - Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Name: "RK002", + Type: []string{"Contributed"}, + Installed: false, + Version: "1.0.6", + Boards: []*rpc.Board{{Name: "RK002"}}, + Help: &rpc.HelpResources{Online: "https://www.retrokits.com/rk002/arduino"}, + Compatible: false, }, }, InstalledVersion: "", - LatestVersion: "1.0.6", }) }) t.Run("SearchBoardName", func(t *testing.T) { res, stat := PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: "Yún", - AllVersions: true, + Instance: inst, + SearchArgs: "Yún", }) require.Nil(t, stat) require.NotNil(t, res) @@ -285,19 +252,18 @@ func TestPlatformSearch(t *testing.T) { {Name: "Arduino Industrial 101"}, {Name: "Linino One"}, }, - Help: &rpc.HelpResources{Online: "http://www.arduino.cc/en/Reference/HomePage"}, + Help: &rpc.HelpResources{Online: "http://www.arduino.cc/en/Reference/HomePage"}, + Compatible: false, }, }, InstalledVersion: "", - LatestVersion: "1.8.3", }) }) t.Run("SearchBoardName2", func(t *testing.T) { res, stat := PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: "yun", - AllVersions: true, + Instance: inst, + SearchArgs: "yun", }) require.Nil(t, stat) require.NotNil(t, res) @@ -344,11 +310,11 @@ func TestPlatformSearch(t *testing.T) { {Name: "Arduino Industrial 101"}, {Name: "Linino One"}, }, - Help: &rpc.HelpResources{Online: "http://www.arduino.cc/en/Reference/HomePage"}, + Help: &rpc.HelpResources{Online: "http://www.arduino.cc/en/Reference/HomePage"}, + Compatible: false, }, }, InstalledVersion: "", - LatestVersion: "1.8.3", }) }) } @@ -370,17 +336,16 @@ func TestPlatformSearchSorting(t *testing.T) { require.NotNil(t, inst) res, stat := PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: "", - AllVersions: false, + Instance: inst, + SearchArgs: "", }) require.Nil(t, stat) require.NotNil(t, res) require.Len(t, res.SearchOutput, 3) - require.Equal(t, res.SearchOutput[0].GetLatestRelease().Name, "Arduino AVR Boards") + require.Equal(t, res.SearchOutput[0].GetSortedReleases()[0].Name, "Arduino AVR Boards") require.Equal(t, res.SearchOutput[0].Metadata.Deprecated, false) - require.Equal(t, res.SearchOutput[1].GetLatestRelease().Name, "RK002") + require.Equal(t, res.SearchOutput[1].GetSortedReleases()[0].Name, "RK002") require.Equal(t, res.SearchOutput[1].Metadata.Deprecated, false) require.Equal(t, res.SearchOutput[2].GetLatestRelease().Name, "Platform") require.Equal(t, res.SearchOutput[2].Metadata.Deprecated, true) diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md index 037f4992058..8b8ebcf7790 100644 --- a/docs/UPGRADING.md +++ b/docs/UPGRADING.md @@ -4,6 +4,34 @@ Here you can find a list of migration guides to handle breaking changes between ## 0.36.0 +### The gRPC `cc.arduino.cli.commands.v1.PlatformRelease` has been changed. + +We've added a new field called `compatible`. This field indicates if the current platform release is installable or not. +It may happen that a platform doesn't have a dependency available for an OS/ARCH, in such cases, if we try to install +the platform it will fail. The new field can be used to know upfront if a specific release is installable. + +### The gRPC `cc.arduino.cli.commands.v1.PlatformSummary` has been changed. + +We've modified the behavior of `latest_version`. Now this field indicates the latest version that can be installed in +the current OS/ARCH. + +### `core list` now returns only the latest version that can be installed. + +Previously, we showed the latest version without checking if all the dependencies were available in the current OS/ARCH. +Now, the latest version will always point to an installable one even if a newer incompatible one is present. + +### `core search` now returns the latest installable version of a core. + +We now show in the `version` column the latest installable version. If none are available then we show a `n/a` label. +The corresponding command with `--format json` now returns the same output of +`arduino-cli core search --all --format json`. + +### `core upgrade` and `core install` will install the latest compatible version. + +Previously, we'd have tried the installation/upgrade of a core even if all the required tools weren't available in the +current OS/ARCH. Now we check this upfront, and allowing the installation of incompatible versions only if a user +explicitly provides it like: `core install arduino:renesas_uno@1.0.2` + ### gRPC service `cc.arduino.cli.settings.v1` has been removed, and all RPC calls have been migrated to `cc.arduino.cli.commands.v1` The service `cc.arduino.cli.settings.v1` no longer exists and all existing RPC calls have been moved to the diff --git a/internal/cli/arguments/completion.go b/internal/cli/arguments/completion.go index 2139e415fe1..89423edd1a7 100644 --- a/internal/cli/arguments/completion.go +++ b/internal/cli/arguments/completion.go @@ -85,7 +85,6 @@ func GetUninstallableCores() []string { platforms, _ := core.PlatformSearch(&rpc.PlatformSearchRequest{ Instance: inst, - AllVersions: false, ManuallyInstalled: true, }) @@ -106,14 +105,15 @@ func GetInstallableCores() []string { inst := instance.CreateAndInit() platforms, _ := core.PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: "", - AllVersions: false, + Instance: inst, + SearchArgs: "", }) var res []string // transform the data structure for the completion - for _, i := range platforms.SearchOutput { - res = append(res, i.GetMetadata().GetId()+"\t"+i.GetReleases()[i.GetLatestVersion()].GetName()) + for _, i := range platforms.GetSearchOutput() { + if latest := i.GetLatestRelease(); latest != nil { + res = append(res, i.GetMetadata().GetId()+"\t"+latest.GetName()) + } } return res } diff --git a/internal/cli/arguments/reference.go b/internal/cli/arguments/reference.go index f9d8737d415..ed6152af5b8 100644 --- a/internal/cli/arguments/reference.go +++ b/internal/cli/arguments/reference.go @@ -96,8 +96,7 @@ func ParseReference(arg string) (*Reference, error) { // try to use core.PlatformList to optimize what the user typed // (by replacing the PackageName and Architecture in ret with the content of core.GetPlatform()) platforms, _ := core.PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: instance.CreateAndInit(), - AllVersions: false, + Instance: instance.CreateAndInit(), }) foundPlatforms := []string{} for _, platform := range platforms.GetSearchOutput() { diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index 1204b529f17..7cd66de7663 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -370,9 +370,8 @@ func runCompileCommand(cmd *cobra.Command, args []string) { res.Error += fmt.Sprintln() if platform, err := core.PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: platformErr.Platform, - AllVersions: false, + Instance: inst, + SearchArgs: platformErr.Platform, }); err != nil { res.Error += err.Error() } else if len(platform.GetSearchOutput()) > 0 { diff --git a/internal/cli/core/list.go b/internal/cli/core/list.go index 1adda2f26bc..40ac933f027 100644 --- a/internal/cli/core/list.go +++ b/internal/cli/core/list.go @@ -16,7 +16,6 @@ package core import ( - "fmt" "os" "github.com/arduino/arduino-cli/commands/core" @@ -56,14 +55,13 @@ func runListCommand(args []string, all bool, updatableOnly bool) { // List gets and prints a list of installed platforms. func List(inst *rpc.Instance, all bool, updatableOnly bool) { platforms := GetList(inst, all, updatableOnly) - feedback.PrintResult(newCoreListResult(platforms)) + feedback.PrintResult(newCoreListResult(platforms, updatableOnly)) } // GetList returns a list of installed platforms. func GetList(inst *rpc.Instance, all bool, updatableOnly bool) []*rpc.PlatformSummary { platforms, err := core.PlatformSearch(&rpc.PlatformSearchRequest{ Instance: inst, - AllVersions: true, ManuallyInstalled: true, }) if err != nil { @@ -88,8 +86,8 @@ func GetList(inst *rpc.Instance, all bool, updatableOnly bool) []*rpc.PlatformSu return result } -func newCoreListResult(in []*rpc.PlatformSummary) *coreListResult { - res := &coreListResult{} +func newCoreListResult(in []*rpc.PlatformSummary, updatableOnly bool) *coreListResult { + res := &coreListResult{updatableOnly: updatableOnly} for _, platformSummary := range in { res.platforms = append(res.platforms, result.NewPlatformSummary(platformSummary)) } @@ -97,7 +95,8 @@ func newCoreListResult(in []*rpc.PlatformSummary) *coreListResult { } type coreListResult struct { - platforms []*result.PlatformSummary + platforms []*result.PlatformSummary + updatableOnly bool } // Data implements Result interface @@ -108,24 +107,19 @@ func (ir coreListResult) Data() interface{} { // String implements Result interface func (ir coreListResult) String() string { if len(ir.platforms) == 0 { + if ir.updatableOnly { + return tr("All platforms are up to date.") + } return tr("No platforms installed.") } t := table.New() t.SetHeader(tr("ID"), tr("Installed"), tr("Latest"), tr("Name")) for _, platform := range ir.platforms { - name := "" - if installed := platform.GetInstalledRelease(); installed != nil { - name = installed.Name - } - if name == "" { - if latest := platform.GetLatestRelease(); latest != nil { - name = latest.Name - } - } - if platform.Deprecated { - name = fmt.Sprintf("[%s] %s", tr("DEPRECATED"), name) + latestVersion := platform.LatestVersion.String() + if latestVersion == "" { + latestVersion = "n/a" } - t.AddRow(platform.Id, platform.InstalledVersion, platform.LatestVersion, name) + t.AddRow(platform.Id, platform.InstalledVersion, latestVersion, platform.GetPlatformName()) } return t.Render() diff --git a/internal/cli/core/search.go b/internal/cli/core/search.go index 30d4f749759..0fc2389cdd8 100644 --- a/internal/cli/core/search.go +++ b/internal/cli/core/search.go @@ -37,18 +37,17 @@ import ( "github.com/spf13/cobra" ) -var ( - allVersions bool -) - func initSearchCommand() *cobra.Command { + var allVersions bool searchCommand := &cobra.Command{ Use: fmt.Sprintf("search <%s...>", tr("keywords")), Short: tr("Search for a core in Boards Manager."), Long: tr("Search for a core in Boards Manager using the specified keywords."), Example: " " + os.Args[0] + " core search MKRZero -a -v", Args: cobra.ArbitraryArgs, - Run: runSearchCommand, + Run: func(cmd *cobra.Command, args []string) { + runSearchCommand(cmd, args, allVersions) + }, } searchCommand.Flags().BoolVarP(&allVersions, "all", "a", false, tr("Show all available core versions.")) @@ -58,7 +57,7 @@ func initSearchCommand() *cobra.Command { // indexUpdateInterval specifies the time threshold over which indexes are updated const indexUpdateInterval = "24h" -func runSearchCommand(cmd *cobra.Command, args []string) { +func runSearchCommand(cmd *cobra.Command, args []string, allVersions bool) { inst := instance.CreateAndInit() if indexesNeedUpdating(indexUpdateInterval) { @@ -73,28 +72,31 @@ func runSearchCommand(cmd *cobra.Command, args []string) { logrus.Infof("Executing `arduino-cli core search` with args: '%s'", arguments) resp, err := core.PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: arguments, - AllVersions: allVersions, + Instance: inst, + SearchArgs: arguments, }) if err != nil { feedback.Fatal(tr("Error searching for platforms: %v", err), feedback.ErrGeneric) } coreslist := resp.GetSearchOutput() - feedback.PrintResult(newSearchResult(coreslist)) + feedback.PrintResult(newSearchResult(coreslist, allVersions)) } // output from this command requires special formatting, let's create a dedicated // feedback.Result implementation type searchResults struct { - platforms []*result.PlatformSummary + platforms []*result.PlatformSummary + allVersions bool } -func newSearchResult(in []*rpc.PlatformSummary) *searchResults { - res := &searchResults{} - for _, platformSummary := range in { - res.platforms = append(res.platforms, result.NewPlatformSummary(platformSummary)) +func newSearchResult(in []*rpc.PlatformSummary, allVersions bool) *searchResults { + res := &searchResults{ + platforms: make([]*result.PlatformSummary, len(in)), + allVersions: allVersions, + } + for i, platformSummary := range in { + res.platforms[i] = result.NewPlatformSummary(platformSummary) } return res } @@ -104,24 +106,33 @@ func (sr searchResults) Data() interface{} { } func (sr searchResults) String() string { - if len(sr.platforms) > 0 { - t := table.New() - t.SetHeader(tr("ID"), tr("Version"), tr("Name")) - for _, platform := range sr.platforms { - name := "" - if latest := platform.GetLatestRelease(); latest != nil { - name = latest.Name - } - if platform.Deprecated { - name = fmt.Sprintf("[%s] %s", tr("DEPRECATED"), name) - } - for _, version := range platform.Releases.Keys() { - t.AddRow(platform.Id, version, name) - } + if len(sr.platforms) == 0 { + return tr("No platforms matching your search.") + } + + t := table.New() + t.SetHeader(tr("ID"), tr("Version"), tr("Name")) + + addRow := func(platform *result.PlatformSummary, release *result.PlatformRelease) { + if release == nil { + t.AddRow(platform.Id, "n/a", platform.GetPlatformName()) + return + } + t.AddRow(platform.Id, release.Version, release.FormatName()) + } + + for _, platform := range sr.platforms { + // When allVersions is not requested we only show the latest compatible version + if !sr.allVersions { + addRow(platform, platform.GetLatestRelease()) + continue + } + + for _, release := range platform.Releases.Values() { + addRow(platform, release) } - return t.Render() } - return tr("No platforms matching your search.") + return t.Render() } // indexesNeedUpdating returns whether one or more index files need updating. diff --git a/internal/cli/core/upgrade.go b/internal/cli/core/upgrade.go index 04045cc3bf6..93bc6c0720f 100644 --- a/internal/cli/core/upgrade.go +++ b/internal/cli/core/upgrade.go @@ -61,8 +61,7 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool, skipPreUni // if no platform was passed, upgrade allthethings if len(args) == 0 { platforms, err := core.PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - AllVersions: false, + Instance: inst, }) if err != nil { feedback.Fatal(tr("Error retrieving core list: %v", err), feedback.ErrGeneric) @@ -73,14 +72,14 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool, skipPreUni if platform.InstalledVersion == "" { continue } - if platform.InstalledVersion == platform.LatestVersion { - // if it's not updatable, skip it - continue + // if it's not updatable, skip it + latestRelease := platform.GetLatestRelease() + if latestRelease != nil && platform.InstalledVersion != latestRelease.Version { + targets = append(targets, &rpc.Platform{ + Metadata: platform.GetMetadata(), + Release: latestRelease, + }) } - targets = append(targets, &rpc.Platform{ - Metadata: platform.GetMetadata(), - Release: platform.GetLatestRelease(), - }) } if len(targets) == 0 { diff --git a/internal/cli/feedback/result/rpc.go b/internal/cli/feedback/result/rpc.go index a632af7737c..63291754fe7 100644 --- a/internal/cli/feedback/result/rpc.go +++ b/internal/cli/feedback/result/rpc.go @@ -17,13 +17,17 @@ package result import ( "cmp" + "fmt" + "github.com/arduino/arduino-cli/i18n" f "github.com/arduino/arduino-cli/internal/algorithms" "github.com/arduino/arduino-cli/internal/orderedmap" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" semver "go.bug.st/relaxed-semver" ) +var tr = i18n.Tr + // NewPlatformSummary creates a new result.PlatformSummary from rpc.PlatformSummary func NewPlatformSummary(in *rpc.PlatformSummary) *PlatformSummary { if in == nil { @@ -76,6 +80,23 @@ func (p *PlatformSummary) GetInstalledRelease() *PlatformRelease { return p.Releases.Get(p.InstalledVersion) } +// GetPlatformName compute the name of the platform based on the installed/available releases. +func (p *PlatformSummary) GetPlatformName() string { + var name string + if installed := p.GetInstalledRelease(); installed != nil { + name = installed.FormatName() + } + if name == "" { + if latest := p.GetLatestRelease(); latest != nil { + name = latest.FormatName() + } else { + keys := p.Releases.Keys() + name = p.Releases.Get(keys[len(keys)-1]).FormatName() + } + } + return name +} + // NewPlatformRelease creates a new result.PlatformRelease from rpc.PlatformRelease func NewPlatformRelease(in *rpc.PlatformRelease) *PlatformRelease { if in == nil { @@ -103,6 +124,7 @@ func NewPlatformRelease(in *rpc.PlatformRelease) *PlatformRelease { Help: help, MissingMetadata: in.MissingMetadata, Deprecated: in.Deprecated, + Compatible: in.Compatible, } return res } @@ -117,6 +139,14 @@ type PlatformRelease struct { Help *HelpResource `json:"help,omitempty"` MissingMetadata bool `json:"missing_metadata,omitempty"` Deprecated bool `json:"deprecated,omitempty"` + Compatible bool `json:"compatible"` +} + +func (p *PlatformRelease) FormatName() string { + if p.Deprecated { + return fmt.Sprintf("[%s] %s", tr("DEPRECATED"), p.Name) + } + return p.Name } // Board maps a rpc.Board diff --git a/internal/cli/upload/upload.go b/internal/cli/upload/upload.go index 73e6166aaaa..7bbc868bf9b 100644 --- a/internal/cli/upload/upload.go +++ b/internal/cli/upload/upload.go @@ -138,9 +138,8 @@ func runUploadCommand(args []string, uploadFieldsArgs map[string]string) { msg += "\n" if platform, err := core.PlatformSearch(&rpc.PlatformSearchRequest{ - Instance: inst, - SearchArgs: platformErr.Platform, - AllVersions: false, + Instance: inst, + SearchArgs: platformErr.Platform, }); err != nil { msg += err.Error() } else if len(platform.GetSearchOutput()) > 0 { diff --git a/internal/integrationtest/arduino-cli.go b/internal/integrationtest/arduino-cli.go index 78ed4dbb3e9..c2b10f7e121 100644 --- a/internal/integrationtest/arduino-cli.go +++ b/internal/integrationtest/arduino-cli.go @@ -576,9 +576,8 @@ func (inst *ArduinoCLIInstance) PlatformUpgrade(ctx context.Context, packager, a // PlatformSearch calls the "PlatformSearch" gRPC method. func (inst *ArduinoCLIInstance) PlatformSearch(ctx context.Context, args string, all bool) (*commands.PlatformSearchResponse, error) { req := &commands.PlatformSearchRequest{ - Instance: inst.instance, - SearchArgs: args, - AllVersions: all, + Instance: inst.instance, + SearchArgs: args, } logCallf(">>> PlatformSearch(%+v)\n", req) resp, err := inst.cli.daemonClient.PlatformSearch(ctx, req) diff --git a/internal/integrationtest/board/board_test.go b/internal/integrationtest/board/board_test.go index 70c53de9039..e4163c749c6 100644 --- a/internal/integrationtest/board/board_test.go +++ b/internal/integrationtest/board/board_test.go @@ -16,8 +16,8 @@ package board_test import ( - "encoding/json" "os" + "runtime" "strings" "testing" @@ -25,7 +25,6 @@ import ( "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/stretchr/testify/require" - semver "go.bug.st/relaxed-semver" "go.bug.st/testifyjson/requirejson" ) @@ -182,26 +181,36 @@ func TestBoardListall(t *testing.T) { "name": "Arduino Yún", "fqbn": "arduino:avr:yun", "platform": { - "id": "arduino:avr", - "installed": "1.8.3", - "name": "Arduino AVR Boards" + "metadata": { + "id": "arduino:avr" + }, + "release": { + "name": "Arduino AVR Boards", + "version": "1.8.3", + "installed": true + } } }, { "name": "Arduino Uno", "fqbn": "arduino:avr:uno", "platform": { - "id": "arduino:avr", - "installed": "1.8.3", - "name": "Arduino AVR Boards" + "metadata": { + "id": "arduino:avr" + }, + "release": { + "name": "Arduino AVR Boards", + "version": "1.8.3", + "installed": true + } } } ] }`) - // Check if the boards' "latest" value is not empty + // Check if the boards' "version" value is not empty requirejson.Parse(t, stdout). - Query(`[ .boards | .[] | .platform | select(.latest == "") ]`). + Query(`[ .boards | .[] | .platform | select(.version == "") ]`). MustBeEmpty() } @@ -232,20 +241,28 @@ func TestBoardListallWithManuallyInstalledPlatform(t *testing.T) { "name": "Arduino MKR1000", "fqbn": "arduino-beta-development:samd:mkr1000", "platform": { - "id": "arduino-beta-development:samd", - "installed": "1.8.11", - "latest": "1.8.11", - "name": "Arduino SAMD (32-bits ARM Cortex-M0+) Boards", + "metadata": { + "id": "arduino-beta-development:samd", + }, + "release": { + "installed": true, + "version": "1.8.11", + "name": "Arduino SAMD (32-bits ARM Cortex-M0+) Boards" + }, } }, { "name": "Arduino NANO 33 IoT", "fqbn": "arduino-beta-development:samd:nano_33_iot", "platform": { - "id": "arduino-beta-development:samd", - "installed": "1.8.11", - "latest": "1.8.11", - "name": "Arduino SAMD (32-bits ARM Cortex-M0+) Boards" + "metadata": { + "id": "arduino-beta-development:samd", + }, + "release": { + "installed": true, + "version": "1.8.11", + "name": "Arduino SAMD (32-bits ARM Cortex-M0+) Boards" + }, } } ] @@ -575,36 +592,6 @@ func TestBoardAttach(t *testing.T) { } } -func TestBoardSearchWithOutdatedCore(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - // Install an old core version - _, _, err = cli.Run("core", "install", "arduino:samd@1.8.6") - require.NoError(t, err) - - stdout, _, err := cli.Run("board", "search", "arduino:samd:mkrwifi1010", "--format", "json") - require.NoError(t, err) - requirejson.Len(t, stdout, 1) - var data []map[string]interface{} - err = json.Unmarshal(stdout, &data) - require.NoError(t, err) - board := data[0] - require.Equal(t, board["name"], "Arduino MKR WiFi 1010") - require.Equal(t, board["fqbn"], "arduino:samd:mkrwifi1010") - samdCore := board["platform"].(map[string]interface{}) - require.Equal(t, samdCore["id"], "arduino:samd") - installedVersion, err := semver.Parse(samdCore["installed"].(string)) - require.NoError(t, err) - latestVersion, err := semver.Parse(samdCore["latest"].(string)) - require.NoError(t, err) - // Installed version must be older than latest - require.True(t, installedVersion.LessThan(latestVersion)) -} - func TestBoardListWithFailedBuiltinInstallation(t *testing.T) { env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) defer env.CleanUp() @@ -616,10 +603,14 @@ func TestBoardListWithFailedBuiltinInstallation(t *testing.T) { _, _, err = cli.Run("board", "list") require.NoError(t, err) + ext := "" + if runtime.GOOS == "windows" { + ext = ".exe" + } // remove files from serial-discovery directory to simulate a failed installation serialDiscovery, err := cli.DataDir().Join("packages", "builtin", "tools", "serial-discovery").ReadDir() require.NoError(t, err) - require.NoError(t, serialDiscovery[0].Join("serial-discovery.exe").Remove()) + require.NoError(t, serialDiscovery[0].Join("serial-discovery"+ext).Remove()) // board list should install serial-discovery again stdout, stderr, err := cli.Run("board", "list") diff --git a/internal/integrationtest/core/core_test.go b/internal/integrationtest/core/core_test.go index c5762d3beb6..c9db2e7701e 100644 --- a/internal/integrationtest/core/core_test.go +++ b/internal/integrationtest/core/core_test.go @@ -178,11 +178,11 @@ func TestCoreSearchNoArgs(t *testing.T) { require.Contains(t, lines, []string{"test:x86", "2.0.0", "test_core"}) numPlatforms := len(lines) - 1 - // same thing in JSON format, also check the number of platforms found is the same + // Same thing in JSON format, also check the number of platforms found is the same stdout, _, err = cli.Run("core", "search", "--format", "json") require.NoError(t, err) requirejson.Contains(t, stdout, `[{"id": "test:x86", "releases": { "2.0.0": {"name":"test_core"}}}]`) - requirejson.Query(t, stdout, "length", fmt.Sprint(numPlatforms)) + requirejson.Len(t, stdout, numPlatforms) // list all with additional urls, check the test core is there stdout, _, err = cli.Run("core", "search", "--additional-urls="+url.String()) @@ -191,17 +191,27 @@ func TestCoreSearchNoArgs(t *testing.T) { for _, v := range strings.Split(strings.TrimSpace(string(stdout)), "\n") { lines = append(lines, strings.Fields(strings.TrimSpace(v))) } - // Check the presence of test:x86@3.0.0 - require.Contains(t, lines, []string{"test:x86", "3.0.0", "test_core"}) + // Check the absence of test:x86@3.0.0 because it contains incompatible deps. The latest available should be the 2.0.0 + require.NotContains(t, lines, []string{"test:x86", "3.0.0", "test_core"}) + require.Contains(t, lines, []string{"test:x86", "2.0.0", "test_core"}) numPlatforms = len(lines) - 1 // same thing in JSON format, also check the number of platforms found is the same stdout, _, err = cli.Run("core", "search", "--format", "json", "--additional-urls="+url.String()) require.NoError(t, err) - requirejson.Contains(t, stdout, `[{"id": "test:x86", "releases": { "3.0.0": {"name":"test_core"}}}]`) - // A platform could contain multiple releases, we get the length of how many releases are present for each platform - // and we sum them to see if the expected numers matches. - requirejson.Query(t, stdout, `[.[].releases | length] | add`, fmt.Sprint(numPlatforms)) + requirejson.Contains(t, stdout, `[ + { + "id": "test:x86", + "installed_version": "2.0.0", + "latest_version": "2.0.0", + "releases": { + "1.0.0": {"name":"test_core", "compatible": true}, + "2.0.0": {"name":"test_core", "compatible": true}, + "3.0.0": {"name":"test_core", "compatible": false} + } + } + ]`) + requirejson.Len(t, stdout, numPlatforms) } func TestCoreUpdateIndexUrlNotFound(t *testing.T) { @@ -705,17 +715,17 @@ func TestCoreSearchSortedResults(t *testing.T) { for _, v := range lines { if strings.HasPrefix(v[2], "[DEPRECATED]") { deprecated = append(deprecated, v) - } else { - notDeprecated = append(notDeprecated, v) + continue } + notDeprecated = append(notDeprecated, v) } // verify that results are already sorted correctly require.True(t, sort.SliceIsSorted(deprecated, func(i, j int) bool { - return strings.ToLower(deprecated[i][2]) < strings.ToLower(deprecated[j][2]) + return strings.ToLower(deprecated[i][0]) < strings.ToLower(deprecated[j][0]) })) require.True(t, sort.SliceIsSorted(notDeprecated, func(i, j int) bool { - return strings.ToLower(notDeprecated[i][2]) < strings.ToLower(notDeprecated[j][2]) + return strings.ToLower(notDeprecated[i][0]) < strings.ToLower(notDeprecated[j][0]) })) // verify that deprecated platforms are the last ones @@ -727,20 +737,20 @@ func TestCoreSearchSortedResults(t *testing.T) { // verify that results are already sorted correctly sortedDeprecated := requirejson.Parse(t, stdout).Query( - "[ .[] | select(.deprecated == true) | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name] | sort").String() + "[ .[] | select(.deprecated == true) | .id |=ascii_downcase | .id] | sort").String() notSortedDeprecated := requirejson.Parse(t, stdout).Query( - "[ .[] | select(.deprecated == true) | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name]").String() + "[ .[] | select(.deprecated == true) | .id |=ascii_downcase | .id]").String() require.Equal(t, sortedDeprecated, notSortedDeprecated) sortedNotDeprecated := requirejson.Parse(t, stdout).Query( - "[ .[] | select(.deprecated != true) | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name] | sort").String() + "[ .[] | select(.deprecated != true) | .id |=ascii_downcase | .id] | sort").String() notSortedNotDeprecated := requirejson.Parse(t, stdout).Query( - "[ .[] | select(.deprecated != true) | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name]").String() + "[ .[] | select(.deprecated != true) | .id |=ascii_downcase | .id]").String() require.Equal(t, sortedNotDeprecated, notSortedNotDeprecated) // verify that deprecated platforms are the last ones platform := requirejson.Parse(t, stdout).Query( - "[ .[] | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name]").String() + "[ .[] | .id |=ascii_downcase | .id]").String() require.Equal(t, platform, strings.TrimRight(notSortedNotDeprecated, "]")+","+strings.TrimLeft(notSortedDeprecated, "[")) } @@ -783,10 +793,10 @@ func TestCoreListSortedResults(t *testing.T) { // verify that results are already sorted correctly require.True(t, sort.SliceIsSorted(deprecated, func(i, j int) bool { - return strings.ToLower(deprecated[i][3]) < strings.ToLower(deprecated[j][3]) + return strings.ToLower(deprecated[i][0]) < strings.ToLower(deprecated[j][0]) })) require.True(t, sort.SliceIsSorted(notDeprecated, func(i, j int) bool { - return strings.ToLower(notDeprecated[i][3]) < strings.ToLower(notDeprecated[j][3]) + return strings.ToLower(notDeprecated[i][0]) < strings.ToLower(notDeprecated[j][0]) })) // verify that deprecated platforms are the last ones @@ -799,20 +809,20 @@ func TestCoreListSortedResults(t *testing.T) { // verify that results are already sorted correctly sortedDeprecated := requirejson.Parse(t, stdout).Query( - "[ .[] | select(.deprecated == true) | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name] | sort").String() + "[ .[] | select(.deprecated == true) | .id |=ascii_downcase | .id] | sort").String() notSortedDeprecated := requirejson.Parse(t, stdout).Query( - "[ .[] | select(.deprecated == true) | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name]").String() + "[ .[] | select(.deprecated == true) | .id |=ascii_downcase | .id]").String() require.Equal(t, sortedDeprecated, notSortedDeprecated) sortedNotDeprecated := requirejson.Parse(t, stdout).Query( - "[ .[] | select(.deprecated != true) | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name] | sort").String() + "[ .[] | select(.deprecated != true) | .id |=ascii_downcase | .id] | sort").String() notSortedNotDeprecated := requirejson.Parse(t, stdout).Query( - "[ .[] | select(.deprecated != true) | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name]").String() + "[ .[] | select(.deprecated != true) | .id |=ascii_downcase | .id]").String() require.Equal(t, sortedNotDeprecated, notSortedNotDeprecated) // verify that deprecated platforms are the last ones platform := requirejson.Parse(t, stdout).Query( - "[ .[] | {name: .releases[.latest_version].name} | .name |=ascii_downcase | .name]").String() + "[ .[] | .id |=ascii_downcase | .id]").String() require.Equal(t, platform, strings.TrimRight(notSortedNotDeprecated, "]")+","+strings.TrimLeft(notSortedDeprecated, "[")) } @@ -1111,3 +1121,128 @@ func TestCoreListWhenNoPlatformAreInstalled(t *testing.T) { require.NoError(t, err) require.Equal(t, "No platforms installed.\n", string(stdout)) } + +func TestCoreHavingIncompatibleDepTools(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + url := env.HTTPServeFile(8000, paths.New("..", "testdata", "test_index.json")).String() + additionalURLs := "--additional-urls=" + url + + _, _, err := cli.Run("core", "update-index", additionalURLs) + require.NoError(t, err) + + // the `latest_version` must point to an installable release. In the releases field the latest entry, points to an incompatible version. + stdout, _, err := cli.Run("core", "list", "--all", "--format", "json", additionalURLs) + require.NoError(t, err) + requirejson.Parse(t, stdout). + Query(`.[] | select(.id == "foo_vendor:avr")`). + MustContain(`{ + "installed_version": "", + "latest_version": "1.0.1", + "releases": { + "1.0.0": {"compatible": true}, + "1.0.1": {"compatible": true}, + "1.0.2": {"compatible": false} + } + }`) + + // install latest compatible version + _, _, err = cli.Run("core", "install", "foo_vendor:avr", additionalURLs) + require.NoError(t, err) + stdout, _, err = cli.Run("core", "list", "--all", "--format", "json", additionalURLs) + require.NoError(t, err) + requirejson.Parse(t, stdout). + Query(`.[] | select(.id == "foo_vendor:avr")`). + MustContain(`{ + "latest_version": "1.0.1", + "installed_version": "1.0.1", + "releases": {"1.0.1": {"compatible": true}} + }`) + + // install a specific incompatible version + _, stderr, err := cli.Run("core", "install", "foo_vendor:avr@1.0.2", additionalURLs) + require.Error(t, err) + require.Contains(t, string(stderr), "no versions available for the current OS") + + // install a specific compatible version + _, _, err = cli.Run("core", "install", "foo_vendor:avr@1.0.0", additionalURLs) + require.NoError(t, err) + stdout, _, err = cli.Run("core", "list", "--format", "json", additionalURLs) + require.NoError(t, err) + requirejson.Parse(t, stdout). + Query(`.[] | select(.id == "foo_vendor:avr")`). + MustContain(`{"installed_version": "1.0.0", "releases": {"1.0.0": {"compatible": true}}}`) + + // Lists all updatable cores + stdout, _, err = cli.Run("core", "list", "--updatable", "--format", "json", additionalURLs) + require.NoError(t, err) + requirejson.Parse(t, stdout). + Query(`.[] | select(.id == "foo_vendor:avr")`). + MustContain(`{"latest_version": "1.0.1", "releases": {"1.0.1": {"compatible": true}}}`) + + // Show outdated cores, must show latest compatible + stdout, _, err = cli.Run("outdated", "--format", "json", additionalURLs) + require.NoError(t, err) + requirejson.Parse(t, stdout). + Query(`.platforms | .[] | select(.id == "foo_vendor:avr")`). + MustContain(`{"latest_version": "1.0.1", "releases":{"1.0.1": {"compatible": true}}}`) + + // upgrade to latest compatible (1.0.0 -> 1.0.1) + _, _, err = cli.Run("core", "upgrade", "foo_vendor:avr", "--format", "json", additionalURLs) + require.NoError(t, err) + stdout, _, err = cli.Run("core", "list", "--format", "json", additionalURLs) + require.NoError(t, err) + requirejson.Parse(t, stdout). + Query(`.[] | select(.id == "foo_vendor:avr") | .releases[.installed_version]`). + MustContain(`{"version": "1.0.1", "compatible": true}`) + + // upgrade to latest incompatible not possible (1.0.1 -> 1.0.2) + _, _, err = cli.Run("core", "upgrade", "foo_vendor:avr", "--format", "json", additionalURLs) + require.NoError(t, err) + stdout, _, err = cli.Run("core", "list", "--format", "json", additionalURLs) + require.NoError(t, err) + requirejson.Query(t, stdout, `.[] | select(.id == "foo_vendor:avr") | .installed_version`, `"1.0.1"`) + + // When no compatible version are found return error + // When trying to install a platform with no compatible version fails + _, stderr, err = cli.Run("core", "install", "incompatible_vendor:avr", additionalURLs) + require.Error(t, err) + require.Contains(t, string(stderr), "is not available for your OS") + + // Core search + { + // core search with and without --all produces the same results. + stdoutSearchAll, _, err := cli.Run("core", "search", "--all", "--format", "json", additionalURLs) + require.NoError(t, err) + stdoutSearch, _, err := cli.Run("core", "search", "--format", "json", additionalURLs) + require.NoError(t, err) + require.Equal(t, stdoutSearchAll, stdoutSearch) + for _, stdout := range [][]byte{stdoutSearchAll, stdoutSearch} { + requirejson.Parse(t, stdout). + Query(`.[] | select(.id == "foo_vendor:avr")`). + MustContain(`{ + "latest_version": "1.0.1", + "releases": { + "1.0.0": {"compatible": true}, + "1.0.1": {"compatible": true}, + "1.0.2": {"compatible": false} + } + }`) + requirejson.Parse(t, stdout). + Query(`.[] | select(.id == "incompatible_vendor:avr")`). + MustContain(`{"latest_version": "", "releases": { "1.0.0": {"compatible": false}}}`) + } + // In text mode, core search shows `n/a` for core that doesn't have any compatible version + stdout, _, err := cli.Run("core", "search", additionalURLs) + require.NoError(t, err) + var lines [][]string + for _, v := range strings.Split(strings.TrimSpace(string(stdout)), "\n") { + lines = append(lines, strings.Fields(strings.TrimSpace(v))) + if strings.Contains(v, "incompatible_vendor:avr") { + t.Log(strings.Fields(strings.TrimSpace(v))) + } + } + require.Contains(t, lines, []string{"incompatible_vendor:avr", "n/a", "Incompatible", "Boards"}) + } +} diff --git a/internal/integrationtest/testdata/test_index.json b/internal/integrationtest/testdata/test_index.json index 70de2ac0fee..95d38d202d4 100644 --- a/internal/integrationtest/testdata/test_index.json +++ b/internal/integrationtest/testdata/test_index.json @@ -236,6 +236,174 @@ ] } ] + }, + { + "name": "foo_vendor", + "maintainer": "Foo Developer", + "websiteURL": "http://example.com", + "email": "test@example.com", + "help": { + "online": "http://example.com" + }, + "platforms": [ + { + "name": "Foo Boards", + "architecture": "avr", + "version": "1.0.0", + "category": "Contributed", + "help": { + "online": "http://example.com" + }, + "url": "https://github.com/damellis/attiny/archive/702aa287455f7e052cf94fd4949398fec0ef21b8.zip", + "archiveFileName": "702aa287455f7e052cf94fd4949398fec0ef21b8.zip", + "checksum": "SHA-256:bfffa4a700e42ae993895f5eea22bc369ba5ac3ea36eca18ac5f72a05bb60ab5", + "size": "5005", + "boards": [], + "toolsDependencies": [ + { + "packager": "foo_vendor", + "name": "some_tool", + "version": "1.0.0" + } + ] + }, + { + "name": "Foo Boards", + "architecture": "avr", + "version": "1.0.1", + "category": "Contributed", + "help": { + "online": "http://example.com" + }, + "url": "https://github.com/damellis/attiny/archive/76ca88ce3c195fcba8e8a645084e352965dc80e0.zip", + "archiveFileName": "76ca88ce3c195fcba8e8a645084e352965dc80e0.zip", + "checksum": "SHA-256:49a4dfc3796caf2533050b0b962ae0affb2471b8ded1283936d7b712cc1fdff1", + "size": "5719", + "boards": [], + "toolsDependencies": [ + { + "packager": "foo_vendor", + "name": "some_tool", + "version": "1.0.0" + } + ] + }, + { + "name": "Foo Boards", + "architecture": "avr", + "version": "1.0.2", + "category": "Contributed", + "help": { + "online": "http://example.com" + }, + "url": "https://github.com/damellis/attiny/archive/76ca88ce3c195fcba8e8a645084e352965dc80e0.zip", + "archiveFileName": "76ca88ce3c195fcba8e8a645084e352965dc80e0.zip", + "checksum": "SHA-256:49a4dfc3796caf2533050b0b962ae0affb2471b8ded1283936d7b712cc1fdff1", + "size": "5719", + "boards": [], + "toolsDependencies": [ + { + "packager": "foo_vendor", + "name": "incompatible_tool", + "version": "2.0.0" + } + ] + } + ], + "tools": [ + { + "name": "some_tool", + "version": "1.0.0", + "systems": [ + { + "size": "219631", + "checksum": "SHA-256:2a8e68c5d803aa6f902ef219f177ec3a4c28275d85cbe272962ad2cd374f50d1", + "host": "arm-linux-gnueabihf", + "archiveFileName": "avrdude-6.3.0-arduino17-armhf-pc-linux-gnu.tar.bz2", + "url": "http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino17-armhf-pc-linux-gnu.tar.bz2" + }, + { + "size": "229852", + "checksum": "SHA-256:6cf948f751acfe7b96684537f2291c766ec8b54b4f7dc95539864821456fa9fc", + "host": "aarch64-linux-gnu", + "archiveFileName": "avrdude-6.3.0-arduino17-aarch64-pc-linux-gnu.tar.bz2", + "url": "http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino17-aarch64-pc-linux-gnu.tar.bz2" + }, + { + "size": "279045", + "checksum": "SHA-256:120cc9edaae699e7e9ac50b1b8eb0e7d51fdfa555bac54233c2511e6ee5418c9", + "host": "x86_64-apple-darwin12", + "archiveFileName": "avrdude-6.3.0-arduino17-x86_64-apple-darwin12.tar.bz2", + "url": "http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino17-x86_64-apple-darwin12.tar.bz2" + }, + { + "size": "254271", + "checksum": "SHA-256:accdfb920af2aabf4f7461d2ac73c0751760f525216dc4e7657427a78c60d13d", + "host": "x86_64-linux-gnu", + "archiveFileName": "avrdude-6.3.0-arduino17-x86_64-pc-linux-gnu.tar.bz2", + "url": "http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino17-x86_64-pc-linux-gnu.tar.bz2" + }, + { + "size": "244550", + "checksum": "SHA-256:5c8cc6c17db9300e1451fe41cd7178b0442b4490ee6fdbc0aed9811aef96c05f", + "host": "i686-linux-gnu", + "archiveFileName": "avrdude-6.3.0-arduino17-i686-pc-linux-gnu.tar.bz2", + "url": "http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino17-i686-pc-linux-gnu.tar.bz2" + }, + { + "size": "328460", + "checksum": "SHA-256:e99188873c7c5ad8f8f906f068c33600e758b2e36cce3adbd518a21bd266749d", + "host": "i686-mingw32", + "archiveFileName": "avrdude-6.3.0-arduino17-i686-w64-mingw32.zip", + "url": "http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino17-i686-w64-mingw32.zip" + } + ] + }, + { + "name": "incompatible_tool", + "version": "2.0.0", + "systems": [] + } + ] + }, + { + "name": "incompatible_vendor", + "maintainer": "Incompatible Developer", + "websiteURL": "http://example.com", + "email": "test@example.com", + "help": { + "online": "http://example.com" + }, + "platforms": [ + { + "name": "Incompatible Boards", + "architecture": "avr", + "version": "1.0.0", + "category": "Contributed", + "help": { + "online": "http://example.com" + }, + "url": "https://github.com/damellis/attiny/archive/702aa287455f7e052cf94fd4949398fec0ef21b8.zip", + "archiveFileName": "702aa287455f7e052cf94fd4949398fec0ef21b8.zip", + "checksum": "SHA-256:bfffa4a700e42ae993895f5eea22bc369ba5ac3ea36eca18ac5f72a05bb60ab5", + "size": "5005", + "boards": [], + "toolsDependencies": [ + { + "packager": "incompatible_vendor", + "name": "incompatible_tool", + "version": "2.0.0" + } + ] + } + ], + "tools": [ + { + "name": "incompatible_tool", + "version": "2.0.0", + "systems": [] + } + ] } ] } diff --git a/rpc/cc/arduino/cli/commands/v1/common.pb.go b/rpc/cc/arduino/cli/commands/v1/common.pb.go index fe1f4e1f700..28bc1b6ed68 100644 --- a/rpc/cc/arduino/cli/commands/v1/common.pb.go +++ b/rpc/cc/arduino/cli/commands/v1/common.pb.go @@ -560,7 +560,8 @@ type PlatformSummary struct { Releases map[string]*PlatformRelease `protobuf:"bytes,2,rep,name=releases,proto3" json:"releases,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // The installed version of the platform, or empty string if none installed InstalledVersion string `protobuf:"bytes,3,opt,name=installed_version,json=installedVersion,proto3" json:"installed_version,omitempty"` - // The latest available version of the platform, or empty if none available + // The latest available version of the platform that can be installable, or + // empty if none available. LatestVersion string `protobuf:"bytes,4,opt,name=latest_version,json=latestVersion,proto3" json:"latest_version,omitempty"` } @@ -761,6 +762,9 @@ type PlatformRelease struct { MissingMetadata bool `protobuf:"varint,7,opt,name=missing_metadata,json=missingMetadata,proto3" json:"missing_metadata,omitempty"` // True this release is deprecated Deprecated bool `protobuf:"varint,8,opt,name=deprecated,proto3" json:"deprecated,omitempty"` + // True if the platform dependencies are available for the current OS/ARCH. + // This also means that the platform is installable. + Compatible bool `protobuf:"varint,9,opt,name=compatible,proto3" json:"compatible,omitempty"` } func (x *PlatformRelease) Reset() { @@ -851,6 +855,13 @@ func (x *PlatformRelease) GetDeprecated() bool { return false } +func (x *PlatformRelease) GetCompatible() bool { + if x != nil { + return x.Compatible + } + return false +} + type InstalledPlatformReference struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1188,7 +1199,7 @@ var file_cc_arduino_cli_commands_v1_common_proto_rawDesc = []byte{ 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x22, 0xb6, 0x02, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x22, 0xd6, 0x02, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, @@ -1208,6 +1219,8 @@ var file_cc_arduino_cli_commands_v1_common_proto_rawDesc = []byte{ 0x0f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x88, 0x01, 0x0a, 0x1a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, diff --git a/rpc/cc/arduino/cli/commands/v1/common.proto b/rpc/cc/arduino/cli/commands/v1/common.proto index fae80bab09b..9a324985d54 100644 --- a/rpc/cc/arduino/cli/commands/v1/common.proto +++ b/rpc/cc/arduino/cli/commands/v1/common.proto @@ -89,7 +89,8 @@ message PlatformSummary { map releases = 2; // The installed version of the platform, or empty string if none installed string installed_version = 3; - // The latest available version of the platform, or empty if none available + // The latest available version of the platform that can be installable, or + // empty if none available. string latest_version = 4; } @@ -141,6 +142,9 @@ message PlatformRelease { bool missing_metadata = 7; // True this release is deprecated bool deprecated = 8; + // True if the platform dependencies are available for the current OS/ARCH. + // This also means that the platform is installable. + bool compatible = 9; } message InstalledPlatformReference { diff --git a/rpc/cc/arduino/cli/commands/v1/core.pb.go b/rpc/cc/arduino/cli/commands/v1/core.pb.go index dca289c80fd..6c3bcb7c5ed 100644 --- a/rpc/cc/arduino/cli/commands/v1/core.pb.go +++ b/rpc/cc/arduino/cli/commands/v1/core.pb.go @@ -682,12 +682,9 @@ type PlatformSearchRequest struct { Instance *Instance `protobuf:"bytes,1,opt,name=instance,proto3" json:"instance,omitempty"` // Keywords for the search. SearchArgs string `protobuf:"bytes,2,opt,name=search_args,json=searchArgs,proto3" json:"search_args,omitempty"` - // Whether to show all available versions. `false` causes only the newest - // versions of the cores to be listed in the search results. - AllVersions bool `protobuf:"varint,3,opt,name=all_versions,json=allVersions,proto3" json:"all_versions,omitempty"` // Whether to show manually installed platforms. `false` causes to skip // manually installed platforms. - ManuallyInstalled bool `protobuf:"varint,4,opt,name=manually_installed,json=manuallyInstalled,proto3" json:"manually_installed,omitempty"` + ManuallyInstalled bool `protobuf:"varint,3,opt,name=manually_installed,json=manuallyInstalled,proto3" json:"manually_installed,omitempty"` } func (x *PlatformSearchRequest) Reset() { @@ -736,13 +733,6 @@ func (x *PlatformSearchRequest) GetSearchArgs() string { return "" } -func (x *PlatformSearchRequest) GetAllVersions() bool { - if x != nil { - return x.AllVersions - } - return false -} - func (x *PlatformSearchRequest) GetManuallyInstalled() bool { if x != nil { return x.ManuallyInstalled @@ -913,7 +903,7 @@ var file_cc_arduino_cli_commands_v1_core_proto_rawDesc = []byte{ 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0xcc, 0x01, + 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0xa9, 0x01, 0x0a, 0x15, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, @@ -921,24 +911,22 @@ var file_cc_arduino_cli_commands_v1_core_proto_rawDesc = []byte{ 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x72, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6c, - 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2d, 0x0a, - 0x12, 0x6d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, - 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6d, 0x61, 0x6e, 0x75, 0x61, - 0x6c, 0x6c, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x22, 0x6a, 0x0a, 0x16, - 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, - 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x0c, 0x73, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, - 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, - 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x72, 0x67, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x6d, 0x61, + 0x6e, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x6c, 0x79, + 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x22, 0x6a, 0x0a, 0x16, 0x50, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x63, 0x2e, + 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, + 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x0c, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, + 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, + 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/rpc/cc/arduino/cli/commands/v1/core.proto b/rpc/cc/arduino/cli/commands/v1/core.proto index 67aa0b214c7..e44331dada8 100644 --- a/rpc/cc/arduino/cli/commands/v1/core.proto +++ b/rpc/cc/arduino/cli/commands/v1/core.proto @@ -115,12 +115,9 @@ message PlatformSearchRequest { Instance instance = 1; // Keywords for the search. string search_args = 2; - // Whether to show all available versions. `false` causes only the newest - // versions of the cores to be listed in the search results. - bool all_versions = 3; // Whether to show manually installed platforms. `false` causes to skip // manually installed platforms. - bool manually_installed = 4; + bool manually_installed = 3; } message PlatformSearchResponse {