-
-
Notifications
You must be signed in to change notification settings - Fork 398
[breaking] Refactor codebase to use a single Sketch struct #1353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
commands/instances.go
Outdated
@@ -842,29 +842,30 @@ func Upgrade(ctx context.Context, req *rpc.UpgradeRequest, downloadCB DownloadPr | |||
|
|||
// LoadSketch collects and returns all files composing a sketch | |||
func LoadSketch(ctx context.Context, req *rpc.LoadSketchRequest) (*rpc.LoadSketchResponse, error) { | |||
sketch, err := builder.SketchLoad(req.SketchPath, "") | |||
// TODO: This a ToRpc function for the Sketch struct |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to introduce breaking changes with this refactoring but I think changing the gRPC interface LoadSketchResponse
message to reflect the internal Sketch
struct would be a nice improvement for the future.
Also I think we should start adding ToRpc/FromRpc
functions to structs that need to be converted when necessary, as of now that are some functions that handle those conversions scattered around different packages.
// simpleLocalWalk locally replaces filepath.Walk and/but goes through symlinks | ||
func simpleLocalWalk(root string, maxDepth int, walkFn func(path string, info os.FileInfo, err error) error) error { | ||
|
||
info, err := os.Stat(root) | ||
|
||
if err != nil { | ||
return walkFn(root, nil, err) | ||
} | ||
|
||
err = walkFn(root, info, err) | ||
if err == filepath.SkipDir { | ||
return nil | ||
} | ||
|
||
if info.IsDir() { | ||
if maxDepth <= 0 { | ||
return walkFn(root, info, errors.New("Filesystem bottom is too deep (directory recursion or filesystem really deep): "+root)) | ||
} | ||
maxDepth-- | ||
files, err := ioutil.ReadDir(root) | ||
if err == nil { | ||
for _, file := range files { | ||
err = simpleLocalWalk(root+string(os.PathSeparator)+file.Name(), maxDepth, walkFn) | ||
if err == filepath.SkipDir { | ||
return nil | ||
} | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function loops through symlinks... we should implement something similar in go-paths-helper to avoid regressions.
8bc67da
to
7d00b83
Compare
Doesn't this PR make significant breaking changes to the API of the Go packages? Are those considered part of Arduino CLI's public API? It breaks Arduino Lint. I'm OK with breaking changes if they are necessary. But I think it's important to communicate about it to the users. |
Good point @per1234, I didn't take that into consideration at all. Nonetheless am not sure how we could handle breaking changes of the public API, we don't have versioning for it and neither a clearly defined interface for those that want to use it as a library. I always thought that the breaking changes policy applied only to the CLI and gRPC consumers, changes in the public API is certainly something that we must take into account for the future if we want to keep using the CLI as a library but we first need to define a public/private boundary. |
f852cf7
to
69ef64b
Compare
It could be handled the same way as any other breaking change:
I've always thought that all exported components of non-internal packages were the interface. This is why I have taken the measure of making the packages of Arduino Lint and
The Go library is advertised as one of the "three pillars of Arduino CLI":
This is where I got the idea that it was intended to be part of the public API of the project. However, I notice now that almost every interface used by the example program in that "Integration Options" article has been broken in the year since it was written. |
69ef64b
to
ac517be
Compare
Am doing this right now.
Rightly so I'd say, fact is that the CLI is kinda burdened with old decisions that make it hard to separate the public from the private APIs, it would be cool to do it. With the Arduino Lint it has been easier since we started the project from the ground up with a clear idea in mind of what we wanted it to be, not so much for the CLI I'd say.
Yeah, I know that, my main pain point about this is the one I stated above though.
That part of the documentation needs some love probably, the example are really outdated. I think we must avoid using images for those kind of examples, it makes it harder to update. |
ee6b995
to
bf30333
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's a really nice improvement Silvano. Thanks for putting up with my nitpickery.
One last suggestion following on the discussion of breaking changes: there are two things which are supposed to be done to communicate breaking changes: The UPGRADING.md part is done now, but not yet the use of the "[breaking]" prefix on the PR title. I don't think it's so important to add it to the commit messages in this case because when a PR contains multiple commits as this one does, the squashed commit is titled with the PR title. The primary reason for the instructions to use the prefix on commit messages is because if a PR contains only a single commit then the PR title is not used by the merged commit. |
Nitpickery is always welcome. 😁
I'll update the PR title, it uses that when squashing and merging. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼
While revisiting #1201, I came upon this PR and looked at it in a bit more detail. It seems this makes three changes that I'm not entirely sure are intentional:
As I said, for the file error handling of point 1, I'm preparing a draft PR. For 2-4, it would probably be good to modify go-paths-helper's ReadDirRecursive to accept a callback that tests file/dir names (and probably an isDir boolean) for inclusion in the result? |
Before commit e7d4eaa ([breaking] Refactor codebase to use a single Sketch struct (arduino#1353)), any sketch file that could not be opened would report a fatal error, but the behavior was changed to silently skip such failing files instead. This restores the original behavior and fails to load a sketch of some of the contained files (after filtering on file extension, so this only includes files that are actually intended to be processed), instead of silently excluding the files (which likely produces hard to explain compilation errors later).
Before commit e7d4eaa ([breaking] Refactor codebase to use a single Sketch struct (arduino#1353)), any sketch file that could not be opened would report a fatal error, but the behavior was changed to silently skip such failing files instead. This restores the original behavior and fails to load a sketch of some of the contained files (after filtering on file extension, so this only includes files that are actually intended to be processed), instead of silently excluding the files (which likely produces hard to explain compilation errors later).
Please check if the PR fulfills these requirements
before creating one)
our contributing guidelines
UPGRADING.md
has been updated with a migration guide (for breaking changes)This enhances the codebase by removing duplicated ways of storing a Sketch data.
There are currently 3 different packages that declare a
Sketch
struct, often keeping track of different informations about a Sketch or using different types for the same underlying data. This made it necessary to have tons of back and forth conversions about the different types often losing information or making it hard to understand the code when working on it.The 3 different packages are:
sketch
inarduino/sketch/sketch.go
sketches
inarduino/sketches/sketches.go
types
inlegacy/builder/types/types.go
What is the new behavior?
Now there is only one
Sketch
struct defined in thesketch
ofarduino/sketch/sketch.go
, it contains all the informations neededby the codebase.
titled accordingly?
Yes, only in the exposed public code interface, gRPC and CLI are untouched.
This fixes #1178.
It's important that we test this in a thorough manner since it touches the
legacy
package quite a bit.The handling of symlinks when found in the Sketch folder is also enhanced, previously they caused several issues like #358 and #424, both handled by #421 and #462.
The integration test
test_compile_with_sketch_with_symlink_selfloop
introduced by #462 used to verify compilation would fail when trying to compile a Sketch with a symlink loop but now that is handled gracefully when a Sketch is loaded internally, so compilation now succeds.Related to this there is also the unit test
TestNewSketchFolderSymlink
to verify that loading of a Sketch with symlinks works fine, previously this wasTestLoadSketchFolderSymlink
inarduino/builder/sketch_test.go
but has been moved toarduino/sketch/sketch_test.go
.See how to contribute