Skip to content

Commit bc6e64c

Browse files
author
Luca Bianconi
committed
fix: handle empty sketch name
1 parent ba8d470 commit bc6e64c

File tree

4 files changed

+49
-9
lines changed

4 files changed

+49
-9
lines changed

Diff for: commands/sketch/new.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ 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]{1}[0-9a-zA-Z_\.-]*$`)
40+
var sketchNameValidationRegex = regexp.MustCompile(`^[0-9a-zA-Z][0-9a-zA-Z_\.-]*$`)
4141

4242
// NewSketch creates a new sketch via gRPC
4343
func NewSketch(ctx context.Context, req *rpc.NewSketchRequest) (*rpc.NewSketchResponse, error) {
@@ -71,12 +71,14 @@ func NewSketch(ctx context.Context, req *rpc.NewSketchRequest) (*rpc.NewSketchRe
7171
}
7272

7373
func validateSketchName(name string) error {
74+
if name == "" {
75+
return &arduino.CantCreateSketchError{Cause: errors.New(tr("sketch name cannot be empty"))}
76+
}
7477
if len(name) > sketchNameMaxLength {
7578
return &arduino.CantCreateSketchError{Cause: errors.New(tr("sketch name too long (%d characters). Maximum allowed length is %d",
7679
len(name),
7780
sketchNameMaxLength))}
7881
}
79-
8082
if !sketchNameValidationRegex.MatchString(name) {
8183
return &arduino.CantCreateSketchError{Cause: errors.New(tr("invalid sketch name \"%s\". Required pattern %s",
8284
name,

Diff for: commands/sketch/new_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ func Test_SketchNameWrongPattern(t *testing.T) {
3232
}
3333
}
3434

35+
func Test_SketchNameEmpty(t *testing.T) {
36+
emptyName := ""
37+
_, err := NewSketch(context.Background(), &commands.NewSketchRequest{
38+
SketchName: emptyName,
39+
SketchDir: t.TempDir(),
40+
})
41+
require.NotNil(t, err)
42+
43+
require.Error(t, err, `Can't create sketch: sketch name cannot be empty`)
44+
}
45+
3546
func Test_SketchNameTooLong(t *testing.T) {
3647
tooLongName := make([]byte, sketchNameMaxLength+1)
3748
for i := range tooLongName {

Diff for: internal/cli/sketch/new.go

+24-7
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,33 @@ func initNewCommand() *cobra.Command {
4949
func runNewCommand(args []string, overwrite bool) {
5050
logrus.Info("Executing `arduino-cli sketch new`")
5151
// Trim to avoid issues if user creates a sketch adding the .ino extesion to the name
52-
sketchName := args[0]
53-
trimmedSketchName := strings.TrimSuffix(sketchName, globals.MainFileValidExtension)
54-
sketchDirPath, err := paths.New(trimmedSketchName).Abs()
55-
if err != nil {
56-
feedback.Fatal(tr("Error creating sketch: %v", err), feedback.ErrGeneric)
52+
inputSketchName := args[0]
53+
trimmedSketchName := strings.TrimSuffix(inputSketchName, globals.MainFileValidExtension)
54+
55+
var sketchDir string
56+
var sketchName string
57+
var sketchDirPath *paths.Path
58+
var err error
59+
60+
if trimmedSketchName == "" {
61+
// `paths.New` returns nil with an empty string so `paths.Abs` panics.
62+
// if the name is empty we rely on the "new" command to fail nicely later
63+
// with the same logic in grpc and cli flows
64+
sketchDir = ""
65+
sketchName = ""
66+
} else {
67+
sketchDirPath, err = paths.New(trimmedSketchName).Abs()
68+
if err != nil {
69+
feedback.Fatal(tr("Error creating sketch: %v", err), feedback.ErrGeneric)
70+
}
71+
sketchDir = sketchDirPath.Parent().String()
72+
sketchName = sketchDirPath.Base()
5773
}
74+
5875
_, err = sk.NewSketch(context.Background(), &rpc.NewSketchRequest{
5976
Instance: nil,
60-
SketchName: sketchDirPath.Base(),
61-
SketchDir: sketchDirPath.Parent().String(),
77+
SketchName: sketchName,
78+
SketchDir: sketchDir,
6279
Overwrite: overwrite,
6380
})
6481
if err != nil {

Diff for: internal/integrationtest/sketch/sketch_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ func TestSketchNew(t *testing.T) {
7373
require.FileExists(t, currentSketchPath.Join(sketchName).String()+".ino")
7474
}
7575

76+
func TestSketchNewEmptyName(t *testing.T) {
77+
// testing that we fail nicely. It panicked in the past
78+
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
79+
defer env.CleanUp()
80+
81+
sketchName := ""
82+
_, _, err := cli.Run("sketch", "new", sketchName)
83+
require.Error(t, err, "Can't create sketch: sketch name cannot be empty")
84+
}
85+
7686
func verifyZipContainsSketchExcludingBuildDir(t *testing.T, files []*zip.File) {
7787
require.Len(t, files, 8)
7888
require.Equal(t, paths.New("sketch_simple", "doc.txt").String(), files[0].Name)

0 commit comments

Comments
 (0)