diff --git a/commands/board/listall.go b/commands/board/listall.go index 78f945ea864..afa0d78b540 100644 --- a/commands/board/listall.go +++ b/commands/board/listall.go @@ -17,9 +17,11 @@ package board import ( "context" + "sort" "strings" "github.com/arduino/arduino-cli/arduino" + "github.com/arduino/arduino-cli/arduino/cores" "github.com/arduino/arduino-cli/arduino/utils" "github.com/arduino/arduino-cli/commands" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" @@ -36,8 +38,8 @@ func ListAll(ctx context.Context, req *rpc.BoardListAllRequest) (*rpc.BoardListA searchArgs := strings.Join(req.GetSearchArgs(), " ") list := &rpc.BoardListAllResponse{Boards: []*rpc.BoardListItem{}} - for _, targetPackage := range pme.GetPackages() { - for _, platform := range targetPackage.Platforms { + for _, targetPackage := range toSortedPackageArray(pme.GetPackages()) { + for _, platform := range toSortedPlatformArray(targetPackage.Platforms) { installedPlatformRelease := pme.GetInstalledPlatformRelease(platform) // We only want to list boards for installed platforms if installedPlatformRelease == nil { @@ -93,3 +95,37 @@ func ListAll(ctx context.Context, req *rpc.BoardListAllRequest) (*rpc.BoardListA return list, nil } + +// TODO use a generic function instead of the two below once go >1.18 is adopted. +// Without generics we either have to create multiple functions for different map types +// or resort to type assertions on the caller side + +// toSortedPackageArray takes a packages map and returns its values as array +// ordered by the map keys alphabetically +func toSortedPackageArray(sourceMap cores.Packages) []*cores.Package { + keys := []string{} + for key := range sourceMap { + keys = append(keys, key) + } + sort.Strings(keys) + sortedValues := make([]*cores.Package, len(keys)) + for i, key := range keys { + sortedValues[i] = sourceMap[key] + } + return sortedValues +} + +// toSortedPlatformArray takes a packages map and returns its values as array +// ordered by the map keys alphabetically +func toSortedPlatformArray(sourceMap map[string]*cores.Platform) []*cores.Platform { + keys := []string{} + for key := range sourceMap { + keys = append(keys, key) + } + sort.Strings(keys) + sortedValues := make([]*cores.Platform, len(keys)) + for i, key := range keys { + sortedValues[i] = sourceMap[key] + } + return sortedValues +} diff --git a/internal/integrationtest/board/board_test.go b/internal/integrationtest/board/board_test.go index b3ac071ddb4..14fbf9ebfd0 100644 --- a/internal/integrationtest/board/board_test.go +++ b/internal/integrationtest/board/board_test.go @@ -33,7 +33,10 @@ func TestCorrectBoardListOrdering(t *testing.T) { env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) defer env.CleanUp() - _, _, err := cli.Run("core", "install", "arduino:avr") + // install two cores, boards must be ordered by package name and platform name + _, _, err := cli.Run("core", "install", "arduino:sam") + require.NoError(t, err) + _, _, err = cli.Run("core", "install", "arduino:avr") require.NoError(t, err) jsonOut, _, err := cli.Run("board", "listall", "--format", "json") require.NoError(t, err) @@ -64,7 +67,9 @@ func TestCorrectBoardListOrdering(t *testing.T) { "arduino:avr:yunmini", "arduino:avr:chiwawa", "arduino:avr:one", - "arduino:avr:unowifi" + "arduino:avr:unowifi", + "arduino:sam:arduino_due_x_dbg", + "arduino:sam:arduino_due_x" ]`) }