Skip to content

Commit a71415f

Browse files
[breaking] Check cross-platform compatibility of sketch names (#2216)
* Exclude sketch names ending with a dot * Fail with error if a reserved name is used as sketch name * Update sketch name specifications in docs
1 parent 223d3fa commit a71415f

File tree

4 files changed

+34
-5
lines changed

4 files changed

+34
-5
lines changed

Diff for: commands/sketch/new.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ void loop() {
3737

3838
// sketchNameMaxLength could be part of the regex, but it's intentionally left out for clearer error reporting
3939
var sketchNameMaxLength = 63
40-
var sketchNameValidationRegex = regexp.MustCompile(`^[0-9a-zA-Z_][0-9a-zA-Z_\.-]*$`)
40+
var sketchNameValidationRegex = regexp.MustCompile(`^[0-9a-zA-Z_](?:[0-9a-zA-Z_\.-]*[0-9a-zA-Z_-]|)$`)
41+
42+
var invalidNames = []string{"CON", "PRN", "AUX", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5",
43+
"COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}
4144

4245
// NewSketch creates a new sketch via gRPC
4346
func NewSketch(ctx context.Context, req *rpc.NewSketchRequest) (*rpc.NewSketchResponse, error) {
@@ -80,8 +83,13 @@ func validateSketchName(name string) error {
8083
sketchNameMaxLength))}
8184
}
8285
if !sketchNameValidationRegex.MatchString(name) {
83-
return &arduino.CantCreateSketchError{Cause: errors.New(tr(`invalid sketch name "%[1]s": the first character must be alphanumeric or "_", the following ones can also contain "-" and ".".`,
86+
return &arduino.CantCreateSketchError{Cause: errors.New(tr(`invalid sketch name "%[1]s": the first character must be alphanumeric or "_", the following ones can also contain "-" and ".". The last one cannot be ".".`,
8487
name))}
8588
}
89+
for _, invalid := range invalidNames {
90+
if name == invalid {
91+
return &arduino.CantCreateSketchError{Cause: errors.New(tr(`sketch name cannot be the reserved name "%[1]s"`, invalid))}
92+
}
93+
}
8694
return nil
8795
}

Diff for: commands/sketch/new_test.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func Test_SketchNameWrongPattern(t *testing.T) {
3030
".hello",
3131
"-hello",
3232
"hello*",
33+
"hello.",
3334
"||||||||||||||",
3435
",`hack[}attempt{];",
3536
}
@@ -39,7 +40,7 @@ func Test_SketchNameWrongPattern(t *testing.T) {
3940
SketchDir: t.TempDir(),
4041
})
4142

42-
require.EqualError(t, err, fmt.Sprintf(`Can't create sketch: invalid sketch name "%s": the first character must be alphanumeric or "_", the following ones can also contain "-" and ".".`,
43+
require.EqualError(t, err, fmt.Sprintf(`Can't create sketch: invalid sketch name "%s": the first character must be alphanumeric or "_", the following ones can also contain "-" and ".". The last one cannot be ".".`,
4344
name))
4445
}
4546
}
@@ -78,7 +79,6 @@ func Test_SketchNameOk(t *testing.T) {
7879
"h",
7980
"h.ello",
8081
"h..ello-world",
81-
"h..ello-world.",
8282
"hello_world__",
8383
"_hello_world",
8484
string(lengthLimitName),
@@ -91,3 +91,15 @@ func Test_SketchNameOk(t *testing.T) {
9191
require.Nil(t, err)
9292
}
9393
}
94+
95+
func Test_SketchNameReserved(t *testing.T) {
96+
invalidNames := []string{"CON", "PRN", "AUX", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4", "COM5",
97+
"COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}
98+
for _, name := range invalidNames {
99+
_, err := NewSketch(context.Background(), &commands.NewSketchRequest{
100+
SketchName: name,
101+
SketchDir: t.TempDir(),
102+
})
103+
require.EqualError(t, err, fmt.Sprintf(`Can't create sketch: sketch name cannot be the reserved name "%s"`, name))
104+
}
105+
}

Diff for: docs/UPGRADING.md

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ Here you can find a list of migration guides to handle breaking changes between
44

55
## 0.34.0
66

7+
### Updated sketch name specifications
8+
9+
[Sketch name specifications](https://arduino.github.io/arduino-cli/dev/sketch-specification) have been updated to
10+
achieve cross-platform compatibility.
11+
12+
Existing sketch names violating the new constraint need to be updated.
13+
714
### golang API: `LoadSketch` function has been moved
815

916
The function `github.com/arduino/arduino-cli/commands.LoadSketch` has been moved to package

Diff for: docs/sketch-specification.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ The programs that run on Arduino boards are called "sketches". This term was inh
77

88
The sketch root folder name and code file names must start with a basic letter (`A`-`Z` or `a`-`z`), number (`0`-`9`)
99
[<sup>1</sup>](#leading-number-note), or underscore (`_`) [<sup>2</sup>](#leading-underscore-note) followed by basic
10-
letters, numbers, underscores, dots (`.`) and dashes (`-`). The maximum length is 63 characters.
10+
letters, numbers, underscores, dots (`.`) and dashes (`-`). The maximum length is 63 characters. The sketch name cannot
11+
end with a dot (`.`) and cannot be a
12+
[reserved name](https://learn.microsoft.com/windows/win32/fileio/naming-a-file#naming-conventions).
1113

1214
<a id="leading-number-note"></a> <sup>1</sup> Supported from Arduino IDE 1.8.4. <br />
1315
<a id="leading-underscore-note"></a> <sup>2</sup> Supported in all versions except Arduino IDE 2.0.4/Arduino CLI

0 commit comments

Comments
 (0)