Skip to content

Commit 34e0cc7

Browse files
authored
Implemented "latest" field in 'firmware list' command (#52)
* Remove code duplication in LoadIndex * Using semver.RelaxedVersion for struct field * Latest firmware for each board is determined at load time * Implemented latest field in 'firmware list' * Fixed tests oppps
1 parent 4d7a0d2 commit 34e0cc7

File tree

3 files changed

+48
-44
lines changed

3 files changed

+48
-44
lines changed

cli/firmware/list.go

+12-6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/arduino/arduino-cli/cli/feedback"
2727
"github.com/arduino/arduino-cli/table"
2828
"github.com/spf13/cobra"
29+
semver "go.bug.st/relaxed-semver"
2930
)
3031

3132
func newListCommand() *cobra.Command {
@@ -46,10 +47,10 @@ func newListCommand() *cobra.Command {
4647
}
4748

4849
type FirmwareResult struct {
49-
BoardName string `json:"board_name"`
50-
BoardFQBN string `json:"board_fqbn"`
51-
Module string `json:"module"`
52-
FirmwareVersion string `json:"firmware_version"`
50+
BoardName string `json:"board_name"`
51+
BoardFQBN string `json:"board_fqbn"`
52+
Module string `json:"module"`
53+
FirmwareVersion *semver.RelaxedVersion `json:"firmware_version"`
5354
Latest bool
5455
}
5556

@@ -70,6 +71,7 @@ func list(fqbn string) {
7071
BoardFQBN: board.Fqbn,
7172
Module: board.Module,
7273
FirmwareVersion: firmware.Version,
74+
Latest: board.Latest == firmware,
7375
})
7476
}
7577
}
@@ -83,9 +85,13 @@ func (f FirmwareListResult) String() string {
8385
return "No firmwares available."
8486
}
8587
t := table.New()
86-
t.SetHeader("Board", "FQBN", "Module", "Version")
88+
t.SetHeader("Board", "FQBN", "Module", "", "Version")
8789
for _, fw := range f {
88-
t.AddRow(fw.BoardName, fw.BoardFQBN, fw.Module, fw.FirmwareVersion)
90+
latest := ""
91+
if fw.Latest {
92+
latest = "✔"
93+
}
94+
t.AddRow(fw.BoardName, fw.BoardFQBN, fw.Module, latest, fw.FirmwareVersion)
8995
}
9096
return t.Render()
9197
}

