Skip to content

Commit 5d56b1a

Browse files
committed
Add the preservation supported flag
2 parents ed2abde + 0ca5cf8 commit 5d56b1a

File tree

2 files changed

+47
-84
lines changed

2 files changed

+47
-84
lines changed

pkg/flasherapi/flasherapi.go

Lines changed: 27 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,56 @@
1616
package flasherapi
1717

1818
import (
19+
"bufio"
1920
"context"
21+
"io"
2022
"log/slog"
2123
"strings"
2224

2325
"github.com/arduino/arduino-app-cli/pkg/board/remote"
2426
)
2527

28+
const R0_IMAGE_VERSION_ID = "20250807-136"
29+
2630
// GetOSImageVersion returns the version of the OS image used in the board.
2731
// It is used by the AppLab to enforce image version compatibility.
28-
func GetOSImageVersion(ctx context.Context, conn remote.RemoteConn) (string, error) {
29-
const defaultVersion = "20250807-136"
32+
func GetOSImageVersion(ctx context.Context, conn remote.RemoteConn) string {
3033

31-
output, err := conn.GetCmd("cat /etc/buildinfo").Output(ctx)
34+
f, err := conn.ReadFile("/etc/buildinfo")
3235
if err != nil {
33-
return defaultVersion, err
36+
slog.Warn("Unable to read buildinfo file", "err", err, "using_default", R0_IMAGE_VERSION_ID)
37+
return R0_IMAGE_VERSION_ID
3438
}
39+
defer f.Close()
3540

36-
if version, ok := ParseOSImageVersion(string(output)); ok {
37-
slog.Info("find OS Image version", "version", version)
38-
return version, nil
41+
if version, ok := parseOSImageVersion(f); ok {
42+
slog.Info("found OS Image version", "version", version)
43+
return version
3944
}
40-
slog.Info("Unable to find OS Image version", "using default version", defaultVersion)
41-
return defaultVersion, nil
45+
slog.Warn("Unable to find OS Image version", "using_default", R0_IMAGE_VERSION_ID)
46+
return R0_IMAGE_VERSION_ID
4247
}
4348

44-
func ParseOSImageVersion(buildInfo string) (string, bool) {
45-
for _, line := range strings.Split(buildInfo, "\n") {
46-
line = strings.TrimSpace(line)
49+
func parseOSImageVersion(r io.Reader) (string, bool) {
50+
scanner := bufio.NewScanner(r)
51+
for scanner.Scan() {
52+
line := strings.TrimSpace(scanner.Text())
4753

4854
key, value, ok := strings.Cut(line, "=")
4955
if !ok || key != "BUILD_ID" {
5056
continue
5157
}
5258

53-
version := strings.Trim(value, "\"' ")
59+
version := strings.Trim(value, `"' `)
5460
if version != "" {
5561
return version, true
5662
}
5763
}
64+
65+
if err := scanner.Err(); err != nil {
66+
return "", false
67+
}
68+
5869
return "", false
5970
}
6071

@@ -64,77 +75,11 @@ type OSImageRelease struct {
6475
Latest bool
6576
}
6677

67-
func ListAvailableOSImages() []OSImageRelease {
68-
return []OSImageRelease{
69-
{
70-
ID: "20251123-159",
71-
VersionLabel: "r159 (2025-11-23)",
72-
Latest: true,
73-
},
74-
}
75-
}
76-
77-
const R0_IMAGE_VERSION_ID = "20250807-136"
78-
7978
// Calculates whether user partition preservation is supported,
8079
// according to the current and target OS image versions.
8180
//
8281
// Preservation is supported if both versions are not the R0 image.
83-
func IsUserPartitionPreservationSupported(ctx context.Context, conn remote.RemoteConn, targetImageVersion OSImageRelease) (bool, error) {
84-
currentImageVersion, err := GetOSImageVersion(ctx, conn)
85-
if err != nil {
86-
return false, err
87-
}
88-
return !(targetImageVersion.ID == R0_IMAGE_VERSION_ID || currentImageVersion == R0_IMAGE_VERSION_ID), err
89-
}
90-
91-
type FlashStep string
92-
93-
const (
94-
FlashStepPrecheck FlashStep = "precheck"
95-
FlashStepDetection FlashStep = "detection"
96-
FlashStepDownloading FlashStep = "downloading"
97-
FlashStepExtracting FlashStep = "extracting"
98-
FlashStepFlashing FlashStep = "flashing"
99-
)
100-
101-
type FlashEvent struct {
102-
Step FlashStep
103-
OverallProgress int // percentage 0-100
104-
Message string // log message to show on the UI
105-
}
106-
107-
func Flash(
108-
ctx context.Context, // context to cancel to interrupt the flashing process
109-
// conn remote.RemoteConn, // is this required for the flash process?
110-
imageVersion OSImageRelease, // OS image version to flash
111-
preserveUserPartition bool, // whether to preserve the user partition or not
112-
eventCB func(event FlashEvent), // Callback, sends progress events to the caller
113-
) error {
114-
// The disk space check is done before starting the flashing process.
115-
return InsufficientDiskSpaceError{
116-
RequiredSpaceMB: 2048,
117-
AvailableSpaceMB: 1024,
118-
}
119-
}
120-
121-
// Errors returned by the Flash function above.
122-
// Assertions can be done on the caller side to show better error messages.
123-
124-
type QDLFlashError struct {
125-
Details string
126-
Cause error
127-
}
128-
129-
type DownloadError struct {
130-
Details string
131-
}
132-
133-
type InsufficientDiskSpaceError struct {
134-
RequiredSpaceMB int64
135-
AvailableSpaceMB int64
136-
}
137-
138-
func (e InsufficientDiskSpaceError) Error() string {
139-
return "insufficient disk space"
82+
func IsUserPartitionPreservationSupported(ctx context.Context, conn remote.RemoteConn, targetImageVersion OSImageRelease) bool {
83+
currentImageVersion := GetOSImageVersion(ctx, conn)
84+
return !(targetImageVersion.ID == R0_IMAGE_VERSION_ID || currentImageVersion == R0_IMAGE_VERSION_ID)
14085
}

pkg/flasherapi/flasherapi_test.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
1+
// This file is part of arduino-app-cli.
2+
//
3+
// Copyright 2025 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-app-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
116
package flasherapi
217

3-
import "testing"
18+
import (
19+
"strings"
20+
"testing"
21+
)
422

523
func TestParseOSImageVersion(t *testing.T) {
624
tests := []struct {
@@ -29,7 +47,7 @@ func TestParseOSImageVersion(t *testing.T) {
2947

3048
for _, tt := range tests {
3149
t.Run(tt.name, func(t *testing.T) {
32-
got, ok := ParseOSImageVersion(tt.input)
50+
got, ok := parseOSImageVersion(strings.NewReader(tt.input))
3351
if ok != tt.found || got != tt.expected {
3452
t.Fatalf("got (%q, %v), expected (%q, %v)", got, ok, tt.expected, tt.found)
3553
}

0 commit comments

Comments
 (0)