Skip to content

Commit 0425c95

Browse files
authored
Fix loading of sketches with folder and main file mismatched casing (#1179)
* Fix loading of sketches with folder and main file mismatched casing * [skip changelog] Fix legacy tests
1 parent 8b5179d commit 0425c95

File tree

63 files changed

+359
-92
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+359
-92
lines changed

arduino/builder/sketch_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,17 @@ func TestCopyAdditionalFiles(t *testing.T) {
230230
info2, err := os.Stat(s2.AdditionalFiles[0].Path)
231231
require.Equal(t, info1.ModTime(), info2.ModTime())
232232
}
233+
234+
func TestLoadSketchCaseMismatch(t *testing.T) {
235+
// pass the path to the sketch folder
236+
sketchPath := filepath.Join("testdata", t.Name())
237+
mainFilePath := filepath.Join(sketchPath, t.Name()+".ino")
238+
s, err := builder.SketchLoad(sketchPath, "")
239+
require.Nil(t, s)
240+
require.Error(t, err)
241+
242+
// pass the path to the main file
243+
s, err = builder.SketchLoad(mainFilePath, "")
244+
require.Nil(t, s)
245+
require.Error(t, err)
246+
}

arduino/sketch/sketch.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"strings"
2323

2424
"github.com/arduino/arduino-cli/arduino/globals"
25+
"github.com/arduino/go-paths-helper"
2526
"github.com/pkg/errors"
2627
)
2728

@@ -116,10 +117,43 @@ func New(sketchFolderPath, mainFilePath, buildPath string, allFilesPaths []strin
116117
sort.Sort(ItemByPath(additionalFiles))
117118
sort.Sort(ItemByPath(otherSketchFiles))
118119

120+
if err := CheckSketchCasing(sketchFolderPath); err != nil {
121+
return nil, err
122+
}
123+
119124
return &Sketch{
120125
MainFile: mainFile,
121126
LocationPath: sketchFolderPath,
122127
OtherSketchFiles: otherSketchFiles,
123128
AdditionalFiles: additionalFiles,
124129
}, nil
125130
}
131+
132+
// CheckSketchCasing returns an error if the casing of the sketch folder and the main file are different.
133+
// Correct:
134+
// MySketch/MySketch.ino
135+
// Wrong:
136+
// MySketch/mysketch.ino
137+
// mysketch/MySketch.ino
138+
//
139+
// This is mostly necessary to avoid errors on Mac OS X.
140+
// For more info see: https://github.com/arduino/arduino-cli/issues/1174
141+
func CheckSketchCasing(sketchFolder string) error {
142+
sketchPath := paths.New(sketchFolder)
143+
files, err := sketchPath.ReadDir()
144+
if err != nil {
145+
return errors.Errorf("reading files: %v", err)
146+
}
147+
files.FilterOutDirs()
148+
149+
sketchName := sketchPath.Base()
150+
files.FilterPrefix(sketchName)
151+
152+
if files.Len() == 0 {
153+
sketchFolderPath := paths.New(sketchFolder)
154+
sketchFile := sketchFolderPath.Join(sketchFolderPath.Base() + globals.MainFileValidExtension)
155+
return errors.Errorf("no valid sketch found in %s: missing %s", sketchFolderPath, sketchFile)
156+
}
157+
158+
return nil
159+
}

arduino/sketch/sketch_test.go

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
package sketch_test
1717

1818
import (
19+
"fmt"
1920
"path/filepath"
2021
"sort"
2122
"testing"
2223

2324
"github.com/arduino/arduino-cli/arduino/sketch"
25+
"github.com/arduino/go-paths-helper"
2426
"github.com/stretchr/testify/assert"
27+
"github.com/stretchr/testify/require"
2528
)
2629