indexes/download/download.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func DownloadFirmware(firmware *firmwareindex.IndexFirmware) (*paths.Path, error
7777
firmwarePath := globals.FwUploaderPath.Join(
7878
"firmwares",
7979
firmware.Module,
80-
firmware.Version,
80+
firmware.Version.String(),
8181
path.Base(firmware.URL))
8282
firmwarePath.Parent().MkdirAll()
8383
if err := firmwarePath.WriteFile(nil); err != nil {

indexes/firmwareindex/firmwareindex.go

+35-37
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ type IndexBoard struct {
4848
UploadTouch bool `json:"upload.use_1200bps_touch"`
4949
UploadWait bool `json:"upload.wait_for_upload_port"`
5050
UploaderCommand *IndexUploaderCommand `json:"uploader.command,required"`
51+
Latest *IndexFirmware `json:"-"`
5152
}
5253

5354
type IndexUploaderCommand struct {
@@ -58,11 +59,11 @@ type IndexUploaderCommand struct {
5859

5960
// IndexFirmware represents a single Firmware version from module_firmware_index.json file.
6061
type IndexFirmware struct {
61-
Version string `json:"version,required"` // `*semver.Version` but with SARA version is giving problems
62-
URL string `json:"url,required"`
63-
Checksum string `json:"checksum,required"`
64-
Size json.Number `json:"size,required"`
65-
Module string `json:"module,required"`
62+
Version *semver.RelaxedVersion `json:"version,required"`
63+
URL string `json:"url,required"`
64+
Checksum string `json:"checksum,required"`
65+
Size json.Number `json:"size,required"`
66+
Module string `json:"module,required"`
6667
}
6768

6869
// IndexLoaderSketch represents the sketch used to upload the new firmware on a board.
@@ -74,12 +75,7 @@ type IndexLoaderSketch struct {
7475

7576
// LoadIndex reads a module_firmware_index.json from a file and returns the corresponding Index structure.
7677
func LoadIndex(jsonIndexFile *paths.Path) (*Index, error) {
77-
buff, err := jsonIndexFile.ReadFile()
78-
if err != nil {
79-
return nil, err
80-
}
81-
var index Index
82-
err = json.Unmarshal(buff, &index.Boards)
78+
index, err := LoadIndexNoSign(jsonIndexFile)
8379
if err != nil {
8480
return nil, err
8581
}
@@ -93,20 +89,21 @@ func LoadIndex(jsonIndexFile *paths.Path) (*Index, error) {
9389
if err != nil {
9490
return nil, err
9591
}
92+
9693
trusted, _, err := security.VerifySignature(jsonIndexFile, jsonSignatureFile, key)
9794
if err != nil {
9895
logrus.
9996
WithField("index", jsonIndexFile).
10097
WithField("signatureFile", jsonSignatureFile).
10198
WithError(err).Infof("Checking signature")
102-
} else {
103-
logrus.
104-
WithField("index", jsonIndexFile).
105-
WithField("signatureFile", jsonSignatureFile).
106-
WithField("trusted", trusted).Infof("Checking signature")
107-
index.IsTrusted = trusted
99+
return nil, err
108100
}
109-
return &index, nil
101+
logrus.
102+
WithField("index", jsonIndexFile).
103+
WithField("signatureFile", jsonSignatureFile).
104+
WithField("trusted", trusted).Infof("Checking signature")
105+
index.IsTrusted = trusted
106+
return index, nil
110107
}
111108

112109
// LoadIndexNoSign reads a module_firmware_index.json from a file and returns the corresponding Index structure.
@@ -123,6 +120,19 @@ func LoadIndexNoSign(jsonIndexFile *paths.Path) (*Index, error) {
123120

124121
index.IsTrusted = true
125122

123+
// Determine latest firmware for each board
124+
for _, board := range index.Boards {
125+
if board.Module == "SARA" {
126+
// TODO implement?? by defualt you have to specify the version
127+
continue
128+
}
129+
for _, firmware := range board.Firmwares {
130+
if board.Latest == nil || firmware.Version.GreaterThan(board.Latest.Version) {
131+
board.Latest = firmware
132+
}
133+
}
134+
}
135+
126136
return &index, nil
127137
}
128138

@@ -133,40 +143,28 @@ func (i *Index) GetLatestFirmwareURL(fqbn string) (string, error) {
133143
if board == nil {
134144
return "", fmt.Errorf("invalid FQBN: %s", fqbn)
135145
}
136-
if board.Module == "SARA" { // TODO togliere sara, lo assumo giá nel comando
137-
// TODO implement?? by defualt you have to specify the version
138-
return "", fmt.Errorf("not implemented for SARA module")
139-
}
140146

141-
var latestVersion *semver.RelaxedVersion
142-
var latestFirmwareURL string
143-
for _, firmware := range board.Firmwares {
144-
version := semver.ParseRelaxed(firmware.Version)
145-
if latestVersion == nil || version.GreaterThan(latestVersion) { // TODO check the condition
146-
latestVersion = version
147-
latestFirmwareURL = firmware.URL
148-
}
149-
}
150-
if latestVersion != nil {
151-
return latestFirmwareURL, nil
152-
} else {
147+
if board.Latest == nil {
153148
return "", fmt.Errorf("cannot find latest version")
154149
}
150+
151+
return board.Latest.URL, nil
155152
}
156153

157154
// GetFirmwareURL will take the fqbn of the required board and the version of the firmware as parameters.
158155
// It will return the URL of the required firmware
159-
func (i *Index) GetFirmwareURL(fqbn, version string) (string, error) {
156+
func (i *Index) GetFirmwareURL(fqbn, v string) (string, error) {
160157
board := i.GetBoard(fqbn)
161158
if board == nil {
162159
return "", fmt.Errorf("invalid FQBN: %s", fqbn)
163160
}
161+
version := semver.ParseRelaxed(v)
164162
for _, firmware := range board.Firmwares {
165-
if firmware.Version == version {
163+
if firmware.Version.Equal(version) {
166164
return firmware.URL, nil
167165
}
168166
}
169-
return "", fmt.Errorf("invalid version: %s", version)
167+
return "", fmt.Errorf("version not found: %s", version)
170168
}
171169

172170
// GetLoaderSketchURL will take the board's fqbn and return the url of the loader sketch

0 commit comments

Comments
 (0)