Skip to content

Commit f3efd0c

Browse files
authored
Changed AdditionalSketchFilesCopier legacy command into new builder API function (#293)
* add convention to func names * move sketch copy ops out of legacy into new API * removed dead code
1 parent 87780d7 commit f3efd0c

10 files changed

+150
-276
lines changed

Diff for: arduino/builder/sketch.go

+66-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package builder
1717

1818
import (
19+
"bytes"
1920
"io/ioutil"
2021
"os"
2122
"path/filepath"
@@ -39,16 +40,16 @@ func QuoteCppString(str string) string {
3940
return "\"" + str + "\""
4041
}
4142

42-
// SaveSketchItemCpp saves a preprocessed .cpp sketch file on disk
43-
func SaveSketchItemCpp(item *sketch.Item, buildPath string) error {
43+
// SketchSaveItemCpp saves a preprocessed .cpp sketch file on disk
44+
func SketchSaveItemCpp(item *sketch.Item, destPath string) error {
4445

4546
sketchName := filepath.Base(item.Path)
4647

47-
if err := os.MkdirAll(buildPath, os.FileMode(0755)); err != nil {
48+
if err := os.MkdirAll(destPath, os.FileMode(0755)); err != nil {
4849
return errors.Wrap(err, "unable to create a folder to save the sketch")
4950
}
5051

51-
destFile := filepath.Join(buildPath, sketchName+".cpp")
52+
destFile := filepath.Join(destPath, sketchName+".cpp")
5253

5354
if err := ioutil.WriteFile(destFile, item.Source, os.FileMode(0644)); err != nil {
5455
return errors.Wrap(err, "unable to save the sketch on disk")
@@ -57,10 +58,10 @@ func SaveSketchItemCpp(item *sketch.Item, buildPath string) error {
5758
return nil
5859
}
5960

60-
// LoadSketch collects all the files composing a sketch.
61+
// SketchLoad collects all the files composing a sketch.
6162
// The parameter `sketchPath` holds a path pointing to a single sketch file or a sketch folder,
6263
// the path must be absolute.
63-
func LoadSketch(sketchPath, buildPath string) (*sketch.Sketch, error) {
64+
func SketchLoad(sketchPath, buildPath string) (*sketch.Sketch, error) {
6465
stat, err := os.Stat(sketchPath)
6566
if err != nil {
6667
return nil, errors.Wrap(err, "unable to stat Sketch location")
@@ -133,8 +134,8 @@ func LoadSketch(sketchPath, buildPath string) (*sketch.Sketch, error) {
133134
return sketch.New(sketchFolder, mainSketchFile, buildPath, files)
134135
}
135136

136-
// MergeSketchSources merges all the source files included in a sketch
137-
func MergeSketchSources(sketch *sketch.Sketch) (int, string) {
137+
// SketchMergeSources merges all the source files included in a sketch
138+
func SketchMergeSources(sketch *sketch.Sketch) (int, string) {
138139
lineOffset := 0
139140
mergedSource := ""
140141

@@ -155,3 +156,60 @@ func MergeSketchSources(sketch *sketch.Sketch) (int, string) {
155156

156157
return lineOffset, mergedSource
157158
}
159+
160+
// SketchCopyAdditionalFiles copies the additional files for a sketch to the
161+
// specified destination directory.
162+
func SketchCopyAdditionalFiles(sketch *sketch.Sketch, destPath string) error {
163+
if err := os.MkdirAll(destPath, os.FileMode(0755)); err != nil {
164+
return errors.Wrap(err, "unable to create a folder to save the sketch files")
165+
}
166+
167+
for _, item := range sketch.AdditionalFiles {
168+
relpath, err := filepath.Rel(sketch.LocationPath, item.Path)
169+
if err != nil {
170+
return errors.Wrap(err, "unable to compute relative path to the sketch for the item")
171+
}
172+
173+
targetPath := filepath.Join(destPath, relpath)
174+
// create the directory containing the target
175+
if err = os.MkdirAll(filepath.Dir(targetPath), os.FileMode(0755)); err != nil {
176+
return errors.Wrap(err, "unable to create the folder containing the item")
177+
}
178+
179+
err = writeIfDifferent(item.Path, targetPath)
180+
if err != nil {
181+
return errors.Wrap(err, "unable to write to destination file")
182+
}
183+
}
184+
185+
return nil
186+
}
187+
188+
func writeIfDifferent(sourcePath, destPath string) error {
189+
// read the source file
190+
newbytes, err := ioutil.ReadFile(sourcePath)
191+
if err != nil {
192+
return errors.Wrap(err, "unable to read contents of the source item")
193+
}
194+
195+
// check whether the destination file exists
196+
_, err = os.Stat(destPath)
197+
if os.IsNotExist(err) {
198+
// write directly
199+
return ioutil.WriteFile(destPath, newbytes, os.FileMode(0644))
200+
}
201+
202+
// read the destination file if it ex
203+
existingBytes, err := ioutil.ReadFile(destPath)
204+
if err != nil {
205+
return errors.Wrap(err, "unable to read contents of the destination item")
206+
}
207+
208+
// overwrite if contents are different
209+
if bytes.Compare(existingBytes, newbytes) != 0 {
210+
return ioutil.WriteFile(destPath, newbytes, os.FileMode(0644))
211+
}
212+
213+
// source and destination are the same, don't write anything
214+
return nil
215+
}

Diff for: arduino/builder/sketch_test.go

+78-43
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package builder_test
1717

1818
import (
19+
"fmt"
1920
"io/ioutil"
2021
"os"
2122
"path/filepath"
@@ -24,7 +25,7 @@ import (
2425

2526
"github.com/arduino/arduino-cli/arduino/builder"
2627
"github.com/arduino/arduino-cli/arduino/sketch"
27-
"github.com/stretchr/testify/assert"
28+
"github.com/stretchr/testify/require"
2829
)
2930

3031
func TestSaveSketch(t *testing.T) {
@@ -38,64 +39,64 @@ func TestSaveSketch(t *testing.T) {
3839
t.Fatalf("unable to read golden file %s: %v", sketchFile, err)
3940
}
4041

41-
builder.SaveSketchItemCpp(&sketch.Item{Path: sketchName, Source: source}, tmp)
42+
builder.SketchSaveItemCpp(&sketch.Item{Path: sketchName, Source: source}, tmp)
4243

4344
out, err := ioutil.ReadFile(filepath.Join(tmp, outName))
4445
if err != nil {
4546
t.Fatalf("unable to read output file %s: %v", outName, err)
4647
}
4748

48-
assert.Equal(t, source, out)
49+
require.Equal(t, source, out)
4950
}
5051

5152
func TestLoadSketchFolder(t *testing.T) {
5253
// pass the path to the sketch folder
5354
sketchPath := filepath.Join("testdata", t.Name())
5455
mainFilePath := filepath.Join(sketchPath, t.Name()+".ino")
55-
s, err := builder.LoadSketch(sketchPath, "")
56-
assert.Nil(t, err)
57-
assert.NotNil(t, s)
58-
assert.Equal(t, mainFilePath, s.MainFile.Path)
59-
assert.Equal(t, sketchPath, s.LocationPath)
60-
assert.Len(t, s.OtherSketchFiles, 2)
61-
assert.Equal(t, "old.pde", filepath.Base(s.OtherSketchFiles[0].Path))
62-
assert.Equal(t, "other.ino", filepath.Base(s.OtherSketchFiles[1].Path))
63-
assert.Len(t, s.AdditionalFiles, 3)
64-
assert.Equal(t, "header.h", filepath.Base(s.AdditionalFiles[0].Path))
65-
assert.Equal(t, "s_file.S", filepath.Base(s.AdditionalFiles[1].Path))
66-
assert.Equal(t, "helper.h", filepath.Base(s.AdditionalFiles[2].Path))
56+
s, err := builder.SketchLoad(sketchPath, "")
57+
require.Nil(t, err)
58+
require.NotNil(t, s)
59+
require.Equal(t, mainFilePath, s.MainFile.Path)
60+
require.Equal(t, sketchPath, s.LocationPath)
61+
require.Len(t, s.OtherSketchFiles, 2)
62+
require.Equal(t, "old.pde", filepath.Base(s.OtherSketchFiles[0].Path))
63+
require.Equal(t, "other.ino", filepath.Base(s.OtherSketchFiles[1].Path))
64+
require.Len(t, s.AdditionalFiles, 3)
65+
require.Equal(t, "header.h", filepath.Base(s.AdditionalFiles[0].Path))
66+
require.Equal(t, "s_file.S", filepath.Base(s.AdditionalFiles[1].Path))
67+
require.Equal(t, "helper.h", filepath.Base(s.AdditionalFiles[2].Path))
6768

6869
// pass the path to the main file
6970
sketchPath = mainFilePath
70-
s, err = builder.LoadSketch(sketchPath, "")
71-
assert.Nil(t, err)
72-
assert.NotNil(t, s)
73-
assert.Equal(t, mainFilePath, s.MainFile.Path)
74-
assert.Len(t, s.OtherSketchFiles, 2)
75-
assert.Equal(t, "old.pde", filepath.Base(s.OtherSketchFiles[0].Path))
76-
assert.Equal(t, "other.ino", filepath.Base(s.OtherSketchFiles[1].Path))
77-
assert.Len(t, s.AdditionalFiles, 3)
78-
assert.Equal(t, "header.h", filepath.Base(s.AdditionalFiles[0].Path))
79-
assert.Equal(t, "s_file.S", filepath.Base(s.AdditionalFiles[1].Path))
80-
assert.Equal(t, "helper.h", filepath.Base(s.AdditionalFiles[2].Path))
71+
s, err = builder.SketchLoad(sketchPath, "")
72+
require.Nil(t, err)
73+
require.NotNil(t, s)
74+
require.Equal(t, mainFilePath, s.MainFile.Path)
75+
require.Len(t, s.OtherSketchFiles, 2)
76+
require.Equal(t, "old.pde", filepath.Base(s.OtherSketchFiles[0].Path))
77+
require.Equal(t, "other.ino", filepath.Base(s.OtherSketchFiles[1].Path))
78+
require.Len(t, s.AdditionalFiles, 3)
79+
require.Equal(t, "header.h", filepath.Base(s.AdditionalFiles[0].Path))
80+
require.Equal(t, "s_file.S", filepath.Base(s.AdditionalFiles[1].Path))
81+
require.Equal(t, "helper.h", filepath.Base(s.AdditionalFiles[2].Path))
8182
}
8283

8384
func TestLoadSketchFolderWrongMain(t *testing.T) {
8485
sketchPath := filepath.Join("testdata", t.Name())
85-
_, err := builder.LoadSketch(sketchPath, "")
86-
assert.Error(t, err)
87-
assert.Contains(t, err.Error(), "unable to find the main sketch file")
86+
_, err := builder.SketchLoad(sketchPath, "")
87+
require.Error(t, err)
88+
require.Contains(t, err.Error(), "unable to find the main sketch file")
8889

89-
_, err = builder.LoadSketch("does/not/exist", "")
90-
assert.Error(t, err)
91-
assert.Contains(t, err.Error(), "no such file or directory")
90+
_, err = builder.SketchLoad("does/not/exist", "")
91+
require.Error(t, err)
92+
require.Contains(t, err.Error(), "no such file or directory")
9293
}
9394

9495
func TestMergeSketchSources(t *testing.T) {
9596
// borrow the sketch from TestLoadSketchFolder to avoid boilerplate
96-
s, err := builder.LoadSketch(filepath.Join("testdata", "TestLoadSketchFolder"), "")
97-
assert.Nil(t, err)
98-
assert.NotNil(t, s)
97+
s, err := builder.SketchLoad(filepath.Join("testdata", "TestLoadSketchFolder"), "")
98+
require.Nil(t, err)
99+
require.NotNil(t, s)
99100

100101
// load expected result
101102
mergedPath := filepath.Join("testdata", t.Name()+".txt")
@@ -104,17 +105,51 @@ func TestMergeSketchSources(t *testing.T) {
104105
t.Fatalf("unable to read golden file %s: %v", mergedPath, err)
105106
}
106107

107-
offset, source := builder.MergeSketchSources(s)
108-
assert.Equal(t, 2, offset)
109-
assert.Equal(t, string(mergedBytes), source)
108+
offset, source := builder.SketchMergeSources(s)
109+
require.Equal(t, 2, offset)
110+
require.Equal(t, string(mergedBytes), source)
110111
}
111112

112113
func TestMergeSketchSourcesArduinoIncluded(t *testing.T) {
113-
s, err := builder.LoadSketch(filepath.Join("testdata", t.Name()), "")
114-
assert.Nil(t, err)
115-
assert.NotNil(t, s)
114+
s, err := builder.SketchLoad(filepath.Join("testdata", t.Name()), "")
115+
require.Nil(t, err)
116+
require.NotNil(t, s)
116117

117118
// ensure not to include Arduino.h when it's already there
118-
_, source := builder.MergeSketchSources(s)
119-
assert.Equal(t, 1, strings.Count(source, "<Arduino.h>"))
119+
_, source := builder.SketchMergeSources(s)
120+
require.Equal(t, 1, strings.Count(source, "<Arduino.h>"))
121+
}
122+
123+
func TestCopyAdditionalFiles(t *testing.T) {
124+
tmp := tmpDirOrDie()
125+
defer os.RemoveAll(tmp)
126+
127+
// load the golden sketch
128+
s1, err := builder.SketchLoad(filepath.Join("testdata", t.Name()), "")
129+
require.Nil(t, err)
130+
require.Len(t, s1.AdditionalFiles, 1)
131+
132+
// copy the sketch over, create a fake main file we don't care about it
133+
// but we need it for `SketchLoad` to suceed later
134+
err = builder.SketchCopyAdditionalFiles(s1, tmp)
135+
require.Nil(t, err)
136+
fakeIno := filepath.Join(tmp, fmt.Sprintf("%s.ino", filepath.Base(tmp)))
137+
require.Nil(t, ioutil.WriteFile(fakeIno, []byte{}, os.FileMode(0644)))
138+
139+
// compare
140+
s2, err := builder.SketchLoad(tmp, "")
141+
require.Nil(t, err)
142+
require.Len(t, s2.AdditionalFiles, 1)
143+
144+
// save file info
145+
info1, err := os.Stat(s2.AdditionalFiles[0].Path)
146+
require.Nil(t, err)
147+
148+
// copy again
149+
err = builder.SketchCopyAdditionalFiles(s1, tmp)
150+
require.Nil(t, err)
151+
152+
// verify file hasn't changed
153+
info2, err := os.Stat(s2.AdditionalFiles[0].Path)
154+
require.Equal(t, info1.ModTime(), info2.ModTime())
120155
}

Diff for: arduino/builder/testdata/TestCopyAdditionalFiles/TestCopyAdditionalFiles.ino

Whitespace-only changes.

Diff for: arduino/builder/testdata/TestCopyAdditionalFiles/include/foo.h

Whitespace-only changes.

Diff for: legacy/builder/additional_sketch_files_copier.go

-85
This file was deleted.

Diff for: legacy/builder/container_add_prototypes.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func (s *ContainerAddPrototypes) Run(ctx *types.Context) error {
6868
}
6969
}
7070

71-
if err := bldr.SaveSketchItemCpp(&sketch.Item{ctx.Sketch.MainFile.Name.String(), []byte(ctx.Source)}, ctx.SketchBuildPath.String()); err != nil {
71+
if err := bldr.SketchSaveItemCpp(&sketch.Item{ctx.Sketch.MainFile.Name.String(), []byte(ctx.Source)}, ctx.SketchBuildPath.String()); err != nil {
7272
return i18n.WrapError(err)
7373
}
7474

0 commit comments

Comments
 (0)