2730
func TestNewItem(t *testing.T) {
@@ -43,9 +46,9 @@ func TestNewItem(t *testing.T) {
4346

4447
func TestSort(t *testing.T) {
4548
items := []*sketch.Item{
46-
&sketch.Item{"foo"},
47-
&sketch.Item{"baz"},
48-
&sketch.Item{"bar"},
49+
{"foo"},
50+
{"baz"},
51+
{"bar"},
4952
}
5053

5154
sort.Sort(sketch.ItemByPath(items))
@@ -71,3 +74,37 @@ func TestNew(t *testing.T) {
7174
assert.Len(t, sketch.OtherSketchFiles, 0)
7275
assert.Len(t, sketch.AdditionalFiles, 1)
7376
}
77+
78+
func TestNewSketchCasingWrong(t *testing.T) {
79+
sketchPath := paths.New("testdata", "SketchCasingWrong")
80+
mainFilePath := paths.New("testadata", "sketchcasingwrong.ino").String()
81+
sketch, err := sketch.New(sketchPath.String(), mainFilePath, "", []string{mainFilePath})
82+
assert.Nil(t, sketch)
83+
expectedError := fmt.Sprintf("no valid sketch found in %s: missing %s", sketchPath.String(), sketchPath.Join(sketchPath.Base()+".ino"))
84+
assert.EqualError(t, err, expectedError)
85+
}
86+
87+
func TestNewSketchCasingCorrect(t *testing.T) {
88+
sketchPath := paths.New("testdata", "SketchCasingCorrect").String()
89+
mainFilePath := paths.New("testadata", "SketchCasingCorrect.ino").String()
90+
sketch, err := sketch.New(sketchPath, mainFilePath, "", []string{mainFilePath})
91+
assert.NotNil(t, sketch)
92+
assert.NoError(t, err)
93+
assert.Equal(t, sketchPath, sketch.LocationPath)
94+
assert.Equal(t, mainFilePath, sketch.MainFile.Path)
95+
assert.Len(t, sketch.OtherSketchFiles, 0)
96+
assert.Len(t, sketch.AdditionalFiles, 0)
97+
}
98+
99+
func TestCheckSketchCasingWrong(t *testing.T) {
100+
sketchFolder := paths.New("testdata", "SketchCasingWrong")
101+
err := sketch.CheckSketchCasing(sketchFolder.String())
102+
expectedError := fmt.Sprintf("no valid sketch found in %s: missing %s", sketchFolder, sketchFolder.Join(sketchFolder.Base()+".ino"))
103+
assert.EqualError(t, err, expectedError)
104+
}
105+
106+
func TestCheckSketchCasingCorrect(t *testing.T) {
107+
sketchFolder := paths.New("testdata", "SketchCasingCorrect").String()
108+
err := sketch.CheckSketchCasing(sketchFolder)
109+
require.NoError(t, err)
110+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
void setup() {
2+
3+
}
4+
5+
void loop() {
6+
7+
}

arduino/sketches/sketches.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/arduino/arduino-cli/arduino/builder"
2323
"github.com/arduino/arduino-cli/arduino/globals"
24+
"github.com/arduino/arduino-cli/arduino/sketch"
2425
"github.com/arduino/go-paths-helper"
2526
"github.com/pkg/errors"
2627
)
@@ -70,19 +71,19 @@ func NewSketchFromPath(path *paths.Path) (*Sketch, error) {
7071
}
7172
}
7273

73-
if mainSketchFile == nil {
74+
if mainSketchFile == nil || sketch.CheckSketchCasing(path.String()) != nil {
7475
sketchFile := path.Join(path.Base() + globals.MainFileValidExtension)
7576
return nil, errors.Errorf("no valid sketch found in %s: missing %s", path, sketchFile)
7677
}
7778

78-
sketch := &Sketch{
79+
s := &Sketch{
7980
FullPath: path,
8081
MainFileExtension: mainSketchFile.Ext(),
8182
Name: path.Base(),
8283
Metadata: &Metadata{},
8384
}
84-
sketch.ImportMetadata()
85-
return sketch, nil
85+
s.ImportMetadata()
86+
return s, nil
8687
}
8788

8889
// ImportMetadata imports metadata into the sketch from a sketch.json file in the root

arduino/sketches/sketches_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,24 @@ func TestCheckForPdeFiles(t *testing.T) {
109109
require.Len(t, files, 1)
110110
require.Equal(t, sketchPath.Parent().Join("SketchMultipleMainFiles.pde"), files[0])
111111
}
112+
113+
func TestSketchLoadWithCasing(t *testing.T) {
114+
sketchFolder := paths.New("testdata", "SketchCasingWrong")
115+
116+
sketch, err := NewSketchFromPath(sketchFolder)
117+
require.Nil(t, sketch)
118+
119+
sketchFolderAbs, _ := sketchFolder.Abs()
120+
sketchMainFileAbs := sketchFolderAbs.Join("SketchCasingWrong.ino")
121+
expectedError := fmt.Sprintf("no valid sketch found in %s: missing %s", sketchFolderAbs, sketchMainFileAbs)
122+
require.EqualError(t, err, expectedError)
123+
}
124+
125+
func TestSketchLoadingCorrectCasing(t *testing.T) {
126+
sketchFolder := paths.New("testdata", "SketchCasingCorrect")
127+
sketch, err := NewSketchFromPath(sketchFolder)
128+
require.NotNil(t, sketch)
129+
require.NoError(t, err)
130+
require.Equal(t, sketch.Name, "SketchCasingCorrect")
131+
require.True(t, sketch.FullPath.EquivalentTo(sketchFolder))
132+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
void setup() {
2+
3+
}
4+
5+
void loop() {
6+
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
void setup() {
2+
3+
}
4+
5+
void loop() {
6+
7+
}

legacy/builder/test/builder_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func prepareBuilderTestContext(t *testing.T, sketchPath *paths.Path, fqbn string
4646
func TestBuilderEmptySketch(t *testing.T) {
4747
DownloadCoresAndToolsAndLibraries(t)
4848

49-
ctx := prepareBuilderTestContext(t, paths.New("sketch1", "sketch.ino"), "arduino:avr:uno")
49+
ctx := prepareBuilderTestContext(t, paths.New("sketch1", "sketch1.ino"), "arduino:avr:uno")
5050
ctx.DebugLevel = 10
5151

5252
buildPath := SetupBuildPath(t, ctx)
@@ -63,13 +63,13 @@ func TestBuilderEmptySketch(t *testing.T) {
6363
exist, err = buildPath.Join(constants.FOLDER_PREPROC, constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E).ExistCheck()
6464
NoError(t, err)
6565
require.True(t, exist)
66-
exist, err = buildPath.Join(constants.FOLDER_SKETCH, "sketch.ino.cpp.o").ExistCheck()
66+
exist, err = buildPath.Join(constants.FOLDER_SKETCH, "sketch1.ino.cpp.o").ExistCheck()
6767
NoError(t, err)
6868
require.True(t, exist)
69-
exist, err = buildPath.Join("sketch.ino.elf").ExistCheck()
69+
exist, err = buildPath.Join("sketch1.ino.elf").ExistCheck()
7070
NoError(t, err)
7171
require.True(t, exist)
72-
exist, err = buildPath.Join("sketch.ino.hex").ExistCheck()
72+
exist, err = buildPath.Join("sketch1.ino.hex").ExistCheck()
7373
NoError(t, err)
7474
require.True(t, exist)
7575
}
@@ -277,7 +277,7 @@ func TestBuilderSketchNoFunctions(t *testing.T) {
277277
func TestBuilderSketchWithBackup(t *testing.T) {
278278
DownloadCoresAndToolsAndLibraries(t)
279279

280-
ctx := prepareBuilderTestContext(t, paths.New("sketch_with_backup_files", "sketch.ino"), "arduino:avr:uno")
280+
ctx := prepareBuilderTestContext(t, paths.New("sketch_with_backup_files", "sketch_with_backup_files.ino"), "arduino:avr:uno")
281281
ctx.HardwareDirs = append(ctx.HardwareDirs, paths.New("downloaded_board_manager_stuff"))
282282
ctx.BuiltInToolsDirs = append(ctx.BuiltInToolsDirs, paths.New("downloaded_board_manager_stuff"))
283283

@@ -293,7 +293,7 @@ func TestBuilderSketchWithBackup(t *testing.T) {
293293
func TestBuilderSketchWithOldLib(t *testing.T) {
294294
DownloadCoresAndToolsAndLibraries(t)
295295

296-
ctx := prepareBuilderTestContext(t, paths.New("sketch_with_old_lib", "sketch.ino"), "arduino:avr:uno")
296+
ctx := prepareBuilderTestContext(t, paths.New("sketch_with_old_lib", "sketch_with_old_lib.ino"), "arduino:avr:uno")
297297

298298
buildPath := SetupBuildPath(t, ctx)
299299
defer buildPath.RemoveAll()
@@ -344,7 +344,7 @@ func TestBuilderSketchBuildPathContainsUnusedPreviouslyCompiledLibrary(t *testin
344344
func TestBuilderWithBuildPathInSketchDir(t *testing.T) {
345345
DownloadCoresAndToolsAndLibraries(t)
346346

347-
ctx := prepareBuilderTestContext(t, paths.New("sketch1", "sketch.ino"), "arduino:avr:uno")
347+
ctx := prepareBuilderTestContext(t, paths.New("sketch1", "sketch1.ino"), "arduino:avr:uno")
348348

349349
var err error
350350
ctx.BuildPath, err = paths.New("sketch1", "build").Abs()
@@ -365,7 +365,7 @@ func TestBuilderWithBuildPathInSketchDir(t *testing.T) {
365365
func TestBuilderCacheCoreAFile(t *testing.T) {
366366
DownloadCoresAndToolsAndLibraries(t)
367367

368-
ctx := prepareBuilderTestContext(t, paths.New("sketch1", "sketch.ino"), "arduino:avr:uno")
368+
ctx := prepareBuilderTestContext(t, paths.New("sketch1", "sketch1.ino"), "arduino:avr:uno")
369369

370370
SetupBuildPath(t, ctx)
371371
defer ctx.BuildPath.RemoveAll()

legacy/builder/test/ctags_runner_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func TestCTagsRunner(t *testing.T) {
7979
func TestCTagsRunnerSketchWithClass(t *testing.T) {
8080
DownloadCoresAndToolsAndLibraries(t)
8181

82-
sketchLocation := Abs(t, paths.New("sketch_with_class", "sketch.ino"))
82+
sketchLocation := Abs(t, paths.New("sketch_with_class", "sketch_with_class.ino"))
8383

8484
ctx := &types.Context{
8585
HardwareDirs: paths.NewPathList(filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"),
@@ -127,7 +127,7 @@ func TestCTagsRunnerSketchWithClass(t *testing.T) {
127127
func TestCTagsRunnerSketchWithTypename(t *testing.T) {
128128
DownloadCoresAndToolsAndLibraries(t)
129129

130-
sketchLocation := Abs(t, paths.New("sketch_with_typename", "sketch.ino"))
130+
sketchLocation := Abs(t, paths.New("sketch_with_typename", "sketch_with_typename.ino"))
131131

132132
ctx := &types.Context{
133133
HardwareDirs: paths.NewPathList(filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"),
@@ -174,7 +174,7 @@ func TestCTagsRunnerSketchWithTypename(t *testing.T) {
174174
func TestCTagsRunnerSketchWithNamespace(t *testing.T) {
175175
DownloadCoresAndToolsAndLibraries(t)
176176

177-
sketchLocation := Abs(t, paths.New("sketch_with_namespace", "sketch.ino"))
177+
sketchLocation := Abs(t, paths.New("sketch_with_namespace", "sketch_with_namespace.ino"))
178178

179179
ctx := &types.Context{
180180
HardwareDirs: paths.NewPathList(filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"),
@@ -220,7 +220,7 @@ func TestCTagsRunnerSketchWithNamespace(t *testing.T) {
220220
func TestCTagsRunnerSketchWithTemplates(t *testing.T) {
221221
DownloadCoresAndToolsAndLibraries(t)
222222

223-
sketchLocation := Abs(t, paths.New("sketch_with_templates_and_shift", "template_and_shift.cpp"))
223+
sketchLocation := Abs(t, paths.New("sketch_with_templates_and_shift", "sketch_with_templates_and_shift.cpp"))
224224

225225
ctx := &types.Context{
226226
HardwareDirs: paths.NewPathList(filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"),

legacy/builder/test/includes_to_include_folders_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func TestIncludesToIncludeFoldersSketchWithIfDef(t *testing.T) {
7070
BuiltInToolsDirs: paths.NewPathList("downloaded_tools"),
7171
BuiltInLibrariesDirs: paths.NewPathList("downloaded_libraries"),
7272
OtherLibrariesDirs: paths.NewPathList("libraries"),
73-
SketchLocation: paths.New("sketch2", "SketchWithIfDef.ino"),
73+
SketchLocation: paths.New("SketchWithIfDef", "SketchWithIfDef.ino"),
7474
FQBN: parseFQBN(t, "arduino:avr:leonardo"),
7575
ArduinoAPIVersion: "10600",
7676
Verbose: true,
@@ -105,7 +105,7 @@ func TestIncludesToIncludeFoldersIRremoteLibrary(t *testing.T) {
105105
BuiltInToolsDirs: paths.NewPathList("downloaded_tools"),
106106
BuiltInLibrariesDirs: paths.NewPathList("downloaded_libraries"),
107107
OtherLibrariesDirs: paths.NewPathList("libraries"),
108-
SketchLocation: paths.New("sketch9", "sketch.ino"),
108+
SketchLocation: paths.New("sketch9", "sketch9.ino"),
109109
FQBN: parseFQBN(t, "arduino:avr:leonardo"),
110110
ArduinoAPIVersion: "10600",
111111
Verbose: true,
@@ -143,7 +143,7 @@ func TestIncludesToIncludeFoldersANewLibrary(t *testing.T) {
143143
BuiltInToolsDirs: paths.NewPathList("downloaded_tools"),
144144
BuiltInLibrariesDirs: paths.NewPathList("downloaded_libraries"),
145145
OtherLibrariesDirs: paths.NewPathList("libraries"),
146-
SketchLocation: paths.New("sketch10", "sketch.ino"),
146+
SketchLocation: paths.New("sketch10", "sketch10.ino"),
147147
FQBN: parseFQBN(t, "arduino:avr:leonardo"),
148148
ArduinoAPIVersion: "10600",
149149
Verbose: true,

legacy/builder/test/load_vid_pid_specific_properties_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func TestLoadVIDPIDSpecificPropertiesWhenNoVIDPIDAreProvided(t *testing.T) {
3131
ctx := &types.Context{
3232
HardwareDirs: paths.NewPathList(filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"),
3333
BuiltInToolsDirs: paths.NewPathList("downloaded_tools", "./tools_builtin"),
34-
SketchLocation: paths.New("sketch1", "sketch.ino"),
34+
SketchLocation: paths.New("sketch1", "sketch1.ino"),
3535
FQBN: parseFQBN(t, "arduino:avr:micro"),
3636
ArduinoAPIVersion: "10600",
3737
}
@@ -61,7 +61,7 @@ func TestLoadVIDPIDSpecificProperties(t *testing.T) {
6161
ctx := &types.Context{
6262
HardwareDirs: paths.NewPathList(filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"),
6363
BuiltInToolsDirs: paths.NewPathList("downloaded_tools", "./tools_builtin"),
64-
SketchLocation: paths.New("sketch1", "sketch.ino"),
64+
SketchLocation: paths.New("sketch1", "sketch1.ino"),
6565
FQBN: parseFQBN(t, "arduino:avr:micro"),
6666
ArduinoAPIVersion: "10600",
6767
}

0 commit comments

Comments
 (0)