Skip to content

Commit

Permalink
Added gRPC command SetSketchDefaults to change sketch attached boar…
Browse files Browse the repository at this point in the history
…d/port (#2217)

* Remove some direct access to sketch.Sketch

* Moved `LoadSketch` command in the proper place

* Removed some accesses to sketch.Sketch

The required information are returned from LoadSketch.

* Added SetSketchDefaults gRPC call

This allows to finally remove wrong access to `sketch.Sketch` from `cli`
package.

* Updated docs

* Fixed integration tests

* Update rpc/cc/arduino/cli/commands/v1/commands.proto

Co-authored-by: Alessio Perugini <alessioper.98@gmail.com>

---------

Co-authored-by: Alessio Perugini <alessioper.98@gmail.com>
  • Loading branch information
cmaglie and alessio-perugini authored Jun 19, 2023
1 parent 82e6f5d commit 223d3fa
Show file tree
Hide file tree
Showing 20 changed files with 1,001 additions and 550 deletions.
13 changes: 13 additions & 0 deletions arduino/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,19 @@ func (e *CantCreateSketchError) Unwrap() error {
return e.Cause
}

// CantUpdateSketchError is returned when the sketch cannot be updated
type CantUpdateSketchError struct {
Cause error
}

func (e *CantUpdateSketchError) Error() string {
return composeErrorMsg(tr("Can't update sketch"), e.Cause)
}

func (e *CantUpdateSketchError) Unwrap() error {
return e.Cause
}

// CantOpenSketchError is returned when the sketch is not found or cannot be opened
type CantOpenSketchError struct {
Cause error
Expand Down
8 changes: 7 additions & 1 deletion commands/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,13 @@ func (s *ArduinoCoreServerImpl) NewSketch(ctx context.Context, req *rpc.NewSketc

// LoadSketch FIXMEDOC
func (s *ArduinoCoreServerImpl) LoadSketch(ctx context.Context, req *rpc.LoadSketchRequest) (*rpc.LoadSketchResponse, error) {
resp, err := commands.LoadSketch(ctx, req)
resp, err := sketch.LoadSketch(ctx, req)
return resp, convertErrorToRPCStatus(err)
}

// SetSketchDefaults FIXMEDOC
func (s *ArduinoCoreServerImpl) SetSketchDefaults(ctx context.Context, req *rpc.SetSketchDefaultsRequest) (*rpc.SetSketchDefaultsResponse, error) {
resp, err := sketch.SetSketchDefaults(ctx, req)
return resp, convertErrorToRPCStatus(err)
}

Expand Down
32 changes: 0 additions & 32 deletions commands/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,38 +569,6 @@ func UpdateIndex(ctx context.Context, req *rpc.UpdateIndexRequest, downloadCB rp
return nil
}

// LoadSketch collects and returns all files composing a sketch
func LoadSketch(ctx context.Context, req *rpc.LoadSketchRequest) (*rpc.LoadSketchResponse, error) {
// TODO: This should be a ToRpc function for the Sketch struct
sk, err := sketch.New(paths.New(req.SketchPath))
if err != nil {
return nil, &arduino.CantOpenSketchError{Cause: err}
}

otherSketchFiles := make([]string, sk.OtherSketchFiles.Len())
for i, file := range sk.OtherSketchFiles {
otherSketchFiles[i] = file.String()
}

additionalFiles := make([]string, sk.AdditionalFiles.Len())
for i, file := range sk.AdditionalFiles {
additionalFiles[i] = file.String()
}

rootFolderFiles := make([]string, sk.RootFolderFiles.Len())
for i, file := range sk.RootFolderFiles {
rootFolderFiles[i] = file.String()
}

return &rpc.LoadSketchResponse{
MainFile: sk.MainFile.String(),
LocationPath: sk.FullPath.String(),
OtherSketchFiles: otherSketchFiles,
AdditionalFiles: additionalFiles,
RootFolderFiles: rootFolderFiles,
}, nil
}

// firstUpdate downloads libraries and packages indexes if they don't exist.
// This ideally is only executed the first time the CLI is run.
func firstUpdate(ctx context.Context, instance *rpc.Instance, downloadCb func(msg *rpc.DownloadProgress), externalPackageIndexes []*url.URL) error {
Expand Down
61 changes: 61 additions & 0 deletions commands/sketch/load.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.

package sketch

import (
"context"

"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/sketch"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
paths "github.com/arduino/go-paths-helper"
)

// LoadSketch collects and returns all files composing a sketch
func LoadSketch(ctx context.Context, req *rpc.LoadSketchRequest) (*rpc.LoadSketchResponse, error) {
// TODO: This should be a ToRpc function for the Sketch struct
sk, err := sketch.New(paths.New(req.SketchPath))
if err != nil {
return nil, &arduino.CantOpenSketchError{Cause: err}
}

otherSketchFiles := make([]string, sk.OtherSketchFiles.Len())
for i, file := range sk.OtherSketchFiles {
otherSketchFiles[i] = file.String()
}

additionalFiles := make([]string, sk.AdditionalFiles.Len())
for i, file := range sk.AdditionalFiles {
additionalFiles[i] = file.String()
}

rootFolderFiles := make([]string, sk.RootFolderFiles.Len())
for i, file := range sk.RootFolderFiles {
rootFolderFiles[i] = file.String()
}

defaultPort, defaultProtocol := sk.GetDefaultPortAddressAndProtocol()
return &rpc.LoadSketchResponse{
MainFile: sk.MainFile.String(),
LocationPath: sk.FullPath.String(),
OtherSketchFiles: otherSketchFiles,
AdditionalFiles: additionalFiles,
RootFolderFiles: rootFolderFiles,
DefaultFqbn: sk.GetDefaultFQBN(),
DefaultPort: defaultPort,
DefaultProtocol: defaultProtocol,
}, nil
}
57 changes: 57 additions & 0 deletions commands/sketch/set_defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.

package sketch

import (
"context"

"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/sketch"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
paths "github.com/arduino/go-paths-helper"
)

// SetSketchDefaults updates the sketch project file (sketch.yaml) with the given defaults
// for the values `default_fqbn`, `default_port`, and `default_protocol`.
func SetSketchDefaults(ctx context.Context, req *rpc.SetSketchDefaultsRequest) (*rpc.SetSketchDefaultsResponse, error) {
sk, err := sketch.New(paths.New(req.SketchPath))
if err != nil {
return nil, &arduino.CantOpenSketchError{Cause: err}
}

oldAddress, oldProtocol := sk.GetDefaultPortAddressAndProtocol()
res := &rpc.SetSketchDefaultsResponse{
DefaultFqbn: sk.GetDefaultFQBN(),
DefaultPortAddress: oldAddress,
DefaultPortProtocol: oldProtocol,
}

if fqbn := req.GetDefaultFqbn(); fqbn != "" {
if err := sk.SetDefaultFQBN(fqbn); err != nil {
return nil, &arduino.CantUpdateSketchError{Cause: err}
}
res.DefaultFqbn = fqbn
}
if newAddress, newProtocol := req.GetDefaultPortAddress(), req.GetDefaultPortProtocol(); newAddress != "" {
if err := sk.SetDefaultPort(newAddress, newProtocol); err != nil {
return nil, &arduino.CantUpdateSketchError{Cause: err}
}
res.DefaultPortAddress = newAddress
res.DefaultPortProtocol = newProtocol
}

return res, nil
}
7 changes: 7 additions & 0 deletions docs/UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

Here you can find a list of migration guides to handle breaking changes between releases of the CLI.

## 0.34.0

### golang API: `LoadSketch` function has been moved

The function `github.com/arduino/arduino-cli/commands.LoadSketch` has been moved to package
`github.com/arduino/arduino-cli/commands/sketch.LoadSketch`. You must change the import accordingly.

## 0.33.0

### gRPC `cc.arduino.cli.commands.v1.Compile` command now return expanded build_properties by default.
Expand Down
11 changes: 4 additions & 7 deletions internal/cli/arguments/fqbn.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"strings"

"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/arduino-cli/internal/cli/feedback"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -70,12 +69,10 @@ func (f *Fqbn) Set(fqbn string) {
// - the port is not found, in this case nil is returned
// - the FQBN autodetection fail, in this case the function prints an error and
// terminates the execution
func CalculateFQBNAndPort(portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance, sk *sketch.Sketch) (string, *rpc.Port) {
// TODO: REMOVE sketch.Sketch from here

func CalculateFQBNAndPort(portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance, defaultFQBN, defaultAddress, defaultProtocol string) (string, *rpc.Port) {
fqbn := fqbnArg.String()
if fqbn == "" && sk != nil {
fqbn = sk.GetDefaultFQBN()
if fqbn == "" {
fqbn = defaultFQBN
}
if fqbn == "" {
if portArgs == nil || portArgs.address == "" {
Expand All @@ -88,7 +85,7 @@ func CalculateFQBNAndPort(portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance,
return fqbn, port
}

port, err := portArgs.GetPort(instance, sk)
port, err := portArgs.GetPort(instance, defaultAddress, defaultProtocol)
if err != nil {
feedback.Fatal(tr("Error getting port metadata: %v", err), feedback.ErrGeneric)
}
Expand Down
14 changes: 6 additions & 8 deletions internal/cli/arguments/port.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (

"github.com/arduino/arduino-cli/arduino"
"github.com/arduino/arduino-cli/arduino/discovery"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/commands/board"
"github.com/arduino/arduino-cli/internal/cli/feedback"
Expand Down Expand Up @@ -57,11 +56,12 @@ func (p *Port) AddToCommand(cmd *cobra.Command) {
// This method allows will bypass the discoveries if:
// - a nil instance is passed: in this case the plain port and protocol arguments are returned (even if empty)
// - a protocol is specified: in this case the discoveries are not needed to autodetect the protocol.
func (p *Port) GetPortAddressAndProtocol(instance *rpc.Instance, sk *sketch.Sketch) (string, string, error) {
func (p *Port) GetPortAddressAndProtocol(instance *rpc.Instance, defaultAddress, defaultProtocol string) (string, string, error) {
if p.protocol != "" || instance == nil {
return p.address, p.protocol, nil
}
port, err := p.GetPort(instance, sk)

port, err := p.GetPort(instance, defaultAddress, defaultProtocol)
if err != nil {
return "", "", err
}
Expand All @@ -70,15 +70,13 @@ func (p *Port) GetPortAddressAndProtocol(instance *rpc.Instance, sk *sketch.Sket

// GetPort returns the Port obtained by parsing command line arguments.
// The extra metadata for the ports is obtained using the pluggable discoveries.
func (p *Port) GetPort(instance *rpc.Instance, sk *sketch.Sketch) (*discovery.Port, error) {
// TODO: REMOVE sketch.Sketch from here
func (p *Port) GetPort(instance *rpc.Instance, defaultAddress, defaultProtocol string) (*discovery.Port, error) {
// TODO: REMOVE discovery from here (use board.List instead)

address := p.address
protocol := p.protocol

if address == "" && sk != nil {
address, protocol = sk.GetDefaultPortAddressAndProtocol()
if address == "" && (defaultAddress != "" || defaultProtocol != "") {
address, protocol = defaultAddress, defaultProtocol
}
if address == "" {
// If no address is provided we assume the user is trying to upload
Expand Down
9 changes: 0 additions & 9 deletions internal/cli/arguments/sketch.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,6 @@ func InitSketchPath(path string) (sketchPath *paths.Path) {
return sketchPath
}

// NewSketch is a helper function useful to create a sketch instance
func NewSketch(sketchPath *paths.Path) *sketch.Sketch {
sketch, err := sketch.New(sketchPath)
if err != nil {
feedback.Fatal(tr("Error opening sketch: %v", err), feedback.ErrGeneric)
}
return sketch
}

// WarnDeprecatedFiles warns the user that a type of sketch files are deprecated
func WarnDeprecatedFiles(sketchPath *paths.Path) {
// .pde files are still supported but deprecated, this warning urges the user to rename them
Expand Down
46 changes: 20 additions & 26 deletions internal/cli/board/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@
package board

import (
"context"
"fmt"
"os"

"github.com/arduino/arduino-cli/commands/sketch"
"github.com/arduino/arduino-cli/internal/cli/arguments"
"github.com/arduino/arduino-cli/internal/cli/feedback"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -51,37 +54,28 @@ func initAttachCommand() *cobra.Command {

func runAttachCommand(path string, port *arguments.Port, fqbn string) {
sketchPath := arguments.InitSketchPath(path)
sk := arguments.NewSketch(sketchPath)

var currentPort *boardAttachPortResult
if currentAddress, currentProtocol := sk.GetDefaultPortAddressAndProtocol(); currentAddress != "" {
currentPort = &boardAttachPortResult{
Address: currentAddress,
Protocol: currentProtocol,
}
}
current := &boardAttachResult{
Port: currentPort,
Fqbn: sk.GetDefaultFQBN(),
portAddress, portProtocol, _ := port.GetPortAddressAndProtocol(nil, "", "")
newDefaults, err := sketch.SetSketchDefaults(context.Background(), &rpc.SetSketchDefaultsRequest{
SketchPath: sketchPath.String(),
DefaultFqbn: fqbn,
DefaultPortAddress: portAddress,
DefaultPortProtocol: portProtocol,
})
if err != nil {
feedback.FatalError(err, feedback.ErrGeneric)
}
address, protocol, _ := port.GetPortAddressAndProtocol(nil, sk)
if address != "" {
if err := sk.SetDefaultPort(address, protocol); err != nil {
feedback.Fatal(fmt.Sprintf("%s: %s", tr("Error saving sketch metadata"), err), feedback.ErrGeneric)
}
current.Port = &boardAttachPortResult{
Address: address,
Protocol: protocol,
}

res := &boardAttachResult{
Fqbn: newDefaults.GetDefaultFqbn(),
}
if fqbn != "" {
if err := sk.SetDefaultFQBN(fqbn); err != nil {
feedback.Fatal(fmt.Sprintf("%s: %s", tr("Error saving sketch metadata"), err), feedback.ErrGeneric)
if newDefaults.GetDefaultPortAddress() != "" {
res.Port = &boardAttachPortResult{
Address: newDefaults.GetDefaultPortAddress(),
Protocol: newDefaults.GetDefaultPortProtocol(),
}
current.Fqbn = fqbn
}

feedback.PrintResult(current)
feedback.PrintResult(res)
}

type boardAttachPortResult struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/burnbootloader/burnbootloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func runBootloaderCommand(command *cobra.Command, args []string) {
logrus.Info("Executing `arduino-cli burn-bootloader`")

// We don't need a Sketch to upload a board's bootloader
discoveryPort, err := port.GetPort(instance, nil)
discoveryPort, err := port.GetPort(instance, "", "")
if err != nil {
feedback.Fatal(tr("Error during Upload: %v", err), feedback.ErrGeneric)
}
Expand Down
Loading

0 comments on commit 223d3fa

Please sign in to comment.