Skip to content

Add smart artifact find during upload #655

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cli/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ func run(cmd *cobra.Command, args []string) {
Verbose: verbose,
Verify: verify,
ImportFile: exportFile,
BuildPath: buildPath,
}, os.Stdout, os.Stderr)

if err != nil {
Expand Down
82 changes: 67 additions & 15 deletions commands/upload/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ import (
"fmt"
"io"
"net/url"
"os"
"path/filepath"
"strings"
"time"

"github.com/arduino/arduino-cli/arduino/builder"
"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/sketches"
"github.com/arduino/arduino-cli/cli/feedback"
Expand Down Expand Up @@ -149,6 +148,15 @@ func Upload(ctx context.Context, req *rpc.UploadReq, outStream io.Writer, errStr
uploadProperties.Set("upload.verify", uploadProperties.Get("upload.params.noverify"))
}

// Extract the final file extension from the upload recipe
ext, err := getExtensionFromRecipe(uploadProperties, err)
if err != nil {
return nil, fmt.Errorf("recipe parsing unsuccessful: %s", err)
}

// Start smart fetch process for the built sketch
var uploadPaths []*paths.Path

// Set path to compiled binary
// Make the filename without the FQBN configs part
fqbn.Configs = properties.NewMap()
Expand All @@ -157,31 +165,51 @@ func Upload(ctx context.Context, req *rpc.UploadReq, outStream io.Writer, errStr
var importPath *paths.Path
var importFile string
if req.GetImportFile() == "" {
// Search for built sketch to upload in CLI param importFile (if passed)...
importPath = sketch.FullPath
importFile = sketch.Name + "." + fqbnSuffix
} else {
// ...or in the Export path (the Sketch Path)
importPath = paths.New(req.GetImportFile()).Parent()
importFile = paths.New(req.GetImportFile()).Base()
}

outputTmpFile, ok := uploadProperties.GetOk("recipe.output.tmp_file")
outputTmpFile = uploadProperties.ExpandPropsInString(outputTmpFile)
if !ok {
return nil, fmt.Errorf("property 'recipe.output.tmp_file' not defined")
}
ext := filepath.Ext(outputTmpFile)
// Remove file extension if any from input
if strings.HasSuffix(importFile, ext) {
importFile = importFile[:len(importFile)-len(ext)]
}

uploadProperties.SetPath("build.path", importPath)
uploadProperties.Set("build.project_name", importFile)
uploadFile := importPath.Join(importFile + ext)
if _, err := uploadFile.Stat(); err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("compiled sketch %s not found", uploadFile.String())
uploadPaths = append(uploadPaths, importPath.Join(importFile+ext))

// Try fetch the file to upload using CLI param buildPath
if req.GetBuildPath() != "" {
buildPath := paths.New(req.GetBuildPath())
// If we search inside the build.path, compile artifact do not have the fqbnSuffix in the filename
uploadPaths = append(uploadPaths, buildPath.Join(sketch.Name+".ino"+ext))
}

// Try fetch the file to upload using builder.GenBuildPath(sketchPath)
fallbackBuildPath := builder.GenBuildPath(sketchPath)
// If we search inside the build.path, compile artifact do not have the fqbnSuffix in the filename
uploadPaths = append(uploadPaths, fallbackBuildPath.Join(sketch.Name+".ino"+ext))

for _, p := range uploadPaths {
if _, err := p.Stat(); err == nil {
uploadProperties.SetPath("build.path", p.Parent())
name := p.Base()
name = name[:len(name)-len(ext)]
uploadProperties.Set("build.project_name", name)
break
} else {
logrus.Warnf("Built sketch opening error in %s: %s", p, err)
}
return nil, fmt.Errorf("cannot open sketch: %s", err)
}

if n, nOK := uploadProperties.GetOk("build.project_name"); n == "" || !nOK {
return nil, fmt.Errorf("cannot find file to upload")
}
if p, pOK := uploadProperties.GetOk("build.path"); p == "" || !pOK {
return nil, fmt.Errorf("cannot find file to upload")
}

// Perform reset via 1200bps touch if requested
Expand Down Expand Up @@ -263,6 +291,30 @@ func Upload(ctx context.Context, req *rpc.UploadReq, outStream io.Writer, errStr
return &rpc.UploadResp{}, nil
}

func getExtensionFromRecipe(uploadProperties *properties.Map, err error) (string, error) {
recipe := uploadProperties.Get("upload.pattern")
cmdLine := uploadProperties.ExpandPropsInString(recipe)
cmdArgs, err := properties.SplitQuotedString(cmdLine, `"'`, false)
if err != nil {
return "", err
}

var uploadInputPath *paths.Path
for _, t := range cmdArgs {
if strings.Contains(t, "build.project_name") {
uploadInputPath = paths.New(t)
break
}
}

if uploadInputPath == nil {
return "", fmt.Errorf("cannot find upload file extension in upload recipe")
}
// trim extension from "}" and following recipe tokens as they could be erroneously included by the Ext() func
trimmedExt := strings.Split(uploadInputPath.Ext(), "}")[0]
return trimmedExt, nil
}

func touchSerialPortAt1200bps(port string) error {
logrus.Infof("Touching port %s at 1200bps", port)

Expand Down
Loading