diff --git a/arduino/cores/cores.go b/arduino/cores/cores.go index 3201112d50b..69669efff4b 100644 --- a/arduino/cores/cores.go +++ b/arduino/cores/cores.go @@ -63,6 +63,7 @@ type PlatformRelease struct { Platform *Platform `json:"-"` Properties *properties.Map `json:"-"` Boards map[string]*Board `json:"-"` + orderedBoards []*Board `json:"-"` // The Boards of this platform, in the order they are defined in the boards.txt file. Programmers map[string]*Programmer `json:"-"` Menus *properties.Map `json:"-"` InstallDir *paths.Path `json:"-"` @@ -292,9 +293,16 @@ func (release *PlatformRelease) GetOrCreateBoard(boardID string) *Board { PlatformRelease: release, } release.Boards[boardID] = board + release.orderedBoards = append(release.orderedBoards, board) return board } +// GetBoards returns the boards in this platforms in the order they +// are defined in the platform.txt file. +func (release *PlatformRelease) GetBoards() []*Board { + return release.orderedBoards +} + // RequiresToolRelease returns true if the PlatformRelease requires the // toolReleased passed as parameter func (release *PlatformRelease) RequiresToolRelease(toolRelease *ToolRelease) bool { diff --git a/arduino/cores/packagemanager/loader.go b/arduino/cores/packagemanager/loader.go index 75d04d9ecdb..298669186fb 100644 --- a/arduino/cores/packagemanager/loader.go +++ b/arduino/cores/packagemanager/loader.go @@ -470,18 +470,15 @@ func (pm *Builder) loadBoards(platform *cores.PlatformRelease) error { return err } - propertiesByBoard := boardsProperties.FirstLevelOf() + platform.Menus = boardsProperties.SubTree("menu") - if menus, ok := propertiesByBoard["menu"]; ok { - platform.Menus = menus - } else { - platform.Menus = properties.NewMap() - } - // This is not a board id so we remove it to correctly - // set all other boards properties - delete(propertiesByBoard, "menu") - - for boardID, boardProperties := range propertiesByBoard { + // Build to boards structure following the boards.txt board ordering + for _, boardID := range boardsProperties.FirstLevelKeys() { + if boardID == "menu" { + // This is not a board id so we remove it to correctly set all other boards properties + continue + } + boardProperties := boardsProperties.SubTree(boardID) var board *cores.Board if !platform.PluggableDiscoveryAware { convertVidPidIdentificationPropertiesToPluggableDiscovery(boardProperties) diff --git a/arduino/cores/packagemanager/package_manager_test.go b/arduino/cores/packagemanager/package_manager_test.go index 05a18e5ce72..580311d3225 100644 --- a/arduino/cores/packagemanager/package_manager_test.go +++ b/arduino/cores/packagemanager/package_manager_test.go @@ -218,6 +218,56 @@ func TestBoardOptionsFunctions(t *testing.T) { } } +func TestBoardOrdering(t *testing.T) { + pmb := packagemanager.NewBuilder(dataDir1, dataDir1.Join("packages"), nil, nil, "") + _ = pmb.LoadHardwareFromDirectories(paths.NewPathList(dataDir1.Join("packages").String())) + pm := pmb.Build() + pme, release := pm.NewExplorer() + defer release() + + pl := pme.FindPlatform(&packagemanager.PlatformReference{ + Package: "arduino", + PlatformArchitecture: "avr", + }) + require.NotNil(t, pl) + plReleases := pl.GetAllInstalled() + require.NotEmpty(t, plReleases) + avr := plReleases[0] + res := []string{} + for _, board := range avr.GetBoards() { + res = append(res, board.Name()) + } + expected := []string{ + "Arduino Yún", + "Arduino Uno", + "Arduino Duemilanove or Diecimila", + "Arduino Nano", + "Arduino Mega or Mega 2560", + "Arduino Mega ADK", + "Arduino Leonardo", + "Arduino Leonardo ETH", + "Arduino Micro", + "Arduino Esplora", + "Arduino Mini", + "Arduino Ethernet", + "Arduino Fio", + "Arduino BT", + "LilyPad Arduino USB", + "LilyPad Arduino", + "Arduino Pro or Pro Mini", + "Arduino NG or older", + "Arduino Robot Control", + "Arduino Robot Motor", + "Arduino Gemma", + "Adafruit Circuit Playground", + "Arduino Yún Mini", + "Arduino Industrial 101", + "Linino One", + "Arduino Uno WiFi", + } + require.Equal(t, expected, res) +} + func TestFindToolsRequiredForBoard(t *testing.T) { os.Setenv("ARDUINO_DATA_DIR", dataDir1.String()) configuration.Settings = configuration.Init("") diff --git a/commands/board/listall.go b/commands/board/listall.go index d18784f9581..78f945ea864 100644 --- a/commands/board/listall.go +++ b/commands/board/listall.go @@ -70,7 +70,7 @@ func ListAll(ctx context.Context, req *rpc.BoardListAllRequest) (*rpc.BoardListA targetPackage.Maintainer, } - for _, board := range installedPlatformRelease.Boards { + for _, board := range installedPlatformRelease.GetBoards() { if !req.GetIncludeHiddenBoards() && board.IsHidden() { continue } diff --git a/internal/integrationtest/board/board_list_test.go b/internal/integrationtest/board/board_list_test.go new file mode 100644 index 00000000000..12b60497171 --- /dev/null +++ b/internal/integrationtest/board/board_list_test.go @@ -0,0 +1,63 @@ +// This file is part of arduino-cli. +// +// Copyright 2022 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to +// modify or otherwise use the software for commercial activities involving the +// Arduino software without disclosing the source code of your own applications. +// To purchase a commercial license, send an email to license@arduino.cc. + +package board_test + +import ( + "testing" + + "github.com/arduino/arduino-cli/internal/integrationtest" + "github.com/stretchr/testify/require" + "go.bug.st/testifyjson/requirejson" +) + +func TestCorrectBoardListOrdering(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("core", "install", "arduino:avr") + require.NoError(t, err) + jsonOut, _, err := cli.Run("board", "listall", "--format", "json") + require.NoError(t, err) + requirejson.Query(t, jsonOut, "[.boards[] | .fqbn]", `[ + "arduino:avr:yun", + "arduino:avr:uno", + "arduino:avr:unomini", + "arduino:avr:diecimila", + "arduino:avr:nano", + "arduino:avr:mega", + "arduino:avr:megaADK", + "arduino:avr:leonardo", + "arduino:avr:leonardoeth", + "arduino:avr:micro", + "arduino:avr:esplora", + "arduino:avr:mini", + "arduino:avr:ethernet", + "arduino:avr:fio", + "arduino:avr:bt", + "arduino:avr:LilyPadUSB", + "arduino:avr:lilypad", + "arduino:avr:pro", + "arduino:avr:atmegang", + "arduino:avr:robotControl", + "arduino:avr:robotMotor", + "arduino:avr:gemma", + "arduino:avr:circuitplay32u4cat", + "arduino:avr:yunmini", + "arduino:avr:chiwawa", + "arduino:avr:one", + "arduino:avr:unowifi" + ]`) +}