From ecec6761c6dbc9d495cc6d6d52b7392c15a5a030 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 1 Dec 2022 16:26:41 +0100 Subject: [PATCH 01/45] Added source code static-check to enforce `--format` output. The first test run gives: === RUN TestNoDirectOutputToStdOut burnbootloader/burnbootloader.go:85:5: object `os.Stdout` should not be used in this package (use `feedback.*` instead) burnbootloader/burnbootloader.go:85:16: object `os.Stderr` should not be used in this package (use `feedback.*` instead) compile/compile.go:235:84: object `os.Stdout` should not be used in this package (use `feedback.*` instead) compile/compile.go:235:95: object `os.Stderr` should not be used in this package (use `feedback.*` instead) compile/compile.go:274:72: object `os.Stdout` should not be used in this package (use `feedback.*` instead) compile/compile.go:274:83: object `os.Stderr` should not be used in this package (use `feedback.*` instead) compile/compile.go:296:4: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:297:4: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:298:4: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:305:3: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:306:3: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:307:3: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:308:3: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:309:3: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:311:3: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:313:4: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:319:4: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:321:5: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:325:4: function `fmt.Println` should not be used in this package (use `feedback.*` instead) compile/compile.go:326:4: function `fmt.Print` should not be used in this package (use `feedback.*` instead) completion/completion.go:58:34: object `os.Stdout` should not be used in this package (use `feedback.*` instead) completion/completion.go:61:38: object `os.Stdout` should not be used in this package (use `feedback.*` instead) completion/completion.go:63:32: object `os.Stdout` should not be used in this package (use `feedback.*` instead) completion/completion.go:66:32: object `os.Stdout` should not be used in this package (use `feedback.*` instead) completion/completion.go:68:38: object `os.Stdout` should not be used in this package (use `feedback.*` instead) daemon/interceptors.go:29:19: object `os.Stdout` should not be used in this package (use `feedback.*` instead) debug/debug.go:106:82: object `os.Stdout` should not be used in this package (use `feedback.*` instead) monitor/term.go:38:9: object `os.Stdout` should not be used in this package (use `feedback.*` instead) output/rpc_progress.go:115:4: function `fmt.Print` should not be used in this package (use `feedback.*` instead) output/rpc_progress.go:117:5: function `fmt.Println` should not be used in this package (use `feedback.*` instead) output/rpc_progress.go:119:5: function `fmt.Println` should not be used in this package (use `feedback.*` instead) upload/upload.go:163:5: object `os.Stdout` should not be used in this package (use `feedback.*` instead) upload/upload.go:163:16: object `os.Stderr` should not be used in this package (use `feedback.*` instead) cli.go:215:4: function `fmt.Println` should not be used in this package (use `feedback.*` instead) --- FAIL: TestNoDirectOutputToStdOut (0.01s) FAIL exit status 1 FAIL github.com/arduino/arduino-cli/cli 0.019s --- cli/cli_test.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 cli/cli_test.go diff --git a/cli/cli_test.go b/cli/cli_test.go new file mode 100644 index 00000000000..ac36a819665 --- /dev/null +++ b/cli/cli_test.go @@ -0,0 +1,105 @@ +// This file is part of arduino-cli. +// +// Copyright 2022 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 cli_test + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "strings" + "testing" + + "github.com/arduino/go-paths-helper" + "github.com/stretchr/testify/require" +) + +func TestNoDirectOutputToStdOut(t *testing.T) { + dirs, err := paths.New(".").ReadDirRecursiveFiltered( + paths.FilterOutNames("testdata"), // skip all testdata folders + paths.AndFilter( + paths.FilterDirectories(), // analyze only packages + paths.FilterOutNames("feedback"), // skip feedback package + )) + require.NoError(t, err) + dirs.Add(paths.New(".")) + + for _, dir := range dirs { + testDir(t, dir) + } +} + +func testDir(t *testing.T, dir *paths.Path) { + fset := token.NewFileSet() + pkgs, err := parser.ParseDir(fset, dir.String(), nil, parser.ParseComments) + require.NoError(t, err) + + for _, pkg := range pkgs { + for _, file := range pkg.Files { + // Do not analyze test files + if strings.HasSuffix(expr(file.Name), "_test") { + continue + } + + ast.Inspect(file, func(n ast.Node) bool { + return inspect(t, fset, n) + }) + } + } +} + +func inspect(t *testing.T, fset *token.FileSet, node ast.Node) bool { + switch n := node.(type) { + case *ast.CallExpr: + name := expr(n.Fun) + if strings.HasPrefix(name, "fmt.P") { + fmt.Printf("%s: function `%s` should not be used in this package (use `feedback.*` instead)\n", fset.Position(n.Pos()), name) + t.Fail() + } + case *ast.SelectorExpr: + wanted := map[string]bool{ + "os.Stdout": true, + "os.Stderr": true, + } + name := expr(n) + if wanted[name] { + fmt.Printf("%s: object `%s` should not be used in this package (use `feedback.*` instead)\n", fset.Position(n.Pos()), name) + t.Fail() + } + } + return true +} + +// expr returns the string representation of an expression, it doesn't expand function arguments or array index. +func expr(_e ast.Expr) string { + switch e := _e.(type) { + case *ast.ArrayType: + return "[...]" + expr(e.Elt) + case *ast.CallExpr: + return expr(e.Fun) + "(...)" + case *ast.FuncLit: + return "func(...) {...}" + case *ast.SelectorExpr: + return expr(e.X) + "." + e.Sel.String() + case *ast.IndexExpr: + return expr(e.X) + "[...]" + case *ast.Ident: + return e.String() + default: + msg := fmt.Sprintf("UNKWOWN: %T", e) + panic(msg) + } +} From 3604efa79bfb6b086d3e66648f414134496acfb7 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 1 Dec 2022 18:53:47 +0100 Subject: [PATCH 02/45] Slightly improved naming/docs of OutputFormat enumeration Also changed a condition in a more meaningful way. --- cli/cli.go | 2 +- cli/feedback/feedback.go | 26 +++++++++++++++----------- cli/version/version.go | 2 +- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/cli/cli.go b/cli/cli.go index a1e93998897..4fc7c366da0 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -146,7 +146,7 @@ func toLogLevel(s string) (t logrus.Level, found bool) { func parseFormatString(arg string) (feedback.OutputFormat, bool) { f, found := map[string]feedback.OutputFormat{ "json": feedback.JSON, - "jsonmini": feedback.JSONMini, + "jsonmini": feedback.MinifiedJSON, "text": feedback.Text, "yaml": feedback.YAML, }[strings.ToLower(arg)] diff --git a/cli/feedback/feedback.go b/cli/feedback/feedback.go index 0a27cc4f5cf..5d08931214e 100644 --- a/cli/feedback/feedback.go +++ b/cli/feedback/feedback.go @@ -29,17 +29,17 @@ import ( "google.golang.org/grpc/status" ) -// OutputFormat is used to determine the output format +// OutputFormat is an output format type OutputFormat int const ( - // Text means plain text format, suitable for ansi terminals + // Text is the plain text format, suitable for interactive terminals Text OutputFormat = iota - // JSON means JSON format + // JSON format JSON - // JSONMini is identical to JSON but without whitespaces - JSONMini - // YAML means YAML format + // MinifiedJSON format + MinifiedJSON + // YAML format YAML ) @@ -114,12 +114,14 @@ func (fb *Feedback) Printf(format string, v ...interface{}) { // Print behaves like fmt.Print but writes on the out writer and adds a newline. func (fb *Feedback) Print(v interface{}) { switch fb.format { - case JSON, JSONMini: + case JSON, MinifiedJSON: fb.printJSON(v) case YAML: fb.printYAML(v) - default: + case Text: fmt.Fprintln(fb.out, v) + default: + panic(fmt.Sprintf("Invalid output format: %v", fb.format)) } } @@ -153,7 +155,7 @@ func (fb *Feedback) printJSON(v interface{}) { var err error if fb.format == JSON { d, err = json.MarshalIndent(v, "", " ") - } else if fb.format == JSONMini { + } else if fb.format == MinifiedJSON { d, err = json.Marshal(v) } if err != nil { @@ -179,11 +181,13 @@ func (fb *Feedback) printYAML(v interface{}) { // structure. func (fb *Feedback) PrintResult(res Result) { switch fb.format { - case JSON, JSONMini: + case JSON, MinifiedJSON: fb.printJSON(res.Data()) case YAML: fb.printYAML(res.Data()) - default: + case Text: fb.Print(res.String()) + default: + panic(fmt.Sprintf("Invalid output format: %v", fb.format)) } } diff --git a/cli/version/version.go b/cli/version/version.go index 73a708c5450..52a479ae6fa 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -61,7 +61,7 @@ func runVersionCommand(cmd *cobra.Command, args []string) { latestVersion := updater.ForceCheckForUpdate(currentVersion) versionInfo := globals.VersionInfo - if f := feedback.GetFormat(); (f == feedback.JSON || f == feedback.JSONMini || f == feedback.YAML) && latestVersion != nil { + if feedback.GetFormat() != feedback.Text && latestVersion != nil { // Set this only we managed to get the latest version versionInfo.LatestVersion = latestVersion.String() } From 922a3eb7b984632907b8274fcb57b63d04bcf055 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 1 Dec 2022 19:06:28 +0100 Subject: [PATCH 03/45] Removed `feedback.Feedback` since only the global instance is used We may think of bringing it back again in the future if the global instance will be removed in a major refactoring of the CLI. --- cli/feedback/exported.go | 91 -------------------------------- cli/feedback/feedback.go | 111 +++++++++++++++++---------------------- 2 files changed, 48 insertions(+), 154 deletions(-) delete mode 100644 cli/feedback/exported.go diff --git a/cli/feedback/exported.go b/cli/feedback/exported.go deleted file mode 100644 index 9b10ee5fe37..00000000000 --- a/cli/feedback/exported.go +++ /dev/null @@ -1,91 +0,0 @@ -// 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 feedback - -import ( - "io" -) - -var ( - fb = DefaultFeedback() -) - -// SetDefaultFeedback lets callers override the default feedback object. Mostly -// useful for testing. -func SetDefaultFeedback(f *Feedback) { - fb = f -} - -// SetOut can be used to change the out writer at runtime -func SetOut(out io.Writer) { - fb.out = out -} - -// SetErr can be used to change the err writer at runtime -func SetErr(err io.Writer) { - fb.err = err -} - -// SetFormat can be used to change the output format at runtime -func SetFormat(f OutputFormat) { - fb.SetFormat(f) -} - -// GetFormat returns the currently set output format -func GetFormat() OutputFormat { - return fb.GetFormat() -} - -// OutputWriter returns the underlying io.Writer to be used when the Print* -// api is not enough -func OutputWriter() io.Writer { - return fb.OutputWriter() -} - -// ErrorWriter is the same as OutputWriter but exposes the underlying error -// writer -func ErrorWriter() io.Writer { - return fb.ErrorWriter() -} - -// Printf behaves like fmt.Printf but writes on the out writer and adds a newline. -func Printf(format string, v ...interface{}) { - fb.Printf(format, v...) -} - -// Print behaves like fmt.Print but writes on the out writer and adds a newline. -func Print(v interface{}) { - fb.Print(v) -} - -// Errorf behaves like fmt.Printf but writes on the error writer and adds a -// newline. It also logs the error. -func Errorf(format string, v ...interface{}) { - fb.Errorf(format, v...) -} - -// Error behaves like fmt.Print but writes on the error writer and adds a -// newline. It also logs the error. -func Error(v ...interface{}) { - fb.Error(v...) -} - -// PrintResult is a convenient wrapper to provide feedback for complex data, -// where the contents can't be just serialized to JSON but requires more -// structure. -func PrintResult(res Result) { - fb.PrintResult(res) -} diff --git a/cli/feedback/feedback.go b/cli/feedback/feedback.go index 5d08931214e..09791e7dbbd 100644 --- a/cli/feedback/feedback.go +++ b/cli/feedback/feedback.go @@ -13,6 +13,8 @@ // Arduino software without disclosing the source code of your own applications. // To purchase a commercial license, send an email to license@arduino.cc. +// Package feedback provides an uniform API that can be used to +// print feedback to the users in different formats. package feedback import ( @@ -22,11 +24,10 @@ import ( "io" "os" - "gopkg.in/yaml.v2" - "github.com/arduino/arduino-cli/i18n" "github.com/sirupsen/logrus" "google.golang.org/grpc/status" + "gopkg.in/yaml.v2" ) // OutputFormat is an output format @@ -43,6 +44,12 @@ const ( YAML ) +var ( + stdOut io.Writer = os.Stdout + stdErr io.Writer = os.Stderr + format OutputFormat = Text +) + // Result is anything more complex than a sentence that needs to be printed // for the user. type Result interface { @@ -50,84 +57,62 @@ type Result interface { Data() interface{} } -// Feedback wraps an io.Writer and provides an uniform API the CLI can use to -// provide feedback to the users. -type Feedback struct { - out io.Writer - err io.Writer - format OutputFormat -} - var tr = i18n.Tr -// New creates a Feedback instance -func New(out, err io.Writer, format OutputFormat) *Feedback { - return &Feedback{ - out: out, - err: err, - format: format, - } -} - -// DefaultFeedback provides a basic feedback object to be used as default. -func DefaultFeedback() *Feedback { - return New(os.Stdout, os.Stderr, Text) -} - // SetOut can be used to change the out writer at runtime -func (fb *Feedback) SetOut(out io.Writer) { - fb.out = out +func SetOut(out io.Writer) { + stdOut = out } // SetErr can be used to change the err writer at runtime -func (fb *Feedback) SetErr(err io.Writer) { - fb.err = err +func SetErr(err io.Writer) { + stdErr = err } // SetFormat can be used to change the output format at runtime -func (fb *Feedback) SetFormat(f OutputFormat) { - fb.format = f +func SetFormat(f OutputFormat) { + format = f } // GetFormat returns the output format currently set -func (fb *Feedback) GetFormat() OutputFormat { - return fb.format +func GetFormat() OutputFormat { + return format } // OutputWriter returns the underlying io.Writer to be used when the Print* -// api is not enough. -func (fb *Feedback) OutputWriter() io.Writer { - return fb.out +// api is not enough +func OutputWriter() io.Writer { + return stdOut } // ErrorWriter is the same as OutputWriter but exposes the underlying error // writer. -func (fb *Feedback) ErrorWriter() io.Writer { - return fb.out +func ErrorWriter() io.Writer { + return stdErr } // Printf behaves like fmt.Printf but writes on the out writer and adds a newline. -func (fb *Feedback) Printf(format string, v ...interface{}) { - fb.Print(fmt.Sprintf(format, v...)) +func Printf(format string, v ...interface{}) { + Print(fmt.Sprintf(format, v...)) } // Print behaves like fmt.Print but writes on the out writer and adds a newline. -func (fb *Feedback) Print(v interface{}) { - switch fb.format { +func Print(v interface{}) { + switch format { case JSON, MinifiedJSON: - fb.printJSON(v) + printJSON(v) case YAML: - fb.printYAML(v) + printYAML(v) case Text: - fmt.Fprintln(fb.out, v) + fmt.Fprintln(stdOut, v) default: - panic(fmt.Sprintf("Invalid output format: %v", fb.format)) + panic("unknown output format") } } // Errorf behaves like fmt.Printf but writes on the error writer and adds a // newline. It also logs the error. -func (fb *Feedback) Errorf(format string, v ...interface{}) { +func Errorf(format string, v ...interface{}) { // Unbox grpc status errors for i := range v { if s, isStatus := v[i].(*status.Status); isStatus { @@ -138,56 +123,56 @@ func (fb *Feedback) Errorf(format string, v ...interface{}) { } } } - fb.Error(fmt.Sprintf(format, v...)) + Error(fmt.Sprintf(format, v...)) } // Error behaves like fmt.Print but writes on the error writer and adds a // newline. It also logs the error. -func (fb *Feedback) Error(v ...interface{}) { - fmt.Fprintln(fb.err, v...) +func Error(v ...interface{}) { + fmt.Fprintln(stdErr, v...) logrus.Error(fmt.Sprint(v...)) } // printJSON is a convenient wrapper to provide feedback by printing the // desired output in a pretty JSON format. It adds a newline to the output. -func (fb *Feedback) printJSON(v interface{}) { +func printJSON(v interface{}) { var d []byte var err error - if fb.format == JSON { + if format == JSON { d, err = json.MarshalIndent(v, "", " ") - } else if fb.format == MinifiedJSON { + } else if format == MinifiedJSON { d, err = json.Marshal(v) } if err != nil { - fb.Errorf(tr("Error during JSON encoding of the output: %v"), err) + Errorf(tr("Error during JSON encoding of the output: %v"), err) } else { - fmt.Fprintf(fb.out, "%v\n", string(d)) + fmt.Fprintf(stdOut, "%v\n", string(d)) } } // printYAML is a convenient wrapper to provide feedback by printing the // desired output in YAML format. It adds a newline to the output. -func (fb *Feedback) printYAML(v interface{}) { +func printYAML(v interface{}) { d, err := yaml.Marshal(v) if err != nil { - fb.Errorf(tr("Error during YAML encoding of the output: %v"), err) + Errorf(tr("Error during YAML encoding of the output: %v"), err) return } - fmt.Fprintf(fb.out, "%v\n", string(d)) + fmt.Fprintf(stdOut, "%v\n", string(d)) } // PrintResult is a convenient wrapper to provide feedback for complex data, // where the contents can't be just serialized to JSON but requires more // structure. -func (fb *Feedback) PrintResult(res Result) { - switch fb.format { +func PrintResult(res Result) { + switch format { case JSON, MinifiedJSON: - fb.printJSON(res.Data()) + printJSON(res.Data()) case YAML: - fb.printYAML(res.Data()) + printYAML(res.Data()) case Text: - fb.Print(res.String()) + Print(res.String()) default: - panic(fmt.Sprintf("Invalid output format: %v", fb.format)) + panic("unknown output format") } } From 4d593ad07868a0d56b80bf97605246568e77da92 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 1 Dec 2022 19:17:00 +0100 Subject: [PATCH 04/45] Moved `cli/output` package into `cli/feedback` This is the better place where it belongs, and slighlty simplifies the golang API. --- cli/cli.go | 5 ----- cli/compile/compile.go | 5 ++--- cli/core/download.go | 3 +-- cli/core/install.go | 3 +-- cli/core/search.go | 3 +-- cli/core/uninstall.go | 3 +-- cli/core/update_index.go | 3 +-- cli/core/upgrade.go | 3 +-- cli/{output => feedback}/rpc_progress.go | 16 ++++------------ cli/instance/instance.go | 9 ++++----- cli/lib/download.go | 3 +-- cli/lib/install.go | 7 +++---- cli/lib/search.go | 3 +-- cli/lib/uninstall.go | 3 +-- cli/lib/update_index.go | 3 +-- cli/lib/upgrade.go | 5 ++--- 16 files changed, 25 insertions(+), 52 deletions(-) rename cli/{output => feedback}/rpc_progress.go (90%) diff --git a/cli/cli.go b/cli/cli.go index 4fc7c366da0..6c049be0780 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -37,7 +37,6 @@ import ( "github.com/arduino/arduino-cli/cli/lib" "github.com/arduino/arduino-cli/cli/monitor" "github.com/arduino/arduino-cli/cli/outdated" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/cli/sketch" "github.com/arduino/arduino-cli/cli/update" "github.com/arduino/arduino-cli/cli/updater" @@ -236,10 +235,6 @@ func preRun(cmd *cobra.Command, args []string) { // Prepare the Feedback system // - // normalize the format strings - outputFormat = strings.ToLower(outputFormat) - // configure the output package - output.OutputFormat = outputFormat // check the right output format was passed format, found := parseFormatString(outputFormat) if !found { diff --git a/cli/compile/compile.go b/cli/compile/compile.go index 73275348a99..55d19dc9caa 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -29,7 +29,6 @@ import ( "github.com/arduino/arduino-cli/cli/arguments" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/globals" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" @@ -229,7 +228,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { verboseCompile := configuration.Settings.GetString("logging.level") == "debug" var compileRes *rpc.CompileResponse var compileError error - if output.OutputFormat == "json" { + if feedback.GetFormat() == feedback.JSON { compileRes, compileError = compile.Compile(context.Background(), compileRequest, compileStdOut, compileStdErr, nil, verboseCompile) } else { compileRes, compileError = compile.Compile(context.Background(), compileRequest, os.Stdout, os.Stderr, nil, verboseCompile) @@ -265,7 +264,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { } var uploadError error - if output.OutputFormat == "json" { + if feedback.GetFormat() == feedback.JSON { // TODO: do not print upload output in json mode uploadStdOut := new(bytes.Buffer) uploadStdErr := new(bytes.Buffer) diff --git a/cli/core/download.go b/cli/core/download.go index 7b45a502313..f6415a96208 100644 --- a/cli/core/download.go +++ b/cli/core/download.go @@ -24,7 +24,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/core" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" @@ -66,7 +65,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { Architecture: platformRef.Architecture, Version: platformRef.Version, } - _, err := core.PlatformDownload(context.Background(), platformDownloadreq, output.ProgressBar()) + _, err := core.PlatformDownload(context.Background(), platformDownloadreq, feedback.ProgressBar()) if err != nil { feedback.Errorf(tr("Error downloading %[1]s: %[2]v"), args[i], err) os.Exit(errorcodes.ErrNetwork) diff --git a/cli/core/install.go b/cli/core/install.go index 776966729ed..0b23a3b1908 100644 --- a/cli/core/install.go +++ b/cli/core/install.go @@ -24,7 +24,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/core" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" @@ -77,7 +76,7 @@ func runInstallCommand(args []string, postInstallFlags arguments.PostInstallFlag SkipPostInstall: postInstallFlags.DetectSkipPostInstallValue(), NoOverwrite: noOverwrite, } - _, err := core.PlatformInstall(context.Background(), platformInstallRequest, output.ProgressBar(), output.TaskProgress()) + _, err := core.PlatformInstall(context.Background(), platformInstallRequest, feedback.ProgressBar(), feedback.TaskProgress()) if err != nil { feedback.Errorf(tr("Error during install: %v"), err) os.Exit(errorcodes.ErrGeneric) diff --git a/cli/core/search.go b/cli/core/search.go index 004302243ed..794143a8c19 100644 --- a/cli/core/search.go +++ b/cli/core/search.go @@ -28,7 +28,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/core" "github.com/arduino/arduino-cli/configuration" @@ -67,7 +66,7 @@ func runSearchCommand(cmd *cobra.Command, args []string) { } if indexesNeedUpdating(indexUpdateInterval) { - err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexRequest{Instance: inst}, output.ProgressBar()) + err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexRequest{Instance: inst}, feedback.ProgressBar()) if err != nil { os.Exit(errorcodes.ErrGeneric) } diff --git a/cli/core/uninstall.go b/cli/core/uninstall.go index c7ce20835f0..927edf919d2 100644 --- a/cli/core/uninstall.go +++ b/cli/core/uninstall.go @@ -24,7 +24,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/core" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" @@ -67,7 +66,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { Instance: inst, PlatformPackage: platformRef.PackageName, Architecture: platformRef.Architecture, - }, output.NewTaskProgressCB()) + }, feedback.NewTaskProgressCB()) if err != nil { feedback.Errorf(tr("Error during uninstall: %v"), err) os.Exit(errorcodes.ErrGeneric) diff --git a/cli/core/update_index.go b/cli/core/update_index.go index 4f3c4f89064..0f9ae8cf179 100644 --- a/cli/core/update_index.go +++ b/cli/core/update_index.go @@ -22,7 +22,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" @@ -49,7 +48,7 @@ func runUpdateIndexCommand(cmd *cobra.Command, args []string) { // UpdateIndex updates the index of platforms. func UpdateIndex(inst *rpc.Instance) { - err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexRequest{Instance: inst}, output.ProgressBar()) + err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexRequest{Instance: inst}, feedback.ProgressBar()) if err != nil { feedback.Error(err) os.Exit(errorcodes.ErrGeneric) diff --git a/cli/core/upgrade.go b/cli/core/upgrade.go index ecd0669395e..7f43aa4b785 100644 --- a/cli/core/upgrade.go +++ b/cli/core/upgrade.go @@ -26,7 +26,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/core" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" @@ -103,7 +102,7 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { SkipPostInstall: skipPostInstall, } - if _, err := core.PlatformUpgrade(context.Background(), r, output.ProgressBar(), output.TaskProgress()); err != nil { + if _, err := core.PlatformUpgrade(context.Background(), r, feedback.ProgressBar(), feedback.TaskProgress()); err != nil { if errors.Is(err, &arduino.PlatformAlreadyAtTheLatestVersionError{}) { feedback.Print(err.Error()) continue diff --git a/cli/output/rpc_progress.go b/cli/feedback/rpc_progress.go similarity index 90% rename from cli/output/rpc_progress.go rename to cli/feedback/rpc_progress.go index 880ab26fa56..a9283668197 100644 --- a/cli/output/rpc_progress.go +++ b/cli/feedback/rpc_progress.go @@ -13,28 +13,20 @@ // Arduino software without disclosing the source code of your own applications. // To purchase a commercial license, send an email to license@arduino.cc. -package output +package feedback import ( "fmt" "sync" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/i18n" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/cmaglie/pb" ) -var ( - // OutputFormat can be "text" or "json" - OutputFormat string - tr = i18n.Tr -) - // ProgressBar returns a DownloadProgressCB that prints a progress bar. // If JSON output format has been selected, the callback outputs nothing. func ProgressBar() rpc.DownloadProgressCB { - if OutputFormat != "json" { + if format != JSON { return NewDownloadProgressBarCB() } return func(curr *rpc.DownloadProgress) { @@ -45,7 +37,7 @@ func ProgressBar() rpc.DownloadProgressCB { // TaskProgress returns a TaskProgressCB that prints the task progress. // If JSON output format has been selected, the callback outputs nothing. func TaskProgress() rpc.TaskProgressCB { - if OutputFormat != "json" { + if format != JSON { return NewTaskProgressCB() } return func(curr *rpc.TaskProgress) { @@ -86,7 +78,7 @@ func NewDownloadProgressBarCB() func(*rpc.DownloadProgress) { if started { bar.FinishPrintOver(label + " " + msg) } else { - feedback.Print(label + " " + msg) + Print(label + " " + msg) } started = false } diff --git a/cli/instance/instance.go b/cli/instance/instance.go index 728032a1e91..9d66bd2c6a2 100644 --- a/cli/instance/instance.go +++ b/cli/instance/instance.go @@ -21,7 +21,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" @@ -81,8 +80,8 @@ func InitWithProfile(instance *rpc.Instance, profileName string, sketchPath *pat return nil } - downloadCallback := output.ProgressBar() - taskCallback := output.TaskProgress() + downloadCallback := feedback.ProgressBar() + taskCallback := feedback.TaskProgress() initReq := &rpc.InitRequest{Instance: instance} if sketchPath != nil { @@ -135,7 +134,7 @@ func FirstUpdate(instance *rpc.Instance) error { &rpc.UpdateLibrariesIndexRequest{ Instance: instance, }, - output.ProgressBar(), + feedback.ProgressBar(), ) if err != nil { return err @@ -151,7 +150,7 @@ func FirstUpdate(instance *rpc.Instance) error { Instance: instance, IgnoreCustomPackageIndexes: true, }, - output.ProgressBar()) + feedback.ProgressBar()) if err != nil { return err } diff --git a/cli/lib/download.go b/cli/lib/download.go index c2ad41638f5..920237d8676 100644 --- a/cli/lib/download.go +++ b/cli/lib/download.go @@ -24,7 +24,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/lib" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" @@ -63,7 +62,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { Name: library.Name, Version: library.Version, } - _, err := lib.LibraryDownload(context.Background(), libraryDownloadRequest, output.ProgressBar()) + _, err := lib.LibraryDownload(context.Background(), libraryDownloadRequest, feedback.ProgressBar()) if err != nil { feedback.Errorf(tr("Error downloading %[1]s: %[2]v"), library, err) os.Exit(errorcodes.ErrNetwork) diff --git a/cli/lib/install.go b/cli/lib/install.go index db039a7f7ec..807fae19494 100644 --- a/cli/lib/install.go +++ b/cli/lib/install.go @@ -26,7 +26,6 @@ import ( "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/lib" "github.com/arduino/arduino-cli/configuration" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" @@ -91,7 +90,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Instance: instance, Path: path, Overwrite: !noOverwrite, - }, output.TaskProgress()) + }, feedback.TaskProgress()) if err != nil { feedback.Errorf(tr("Error installing Zip Library: %v"), err) os.Exit(errorcodes.ErrGeneric) @@ -114,7 +113,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Instance: instance, Url: url, Overwrite: !noOverwrite, - }, output.TaskProgress()) + }, feedback.TaskProgress()) if err != nil { feedback.Errorf(tr("Error installing Git Library: %v"), err) os.Exit(errorcodes.ErrGeneric) @@ -137,7 +136,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { NoDeps: noDeps, NoOverwrite: noOverwrite, } - err := lib.LibraryInstall(context.Background(), libraryInstallRequest, output.ProgressBar(), output.TaskProgress()) + err := lib.LibraryInstall(context.Background(), libraryInstallRequest, feedback.ProgressBar(), feedback.TaskProgress()) if err != nil { feedback.Errorf(tr("Error installing %s: %v"), libRef.Name, err) os.Exit(errorcodes.ErrGeneric) diff --git a/cli/lib/search.go b/cli/lib/search.go index 294c3cf8112..6c75071a3a5 100644 --- a/cli/lib/search.go +++ b/cli/lib/search.go @@ -25,7 +25,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/lib" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" @@ -62,7 +61,7 @@ func runSearchCommand(args []string, namesOnly bool) { if err := commands.UpdateLibrariesIndex( context.Background(), &rpc.UpdateLibrariesIndexRequest{Instance: inst}, - output.ProgressBar(), + feedback.ProgressBar(), ); err != nil { feedback.Errorf(tr("Error updating library index: %v"), err) os.Exit(errorcodes.ErrGeneric) diff --git a/cli/lib/uninstall.go b/cli/lib/uninstall.go index 2f7c20ef3bd..b3e2124cef3 100644 --- a/cli/lib/uninstall.go +++ b/cli/lib/uninstall.go @@ -24,7 +24,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/lib" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" @@ -61,7 +60,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { Instance: instance, Name: library.Name, Version: library.Version, - }, output.TaskProgress()) + }, feedback.TaskProgress()) if err != nil { feedback.Errorf(tr("Error uninstalling %[1]s: %[2]v"), library, err) os.Exit(errorcodes.ErrGeneric) diff --git a/cli/lib/update_index.go b/cli/lib/update_index.go index ccd05cccec2..6775bd40165 100644 --- a/cli/lib/update_index.go +++ b/cli/lib/update_index.go @@ -22,7 +22,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" @@ -51,7 +50,7 @@ func runUpdateIndexCommand(cmd *cobra.Command, args []string) { func UpdateIndex(inst *rpc.Instance) { err := commands.UpdateLibrariesIndex(context.Background(), &rpc.UpdateLibrariesIndexRequest{ Instance: inst, - }, output.ProgressBar()) + }, feedback.ProgressBar()) if err != nil { feedback.Errorf(tr("Error updating library index: %v"), err) os.Exit(errorcodes.ErrGeneric) diff --git a/cli/lib/upgrade.go b/cli/lib/upgrade.go index 0e711816ed6..72631e2de8c 100644 --- a/cli/lib/upgrade.go +++ b/cli/lib/upgrade.go @@ -22,7 +22,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/lib" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" @@ -54,14 +53,14 @@ func Upgrade(instance *rpc.Instance, libraries []string) { var upgradeErr error if len(libraries) == 0 { req := &rpc.LibraryUpgradeAllRequest{Instance: instance} - upgradeErr = lib.LibraryUpgradeAll(req, output.ProgressBar(), output.TaskProgress()) + upgradeErr = lib.LibraryUpgradeAll(req, feedback.ProgressBar(), feedback.TaskProgress()) } else { for _, libName := range libraries { req := &rpc.LibraryUpgradeRequest{ Instance: instance, Name: libName, } - upgradeErr = lib.LibraryUpgrade(context.Background(), req, output.ProgressBar(), output.TaskProgress()) + upgradeErr = lib.LibraryUpgrade(context.Background(), req, feedback.ProgressBar(), feedback.TaskProgress()) if upgradeErr != nil { break } From 93c2d62fe3f5eb2d831bc22b2c251fe41a613ace Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 1 Dec 2022 19:26:18 +0100 Subject: [PATCH 05/45] Print progress bar and task progess only on interactive terminals --- cli/feedback/rpc_progress.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cli/feedback/rpc_progress.go b/cli/feedback/rpc_progress.go index a9283668197..6987fab90b0 100644 --- a/cli/feedback/rpc_progress.go +++ b/cli/feedback/rpc_progress.go @@ -24,24 +24,22 @@ import ( ) // ProgressBar returns a DownloadProgressCB that prints a progress bar. -// If JSON output format has been selected, the callback outputs nothing. func ProgressBar() rpc.DownloadProgressCB { - if format != JSON { + if format == Text { return NewDownloadProgressBarCB() } return func(curr *rpc.DownloadProgress) { - // XXX: Output progress in JSON? + // Non interactive output, no progress bar } } // TaskProgress returns a TaskProgressCB that prints the task progress. -// If JSON output format has been selected, the callback outputs nothing. func TaskProgress() rpc.TaskProgressCB { - if format != JSON { + if format == Text { return NewTaskProgressCB() } return func(curr *rpc.TaskProgress) { - // XXX: Output progress in JSON? + // Non interactive output, no task progess } } From 766da7fbfd6efc1a5430afc0ac3fc7be3ebb1f08 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 1 Dec 2022 19:27:21 +0100 Subject: [PATCH 06/45] Use feedback functions to output task progress --- cli/feedback/rpc_progress.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/cli/feedback/rpc_progress.go b/cli/feedback/rpc_progress.go index 6987fab90b0..c9a413a4fdb 100644 --- a/cli/feedback/rpc_progress.go +++ b/cli/feedback/rpc_progress.go @@ -16,7 +16,6 @@ package feedback import ( - "fmt" "sync" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" @@ -86,23 +85,16 @@ func NewDownloadProgressBarCB() func(*rpc.DownloadProgress) { // NewTaskProgressCB returns a commands.TaskProgressCB progress listener // that outputs to terminal func NewTaskProgressCB() func(curr *rpc.TaskProgress) { - var name string return func(curr *rpc.TaskProgress) { - // fmt.Printf(">>> %v\n", curr) msg := curr.GetMessage() - if curr.GetName() != "" { - name = curr.GetName() - if msg == "" { - msg = name - } + if msg == "" { + msg = curr.GetName() } if msg != "" { - fmt.Print(msg) - if curr.GetCompleted() { - fmt.Println() - } else { - fmt.Println("...") + if !curr.GetCompleted() { + msg += "..." } + Print(msg) } } } From 344669e7dd606f6dd9eca19943b7f6b815b03b51 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sun, 4 Dec 2022 16:44:50 +0100 Subject: [PATCH 07/45] User-input functions are now moved into `feedback` package --- cli/arguments/user_fields.go | 25 ++++-------------- cli/compile/compile.go | 7 ++++- cli/feedback/terminal.go | 50 ++++++++++++++++++++++++++++++++++++ cli/upload/upload.go | 7 ++++- 4 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 cli/feedback/terminal.go diff --git a/cli/arguments/user_fields.go b/cli/arguments/user_fields.go index edef603e809..d1287c0509f 100644 --- a/cli/arguments/user_fields.go +++ b/cli/arguments/user_fields.go @@ -16,36 +16,21 @@ package arguments import ( - "bufio" - "fmt" - "os" - "github.com/arduino/arduino-cli/cli/feedback" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" - "golang.org/x/term" ) // AskForUserFields prompts the user to input the provided user fields. // If there is an error reading input it panics. -func AskForUserFields(userFields []*rpc.UserField) map[string]string { - writer := feedback.OutputWriter() +func AskForUserFields(userFields []*rpc.UserField) (map[string]string, error) { fields := map[string]string{} - reader := bufio.NewReader(os.Stdin) for _, f := range userFields { - fmt.Fprintf(writer, "%s: ", f.Label) - var value []byte - var err error - if f.Secret { - value, err = term.ReadPassword(int(os.Stdin.Fd())) - } else { - value, err = reader.ReadBytes('\n') - } + value, err := feedback.InputUserField(f.Label, f.Secret) if err != nil { - panic(err) + return nil, err } - fields[f.Name] = string(value) + fields[f.Name] = value } - fmt.Fprintln(writer, "") - return fields + return fields, nil } diff --git a/cli/compile/compile.go b/cli/compile/compile.go index 55d19dc9caa..2fc40fc620c 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -248,7 +248,12 @@ func runCompileCommand(cmd *cobra.Command, args []string) { fields := map[string]string{} if len(userFieldRes.UserFields) > 0 { feedback.Print(tr("Uploading to specified board using %s protocol requires the following info:", port.Protocol)) - fields = arguments.AskForUserFields(userFieldRes.UserFields) + if f, err := arguments.AskForUserFields(userFieldRes.UserFields); err != nil { + feedback.Error(err) + os.Exit(errorcodes.ErrBadArgument) + } else { + fields = f + } } uploadRequest := &rpc.UploadRequest{ diff --git a/cli/feedback/terminal.go b/cli/feedback/terminal.go new file mode 100644 index 00000000000..cf614dcd8d6 --- /dev/null +++ b/cli/feedback/terminal.go @@ -0,0 +1,50 @@ +// This file is part of arduino-cli. +// +// Copyright 2022 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 feedback + +import ( + "bufio" + "errors" + "fmt" + "os" + + "golang.org/x/term" +) + +// InputUserField prompts the user to input the provided user field. +func InputUserField(prompt string, secret bool) (string, error) { + if format != Text { + return "", errors.New(tr("user input not supported for the selected output format")) + } + if !term.IsTerminal(int(os.Stdin.Fd())) { + return "", errors.New(tr("user input not supported in non interactive mode")) + } + + fmt.Fprintf(stdOut, "%s: ", prompt) + var value []byte + var err error + if secret { + value, err = term.ReadPassword(int(os.Stdin.Fd())) + } else { + value, err = bufio.NewReader(os.Stdin).ReadBytes('\n') + } + if err != nil { + panic(err) + } + fmt.Fprintln(stdOut, "") + + return string(value), nil +} diff --git a/cli/upload/upload.go b/cli/upload/upload.go index f9713a1037a..c247c7971e4 100644 --- a/cli/upload/upload.go +++ b/cli/upload/upload.go @@ -141,7 +141,12 @@ func runUploadCommand(command *cobra.Command, args []string) { fields := map[string]string{} if len(userFieldRes.UserFields) > 0 { feedback.Print(tr("Uploading to specified board using %s protocol requires the following info:", port.Protocol)) - fields = arguments.AskForUserFields(userFieldRes.UserFields) + if f, err := arguments.AskForUserFields(userFieldRes.UserFields); err != nil { + feedback.Errorf("%s: %s", tr("Error getting user input"), err) + os.Exit(errorcodes.ErrGeneric) + } else { + fields = f + } } if sketchPath != nil { From c850c16519efae5a4676aa407a0e9f0a7915b2a1 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sun, 4 Dec 2022 17:06:02 +0100 Subject: [PATCH 08/45] Fix user-input function - Final "\n" is automatically printed when entering non-passwords (no need to do a Println() - The final "\n" is included in the result of ReadBytes() so it will be removed. --- cli/feedback/terminal.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cli/feedback/terminal.go b/cli/feedback/terminal.go index cf614dcd8d6..e40b791db51 100644 --- a/cli/feedback/terminal.go +++ b/cli/feedback/terminal.go @@ -38,13 +38,16 @@ func InputUserField(prompt string, secret bool) (string, error) { var err error if secret { value, err = term.ReadPassword(int(os.Stdin.Fd())) + fmt.Fprintln(stdOut) } else { value, err = bufio.NewReader(os.Stdin).ReadBytes('\n') + if l := len(value); l > 0 { + value = value[:l-1] + } } if err != nil { panic(err) } - fmt.Fprintln(stdOut, "") return string(value), nil } From 53c80b003ef67b6fd5acbe25ba0fb8832e615e63 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sun, 4 Dec 2022 17:08:07 +0100 Subject: [PATCH 09/45] Added cmd to test feedback functions --- cli/cli.go | 1 + cli/feedback/feedback_cmd.go | 59 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 cli/feedback/feedback_cmd.go diff --git a/cli/cli.go b/cli/cli.go index 6c049be0780..a47c7cf8f71 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -102,6 +102,7 @@ func createCliCommandTree(cmd *cobra.Command) { cmd.AddCommand(debug.NewCommand()) cmd.AddCommand(burnbootloader.NewCommand()) cmd.AddCommand(version.NewCommand()) + cmd.AddCommand(feedback.NewCommand()) cmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, tr("Print the logs on the standard output.")) validLogLevels := []string{"trace", "debug", "info", "warn", "error", "fatal", "panic"} diff --git a/cli/feedback/feedback_cmd.go b/cli/feedback/feedback_cmd.go new file mode 100644 index 00000000000..e298134e9a9 --- /dev/null +++ b/cli/feedback/feedback_cmd.go @@ -0,0 +1,59 @@ +// 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 feedback + +import ( + "os" + + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/spf13/cobra" +) + +// NewCommand creates a new `feedback` command +func NewCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "feedback", + Short: "Test the feedback functions of the arduino CLI.", + Long: "This command is for testing purposes only, it is not intended for use by end users.", + Args: cobra.NoArgs, + Hidden: true, + } + cmd.AddCommand(&cobra.Command{ + Use: "input", + Short: "Test the input functions", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + user, err := InputUserField("User name", false) + if err != nil { + Errorf("Error reading input: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + pass, err := InputUserField("Password", true) + if err != nil { + Errorf("Error reading input: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + nick, err := InputUserField("Nickname", false) + if err != nil { + Errorf("Error reading input: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + Print("Hello " + user + " (a.k.a " + nick + ")!") + Print("Your password is " + pass + "!") + }, + }) + return cmd +} From 94cb4b57ddf5e9e7d928f399e35876a96dcd8895 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sun, 4 Dec 2022 17:11:40 +0100 Subject: [PATCH 10/45] Better error message --- cli/cli.go | 13 +------------ cli/feedback/feedback.go | 23 +++++++++++++++++++++++ cli/feedback/terminal.go | 2 +- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/cli/cli.go b/cli/cli.go index a47c7cf8f71..13bf2a8f6c0 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -143,17 +143,6 @@ func toLogLevel(s string) (t logrus.Level, found bool) { return } -func parseFormatString(arg string) (feedback.OutputFormat, bool) { - f, found := map[string]feedback.OutputFormat{ - "json": feedback.JSON, - "jsonmini": feedback.MinifiedJSON, - "text": feedback.Text, - "yaml": feedback.YAML, - }[strings.ToLower(arg)] - - return f, found -} - func preRun(cmd *cobra.Command, args []string) { configFile := configuration.Settings.ConfigFileUsed() @@ -237,7 +226,7 @@ func preRun(cmd *cobra.Command, args []string) { // // check the right output format was passed - format, found := parseFormatString(outputFormat) + format, found := feedback.ParseOutputFormat(outputFormat) if !found { feedback.Errorf(tr("Invalid output format: %s"), outputFormat) os.Exit(errorcodes.ErrBadCall) diff --git a/cli/feedback/feedback.go b/cli/feedback/feedback.go index 09791e7dbbd..84629414c52 100644 --- a/cli/feedback/feedback.go +++ b/cli/feedback/feedback.go @@ -44,6 +44,29 @@ const ( YAML ) +var formats map[string]OutputFormat = map[string]OutputFormat{ + "json": JSON, + "jsonmini": MinifiedJSON, + "yaml": YAML, + "text": Text, +} + +func (f OutputFormat) String() string { + for res, format := range formats { + if format == f { + return res + } + } + panic("unknown output format") +} + +// ParseOutputFormat parses a string and returns the corresponding OutputFormat. +// The boolean returned is true if the string was a valid OutputFormat. +func ParseOutputFormat(in string) (OutputFormat, bool) { + format, found := formats[in] + return format, found +} + var ( stdOut io.Writer = os.Stdout stdErr io.Writer = os.Stderr diff --git a/cli/feedback/terminal.go b/cli/feedback/terminal.go index e40b791db51..0bba6a55cc4 100644 --- a/cli/feedback/terminal.go +++ b/cli/feedback/terminal.go @@ -27,7 +27,7 @@ import ( // InputUserField prompts the user to input the provided user field. func InputUserField(prompt string, secret bool) (string, error) { if format != Text { - return "", errors.New(tr("user input not supported for the selected output format")) + return "", errors.New(tr("user input not supported for the '%s' output format", format)) } if !term.IsTerminal(int(os.Stdin.Fd())) { return "", errors.New(tr("user input not supported in non interactive mode")) From 5c41e74410f5af00ec799bc67844c9cce114b81a Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sun, 4 Dec 2022 17:14:47 +0100 Subject: [PATCH 11/45] Removed unprotected print --- cli/cli.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/cli.go b/cli/cli.go index 13bf2a8f6c0..817f30cf9f7 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -201,7 +201,7 @@ func preRun(cmd *cobra.Command, args []string) { if logFile != "" { file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { - fmt.Println(tr("Unable to open file for logging: %s", logFile)) + feedback.Errorf(tr("Unable to open file for logging: %s", logFile)) os.Exit(errorcodes.ErrBadCall) } From 07f4bd032549d6081f4e81b22d18b289888d73cf Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 5 Dec 2022 10:32:23 +0100 Subject: [PATCH 12/45] Removed useless response from Upload and UploadWithProgrammer --- cli/compile/compile.go | 4 ++-- cli/upload/upload.go | 5 +++-- commands/daemon/daemon.go | 8 ++++---- commands/upload/upload.go | 18 +++++++++--------- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/cli/compile/compile.go b/cli/compile/compile.go index 2fc40fc620c..646afc6695c 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -273,9 +273,9 @@ func runCompileCommand(cmd *cobra.Command, args []string) { // TODO: do not print upload output in json mode uploadStdOut := new(bytes.Buffer) uploadStdErr := new(bytes.Buffer) - _, uploadError = upload.Upload(context.Background(), uploadRequest, uploadStdOut, uploadStdErr) + uploadError = upload.Upload(context.Background(), uploadRequest, uploadStdOut, uploadStdErr) } else { - _, uploadError = upload.Upload(context.Background(), uploadRequest, os.Stdout, os.Stderr) + uploadError = upload.Upload(context.Background(), uploadRequest, os.Stdout, os.Stderr) } if uploadError != nil { feedback.Errorf(tr("Error during Upload: %v"), uploadError) diff --git a/cli/upload/upload.go b/cli/upload/upload.go index c247c7971e4..3d3718d7288 100644 --- a/cli/upload/upload.go +++ b/cli/upload/upload.go @@ -153,7 +153,7 @@ func runUploadCommand(command *cobra.Command, args []string) { path = sketchPath.String() } - if _, err := upload.Upload(context.Background(), &rpc.UploadRequest{ + req := &rpc.UploadRequest{ Instance: instance, Fqbn: fqbn, SketchPath: path, @@ -165,7 +165,8 @@ func runUploadCommand(command *cobra.Command, args []string) { Programmer: programmer.String(), DryRun: dryRun, UserFields: fields, - }, os.Stdout, os.Stderr); err != nil { + } + if err := upload.Upload(context.Background(), req, os.Stdout, os.Stderr); err != nil { feedback.Errorf(tr("Error during Upload: %v"), err) os.Exit(errorcodes.ErrGeneric) } diff --git a/commands/daemon/daemon.go b/commands/daemon/daemon.go index 534fc29a2d3..fc468c8f072 100644 --- a/commands/daemon/daemon.go +++ b/commands/daemon/daemon.go @@ -292,26 +292,26 @@ func (s *ArduinoCoreServerImpl) PlatformList(ctx context.Context, req *rpc.Platf func (s *ArduinoCoreServerImpl) Upload(req *rpc.UploadRequest, stream rpc.ArduinoCoreService_UploadServer) error { outStream := feedStreamTo(func(data []byte) { stream.Send(&rpc.UploadResponse{OutStream: data}) }) errStream := feedStreamTo(func(data []byte) { stream.Send(&rpc.UploadResponse{ErrStream: data}) }) - resp, err := upload.Upload(stream.Context(), req, outStream, errStream) + err := upload.Upload(stream.Context(), req, outStream, errStream) outStream.Close() errStream.Close() if err != nil { return convertErrorToRPCStatus(err) } - return stream.Send(resp) + return nil } // UploadUsingProgrammer FIXMEDOC func (s *ArduinoCoreServerImpl) UploadUsingProgrammer(req *rpc.UploadUsingProgrammerRequest, stream rpc.ArduinoCoreService_UploadUsingProgrammerServer) error { outStream := feedStreamTo(func(data []byte) { stream.Send(&rpc.UploadUsingProgrammerResponse{OutStream: data}) }) errStream := feedStreamTo(func(data []byte) { stream.Send(&rpc.UploadUsingProgrammerResponse{ErrStream: data}) }) - resp, err := upload.UsingProgrammer(stream.Context(), req, outStream, errStream) + err := upload.UsingProgrammer(stream.Context(), req, outStream, errStream) outStream.Close() errStream.Close() if err != nil { return convertErrorToRPCStatus(err) } - return stream.Send(resp) + return nil } // SupportedUserFields FIXMEDOC diff --git a/commands/upload/upload.go b/commands/upload/upload.go index b026e45ff2d..cfa0d72d4d7 100644 --- a/commands/upload/upload.go +++ b/commands/upload/upload.go @@ -123,7 +123,7 @@ func getUserFields(toolID string, platformRelease *cores.PlatformRelease) []*rpc } // Upload FIXMEDOC -func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, errStream io.Writer) (*rpc.UploadResponse, error) { +func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, errStream io.Writer) error { logrus.Tracef("Upload %s on %s started", req.GetSketchPath(), req.GetFqbn()) // TODO: make a generic function to extract sketch from request @@ -131,12 +131,12 @@ func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, er sketchPath := paths.New(req.GetSketchPath()) sk, err := sketch.New(sketchPath) if err != nil && req.GetImportDir() == "" && req.GetImportFile() == "" { - return nil, &arduino.CantOpenSketchError{Cause: err} + return &arduino.CantOpenSketchError{Cause: err} } pme, release := commands.GetPackageManagerExplorer(req) if pme == nil { - return nil, &arduino.InvalidInstanceError{} + return &arduino.InvalidInstanceError{} } defer release() @@ -156,20 +156,20 @@ func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, er req.GetDryRun(), req.GetUserFields(), ); err != nil { - return nil, err + return err } - return &rpc.UploadResponse{}, nil + return nil } // UsingProgrammer FIXMEDOC -func UsingProgrammer(ctx context.Context, req *rpc.UploadUsingProgrammerRequest, outStream io.Writer, errStream io.Writer) (*rpc.UploadUsingProgrammerResponse, error) { +func UsingProgrammer(ctx context.Context, req *rpc.UploadUsingProgrammerRequest, outStream io.Writer, errStream io.Writer) error { logrus.Tracef("Upload using programmer %s on %s started", req.GetSketchPath(), req.GetFqbn()) if req.GetProgrammer() == "" { - return nil, &arduino.MissingProgrammerError{} + return &arduino.MissingProgrammerError{} } - _, err := Upload(ctx, &rpc.UploadRequest{ + err := Upload(ctx, &rpc.UploadRequest{ Instance: req.GetInstance(), SketchPath: req.GetSketchPath(), ImportFile: req.GetImportFile(), @@ -181,7 +181,7 @@ func UsingProgrammer(ctx context.Context, req *rpc.UploadUsingProgrammerRequest, Verify: req.GetVerify(), UserFields: req.GetUserFields(), }, outStream, errStream) - return &rpc.UploadUsingProgrammerResponse{}, err + return err } func runProgramAction(pme *packagemanager.Explorer, From 36817e7e1e8bdda49df6ca5fff6bd3babf8f4345 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 5 Dec 2022 17:46:23 +0100 Subject: [PATCH 13/45] VersionInfo now implements feedback.Result interface --- cli/version/version.go | 4 ++-- version/version.go | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cli/version/version.go b/cli/version/version.go index 52a479ae6fa..384d6d41d8e 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -49,7 +49,7 @@ func runVersionCommand(cmd *cobra.Command, args []string) { if strings.Contains(globals.VersionInfo.VersionString, "git-snapshot") || strings.Contains(globals.VersionInfo.VersionString, "nightly") { // We're using a development version, no need to check if there's a // new release available - feedback.Print(globals.VersionInfo) + feedback.PrintResult(globals.VersionInfo) return } @@ -66,7 +66,7 @@ func runVersionCommand(cmd *cobra.Command, args []string) { versionInfo.LatestVersion = latestVersion.String() } - feedback.Print(versionInfo) + feedback.PrintResult(versionInfo) if feedback.GetFormat() == feedback.Text && latestVersion != nil { updater.NotifyNewVersionIsAvailable(latestVersion.String()) diff --git a/version/version.go b/version/version.go index a1e233d108a..8302740782f 100644 --- a/version/version.go +++ b/version/version.go @@ -53,6 +53,11 @@ func (i *Info) String() string { return tr("%[1]s %[2]s Version: %[3]s Commit: %[4]s Date: %[5]s", i.Application, i.Status, i.VersionString, i.Commit, i.Date) } +// Data implements feedback.Result interface +func (i *Info) Data() interface{} { + return i +} + //nolint:gochecknoinits func init() { if versionString == "" { From 8d6b33d93627f21805a26006fd8d42ea5fc030a6 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 10:47:14 +0100 Subject: [PATCH 14/45] Added `feedback` support for direct streaming When the Text format is selected the output is sent straigh to the output stream, otherwise it is buffered and returned as a `feedback.Result` to be used at the end of the job. --- cli/feedback/feedback.go | 128 +++++++++++++++++++--------------- cli/feedback/feedback_test.go | 123 ++++++++++++++++++++++++++++++++ cli/feedback/stdio.go | 68 ++++++++++++++++++ 3 files changed, 261 insertions(+), 58 deletions(-) create mode 100644 cli/feedback/feedback_test.go create mode 100644 cli/feedback/stdio.go diff --git a/cli/feedback/feedback.go b/cli/feedback/feedback.go index 84629414c52..5daaf4ed304 100644 --- a/cli/feedback/feedback.go +++ b/cli/feedback/feedback.go @@ -18,6 +18,7 @@ package feedback import ( + "bytes" "encoding/json" "errors" "fmt" @@ -68,11 +69,32 @@ func ParseOutputFormat(in string) (OutputFormat, bool) { } var ( - stdOut io.Writer = os.Stdout - stdErr io.Writer = os.Stderr - format OutputFormat = Text + stdOut io.Writer + stdErr io.Writer + feedbackOut io.Writer + feedbackErr io.Writer + bufferOut *bytes.Buffer + bufferErr *bytes.Buffer + format OutputFormat + formatSelected bool ) +func init() { + reset() +} + +// reset resets the feedback package to its initial state, useful for unit testing +func reset() { + stdOut = os.Stdout + stdErr = os.Stderr + feedbackOut = os.Stdout + feedbackErr = os.Stderr + bufferOut = &bytes.Buffer{} + bufferErr = &bytes.Buffer{} + format = Text + formatSelected = false +} + // Result is anything more complex than a sentence that needs to be printed // for the user. type Result interface { @@ -84,17 +106,35 @@ var tr = i18n.Tr // SetOut can be used to change the out writer at runtime func SetOut(out io.Writer) { + if formatSelected { + panic("output format already selected") + } stdOut = out } // SetErr can be used to change the err writer at runtime func SetErr(err io.Writer) { + if formatSelected { + panic("output format already selected") + } stdErr = err } // SetFormat can be used to change the output format at runtime func SetFormat(f OutputFormat) { + if formatSelected { + panic("output format already selected") + } format = f + formatSelected = true + + if format == Text { + feedbackOut = stdOut + feedbackErr = stdErr + } else { + feedbackOut = bufferOut + feedbackErr = bufferErr + } } // GetFormat returns the output format currently set @@ -102,35 +142,14 @@ func GetFormat() OutputFormat { return format } -// OutputWriter returns the underlying io.Writer to be used when the Print* -// api is not enough -func OutputWriter() io.Writer { - return stdOut -} - -// ErrorWriter is the same as OutputWriter but exposes the underlying error -// writer. -func ErrorWriter() io.Writer { - return stdErr -} - // Printf behaves like fmt.Printf but writes on the out writer and adds a newline. func Printf(format string, v ...interface{}) { Print(fmt.Sprintf(format, v...)) } // Print behaves like fmt.Print but writes on the out writer and adds a newline. -func Print(v interface{}) { - switch format { - case JSON, MinifiedJSON: - printJSON(v) - case YAML: - printYAML(v) - case Text: - fmt.Fprintln(stdOut, v) - default: - panic("unknown output format") - } +func Print(v string) { + fmt.Fprintln(feedbackOut, v) } // Errorf behaves like fmt.Printf but writes on the error writer and adds a @@ -156,46 +175,39 @@ func Error(v ...interface{}) { logrus.Error(fmt.Sprint(v...)) } -// printJSON is a convenient wrapper to provide feedback by printing the -// desired output in a pretty JSON format. It adds a newline to the output. -func printJSON(v interface{}) { - var d []byte - var err error - if format == JSON { - d, err = json.MarshalIndent(v, "", " ") - } else if format == MinifiedJSON { - d, err = json.Marshal(v) - } - if err != nil { - Errorf(tr("Error during JSON encoding of the output: %v"), err) - } else { - fmt.Fprintf(stdOut, "%v\n", string(d)) - } -} - -// printYAML is a convenient wrapper to provide feedback by printing the -// desired output in YAML format. It adds a newline to the output. -func printYAML(v interface{}) { - d, err := yaml.Marshal(v) - if err != nil { - Errorf(tr("Error during YAML encoding of the output: %v"), err) - return - } - fmt.Fprintf(stdOut, "%v\n", string(d)) -} - // PrintResult is a convenient wrapper to provide feedback for complex data, // where the contents can't be just serialized to JSON but requires more // structure. func PrintResult(res Result) { + var data string switch format { - case JSON, MinifiedJSON: - printJSON(res.Data()) + case JSON: + d, err := json.MarshalIndent(res.Data(), "", " ") + if err != nil { + Errorf("Error during JSON encoding of the output: %v", err) + return + } + data = string(d) + case MinifiedJSON: + d, err := json.Marshal(res.Data()) + if err != nil { + Errorf("Error during JSON encoding of the output: %v", err) + return + } + data = string(d) case YAML: - printYAML(res.Data()) + d, err := yaml.Marshal(res.Data()) + if err != nil { + Errorf("Error during YAML encoding of the output: %v", err) + return + } + data = string(d) case Text: - Print(res.String()) + data = res.String() default: panic("unknown output format") } + if data != "" { + fmt.Fprintln(stdOut, data) + } } diff --git a/cli/feedback/feedback_test.go b/cli/feedback/feedback_test.go new file mode 100644 index 00000000000..862afb95b13 --- /dev/null +++ b/cli/feedback/feedback_test.go @@ -0,0 +1,123 @@ +// 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 feedback + +import ( + "bytes" + "encoding/json" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestOutputSelection(t *testing.T) { + reset() + + myErr := new(bytes.Buffer) + myOut := new(bytes.Buffer) + SetOut(myOut) + SetErr(myErr) + SetFormat(Text) + + // Could not change output stream after format has been set + require.Panics(t, func() { SetOut(nil) }) + require.Panics(t, func() { SetErr(nil) }) + + // Coule not change output format twice + require.Panics(t, func() { SetFormat(JSON) }) + + Print("Hello") + require.Equal(t, myOut.String(), "Hello\n") +} + +func TestJSONOutputStream(t *testing.T) { + reset() + + require.Panics(t, func() { OutputStreams() }) + + SetFormat(JSON) + stdout, stderr, res := OutputStreams() + fmt.Fprint(stdout, "Hello") + fmt.Fprint(stderr, "Hello ERR") + + d, err := json.Marshal(res()) + require.NoError(t, err) + require.JSONEq(t, `{"stdout":"Hello","stderr":"Hello ERR"}`, string(d)) + + stdout.Write([]byte{0xc2, 'A'}) // Invaid UTF-8 + + d, err = json.Marshal(res()) + require.NoError(t, err) + require.JSONEq(t, string(d), `{"stdout":"Hello\ufffdA","stderr":"Hello ERR"}`) +} + +func TestJsonOutputOnCustomStreams(t *testing.T) { + reset() + + myErr := new(bytes.Buffer) + myOut := new(bytes.Buffer) + SetOut(myOut) + SetErr(myErr) + SetFormat(JSON) + + // Could not change output stream after format has been set + require.Panics(t, func() { SetOut(nil) }) + require.Panics(t, func() { SetErr(nil) }) + // Could not change output format twice + require.Panics(t, func() { SetFormat(JSON) }) + + Print("Hello") // Output interactive data + + require.Equal(t, "", myOut.String()) + require.Equal(t, "", myErr.String()) + require.Equal(t, "Hello\n", bufferOut.String()) + + PrintResult(&testResult{Success: true}) + + require.JSONEq(t, myOut.String(), `{ "success": true }`) + require.Equal(t, myErr.String(), "") + myOut.Reset() + + _, _, res := OutputStreams() + PrintResult(&testResult{Success: false, Output: res()}) + + require.JSONEq(t, ` +{ + "success": false, + "output": { + "stdout": "Hello\n", + "stderr": "" + } +}`, myOut.String()) + require.Equal(t, myErr.String(), "") +} + +type testResult struct { + Success bool `json:"success"` + Output *OutputStreamsResult `json:"output,omitempty"` +} + +func (r *testResult) Data() interface{} { + return r +} + +func (r *testResult) String() string { + if r.Success { + return "Success" + } + return "Failure" +} diff --git a/cli/feedback/stdio.go b/cli/feedback/stdio.go new file mode 100644 index 00000000000..39a85fe058b --- /dev/null +++ b/cli/feedback/stdio.go @@ -0,0 +1,68 @@ +// 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 feedback + +import ( + "io" +) + +// OutputStreams returns the underlying io.Writer to directly stream to +// stdout and stderr. +// If the selected output format is not Text, the returned writers will +// accumulate the output until command execution is completed. +// This function returns also a callback that must be called when the +// command execution is completed, it will return a *OutputStreamsResult +// object that can be used as a Result or to retrieve the output to embed +// it in another object. +func OutputStreams() (io.Writer, io.Writer, func() *OutputStreamsResult) { + if !formatSelected { + panic("output format not yet selected") + } + if format == Text { + return stdOut, stdErr, getOutputStreamResult + } + return bufferOut, bufferErr, getOutputStreamResult +} + +func getOutputStreamResult() *OutputStreamsResult { + return &OutputStreamsResult{ + Stdout: bufferOut.String(), + Stderr: bufferErr.String(), + } +} + +// OutputStreamsResult contains the accumulated stdout and stderr output +// when the selected output format is not Text. +type OutputStreamsResult struct { + Stdout string `json:"stdout"` + Stderr string `json:"stderr"` +} + +// Data returns the result object itself, it is used to implement the Result interface. +func (r *OutputStreamsResult) Data() interface{} { + // In case of non-Text output format, the output is accumulared so retrun the buffer as a Result object + return r +} + +func (r *OutputStreamsResult) String() string { + // In case of Text output format, the output is streamed to stdout and stderr directly, no need to print anything + return "" +} + +// Empty returns true if both Stdout and Stderr are empty. +func (r *OutputStreamsResult) Empty() bool { + return r.Stdout == "" && r.Stderr == "" +} From 5d1fef187a35ef1b34e3da9306c523a78b2652fb Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 10:49:22 +0100 Subject: [PATCH 15/45] Replace direct use of os.Stdout/Stderr in Upload command --- cli/upload/upload.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cli/upload/upload.go b/cli/upload/upload.go index 3d3718d7288..92c2b083e82 100644 --- a/cli/upload/upload.go +++ b/cli/upload/upload.go @@ -153,6 +153,7 @@ func runUploadCommand(command *cobra.Command, args []string) { path = sketchPath.String() } + stdOut, stdErr, stdIOResult := feedback.OutputStreams() req := &rpc.UploadRequest{ Instance: instance, Fqbn: fqbn, @@ -166,8 +167,9 @@ func runUploadCommand(command *cobra.Command, args []string) { DryRun: dryRun, UserFields: fields, } - if err := upload.Upload(context.Background(), req, os.Stdout, os.Stderr); err != nil { + if err := upload.Upload(context.Background(), req, stdOut, stdErr); err != nil { feedback.Errorf(tr("Error during Upload: %v"), err) os.Exit(errorcodes.ErrGeneric) } + feedback.PrintResult(stdIOResult()) } From 017258ca9429dabfbd83c13d93a27463db0dc866 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 15:36:42 +0100 Subject: [PATCH 16/45] Implemented feedback.Fatal and FatalError These functions outputs the error (also in machine-encoded if user choose to do so) and at the same time exits with os.Exit(). This API is much more readable and provides a better meaning to the CLI commands implementation. --- cli/arguments/arguments.go | 12 +++--- cli/arguments/fqbn.go | 10 ++--- cli/arguments/port.go | 10 ++--- cli/arguments/sketch.go | 8 +--- cli/board/attach.go | 6 +-- cli/board/details.go | 3 +- cli/board/list.go | 3 +- cli/board/listall.go | 3 +- cli/board/search.go | 3 +- cli/burnbootloader/burnbootloader.go | 6 +-- cli/cache/clean.go | 3 +- cli/cli.go | 15 +++---- cli/compile/compile.go | 34 ++++++--------- cli/completion/completion.go | 3 +- cli/config/add.go | 7 ++- cli/config/delete.go | 6 +-- cli/config/dump.go | 5 +-- cli/config/init.go | 15 +++---- cli/config/remove.go | 7 ++- cli/config/set.go | 9 ++-- cli/config/validate.go | 4 +- cli/core/download.go | 6 +-- cli/core/install.go | 6 +-- cli/core/list.go | 3 +- cli/core/search.go | 9 ++-- cli/core/uninstall.go | 9 ++-- cli/core/update_index.go | 3 +- cli/core/upgrade.go | 9 ++-- cli/daemon/daemon.go | 20 +++------ cli/debug/debug.go | 6 +-- cli/feedback/feedback.go | 43 ++++++++++++++++--- cli/feedback/feedback_cmd.go | 11 ++--- cli/instance/instance.go | 10 ++--- cli/lib/check_deps.go | 5 +-- cli/lib/download.go | 6 +-- cli/lib/examples.go | 3 +- cli/lib/install.go | 18 +++----- cli/lib/list.go | 3 +- cli/lib/search.go | 9 ++-- cli/lib/uninstall.go | 6 +-- cli/lib/update_index.go | 3 +- cli/lib/upgrade.go | 4 +- cli/monitor/monitor.go | 18 +++----- cli/sketch/archive.go | 3 +- cli/sketch/new.go | 6 +-- cli/upload/upload.go | 19 ++++---- cli/version/version.go | 4 +- .../integrationtest/compile_1/compile_test.go | 2 +- .../integrationtest/config/config_test.go | 2 +- 49 files changed, 172 insertions(+), 246 deletions(-) diff --git a/cli/arguments/arguments.go b/cli/arguments/arguments.go index 1b9dfe92b3c..9e028670814 100644 --- a/cli/arguments/arguments.go +++ b/cli/arguments/arguments.go @@ -16,7 +16,6 @@ package arguments import ( - "os" "strings" "github.com/arduino/arduino-cli/cli/errorcodes" @@ -34,8 +33,9 @@ func CheckFlagsConflicts(command *cobra.Command, flagNames ...string) { return } } - feedback.Errorf(tr("Can't use %s flags at the same time.", "--"+strings.Join(flagNames, " "+tr("and")+" --"))) - os.Exit(errorcodes.ErrBadArgument) + flags := "--" + strings.Join(flagNames, ", --") + msg := tr("Can't use the following flags together: %s", flags) + feedback.Fatal(msg, errorcodes.ErrBadArgument) } // CheckFlagsMandatory is a helper function useful to report errors when at least one flag is not used in a group of "required" flags @@ -43,9 +43,9 @@ func CheckFlagsMandatory(command *cobra.Command, flagNames ...string) { for _, flagName := range flagNames { if command.Flag(flagName).Changed { continue - } else { - feedback.Errorf(tr("Flag %[1]s is mandatory when used in conjunction with flag %[2]s.", "--"+flagName, "--"+strings.Join(flagNames, " "+tr("and")+" --"))) - os.Exit(errorcodes.ErrBadArgument) } + flags := "--" + strings.Join(flagNames, ", --") + msg := tr("Flag %[1]s is mandatory when used in conjunction with: %[2]s", "--"+flagName, flags) + feedback.Fatal(msg, errorcodes.ErrBadArgument) } } diff --git a/cli/arguments/fqbn.go b/cli/arguments/fqbn.go index 8520994d2fb..8004c6a9a05 100644 --- a/cli/arguments/fqbn.go +++ b/cli/arguments/fqbn.go @@ -16,7 +16,6 @@ package arguments import ( - "os" "strings" "github.com/arduino/arduino-cli/arduino" @@ -81,21 +80,18 @@ func CalculateFQBNAndPort(portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance, } if fqbn == "" { if portArgs == nil || portArgs.address == "" { - feedback.Error(&arduino.MissingFQBNError{}) - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(&arduino.MissingFQBNError{}, errorcodes.ErrGeneric) } fqbn, port := portArgs.DetectFQBN(instance) if fqbn == "" { - feedback.Error(&arduino.MissingFQBNError{}) - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(&arduino.MissingFQBNError{}, errorcodes.ErrGeneric) } return fqbn, port } port, err := portArgs.GetPort(instance, sk) if err != nil { - feedback.Errorf(tr("Error getting port metadata: %v", err)) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error getting port metadata: %v", err), errorcodes.ErrGeneric) } return fqbn, port.ToRPC() } diff --git a/cli/arguments/port.go b/cli/arguments/port.go index 54162f98eab..d52b9f46488 100644 --- a/cli/arguments/port.go +++ b/cli/arguments/port.go @@ -17,7 +17,6 @@ package arguments import ( "fmt" - "os" "time" "github.com/arduino/arduino-cli/arduino" @@ -147,8 +146,7 @@ func (p *Port) DetectFQBN(inst *rpc.Instance) (string, *rpc.Port) { Timeout: p.timeout.Get().Milliseconds(), }) if err != nil { - feedback.Errorf(tr("Error during FQBN detection: %v", err)) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during FQBN detection: %v", err), errorcodes.ErrGeneric) } for _, detectedPort := range detectedPorts { port := detectedPort.GetPort() @@ -159,12 +157,10 @@ func (p *Port) DetectFQBN(inst *rpc.Instance) (string, *rpc.Port) { continue } if len(detectedPort.MatchingBoards) > 1 { - feedback.Error(&arduino.MultipleBoardsDetectedError{Port: port}) - os.Exit(errorcodes.ErrBadArgument) + feedback.FatalError(&arduino.MultipleBoardsDetectedError{Port: port}, errorcodes.ErrBadArgument) } if len(detectedPort.MatchingBoards) == 0 { - feedback.Error(&arduino.NoBoardsDetectedError{Port: port}) - os.Exit(errorcodes.ErrBadArgument) + feedback.FatalError(&arduino.NoBoardsDetectedError{Port: port}, errorcodes.ErrBadArgument) } return detectedPort.MatchingBoards[0].Fqbn, port } diff --git a/cli/arguments/sketch.go b/cli/arguments/sketch.go index 11a93c1963b..922d4f32817 100644 --- a/cli/arguments/sketch.go +++ b/cli/arguments/sketch.go @@ -16,8 +16,6 @@ package arguments import ( - "os" - "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" @@ -34,8 +32,7 @@ func InitSketchPath(path string) (sketchPath *paths.Path) { } else { wd, err := paths.Getwd() if err != nil { - feedback.Errorf(tr("Couldn't get current working directory: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Couldn't get current working directory: %v", err), errorcodes.ErrGeneric) } logrus.Infof("Reading sketch from dir: %s", wd) sketchPath = wd @@ -48,8 +45,7 @@ func InitSketchPath(path string) (sketchPath *paths.Path) { func NewSketch(sketchPath *paths.Path) *sketch.Sketch { sketch, err := sketch.New(sketchPath) if err != nil { - feedback.Errorf(tr("Error opening sketch: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error opening sketch: %v", err), errorcodes.ErrGeneric) } return sketch } diff --git a/cli/board/attach.go b/cli/board/attach.go index 14751a7bcee..ca50eb97924 100644 --- a/cli/board/attach.go +++ b/cli/board/attach.go @@ -67,8 +67,7 @@ func runAttachCommand(path string, port *arguments.Port, fqbn string) { address, protocol, _ := port.GetPortAddressAndProtocol(nil, sk) if address != "" { if err := sk.SetDefaultPort(address, protocol); err != nil { - feedback.Errorf("%s: %s", tr("Error saving sketch metadata"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(fmt.Sprintf("%s: %s", tr("Error saving sketch metadata"), err), errorcodes.ErrGeneric) } current.Port = &boardAttachPortResult{ Address: address, @@ -77,8 +76,7 @@ func runAttachCommand(path string, port *arguments.Port, fqbn string) { } if fqbn != "" { if err := sk.SetDefaultFQBN(fqbn); err != nil { - feedback.Errorf("%s: %s", tr("Error saving sketch metadata"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(fmt.Sprintf("%s: %s", tr("Error saving sketch metadata"), err), errorcodes.ErrGeneric) } current.Fqbn = fqbn } diff --git a/cli/board/details.go b/cli/board/details.go index 9a4143bc8ff..ba9de2fa356 100644 --- a/cli/board/details.go +++ b/cli/board/details.go @@ -67,8 +67,7 @@ func runDetailsCommand(cmd *cobra.Command, args []string) { }) if err != nil { - feedback.Errorf(tr("Error getting board details: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error getting board details: %v", err), errorcodes.ErrGeneric) } feedback.PrintResult(detailsResult{details: res}) diff --git a/cli/board/list.go b/cli/board/list.go index 7a690d24d39..4b412d9cb86 100644 --- a/cli/board/list.go +++ b/cli/board/list.go @@ -80,8 +80,7 @@ func runListCommand(cmd *cobra.Command, args []string) { func watchList(cmd *cobra.Command, inst *rpc.Instance) { eventsChan, closeCB, err := board.Watch(&rpc.BoardListWatchRequest{Instance: inst}) if err != nil { - feedback.Errorf(tr("Error detecting boards: %v"), err) - os.Exit(errorcodes.ErrNetwork) + feedback.Fatal(tr("Error detecting boards: %v", err), errorcodes.ErrNetwork) } defer closeCB() diff --git a/cli/board/listall.go b/cli/board/listall.go index b4142b935cd..429daf00b11 100644 --- a/cli/board/listall.go +++ b/cli/board/listall.go @@ -61,8 +61,7 @@ func runListAllCommand(cmd *cobra.Command, args []string) { IncludeHiddenBoards: showHiddenBoard, }) if err != nil { - feedback.Errorf(tr("Error listing boards: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error listing boards: %v", err), errorcodes.ErrGeneric) } feedback.PrintResult(resultAll{list}) diff --git a/cli/board/search.go b/cli/board/search.go index be2e7b97e19..12cf7499d73 100644 --- a/cli/board/search.go +++ b/cli/board/search.go @@ -59,8 +59,7 @@ func runSearchCommand(cmd *cobra.Command, args []string) { IncludeHiddenBoards: showHiddenBoard, }) if err != nil { - feedback.Errorf(tr("Error searching boards: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error searching boards: %v", err), errorcodes.ErrGeneric) } feedback.PrintResult(searchResults{res.Boards}) diff --git a/cli/burnbootloader/burnbootloader.go b/cli/burnbootloader/burnbootloader.go index f16997086be..0f35e6ea6ea 100644 --- a/cli/burnbootloader/burnbootloader.go +++ b/cli/burnbootloader/burnbootloader.go @@ -70,8 +70,7 @@ func runBootloaderCommand(command *cobra.Command, args []string) { // We don't need a Sketch to upload a board's bootloader discoveryPort, err := port.GetPort(instance, nil) if err != nil { - feedback.Errorf(tr("Error during Upload: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) } if _, err := upload.BurnBootloader(context.Background(), &rpc.BurnBootloaderRequest{ @@ -83,8 +82,7 @@ func runBootloaderCommand(command *cobra.Command, args []string) { Programmer: programmer.String(), DryRun: dryRun, }, os.Stdout, os.Stderr); err != nil { - feedback.Errorf(tr("Error during Upload: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) } os.Exit(0) } diff --git a/cli/cache/clean.go b/cli/cache/clean.go index cd0648f668f..fddb0e5e3c8 100644 --- a/cli/cache/clean.go +++ b/cli/cache/clean.go @@ -43,7 +43,6 @@ func runCleanCommand(cmd *cobra.Command, args []string) { cachePath := configuration.DownloadsDir(configuration.Settings) err := cachePath.RemoveAll() if err != nil { - feedback.Errorf(tr("Error cleaning caches: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error cleaning caches: %v", err), errorcodes.ErrGeneric) } } diff --git a/cli/cli.go b/cli/cli.go index 817f30cf9f7..441e15c0e62 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -149,8 +149,7 @@ func preRun(cmd *cobra.Command, args []string) { // initialize inventory err := inventory.Init(configuration.DataDir(configuration.Settings).String()) if err != nil { - feedback.Errorf("Error: %v", err) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(fmt.Sprintf("Error: %v", err), errorcodes.ErrBadArgument) } // https://no-color.org/ @@ -201,8 +200,7 @@ func preRun(cmd *cobra.Command, args []string) { if logFile != "" { file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { - feedback.Errorf(tr("Unable to open file for logging: %s", logFile)) - os.Exit(errorcodes.ErrBadCall) + feedback.Fatal(tr("Unable to open file for logging: %s", logFile), errorcodes.ErrBadCall) } // we use a hook so we don't get color codes in the log file @@ -215,8 +213,7 @@ func preRun(cmd *cobra.Command, args []string) { // configure logging filter if lvl, found := toLogLevel(configuration.Settings.GetString("logging.level")); !found { - feedback.Errorf(tr("Invalid option for --log-level: %s"), configuration.Settings.GetString("logging.level")) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid option for --log-level: %s", configuration.Settings.GetString("logging.level")), errorcodes.ErrBadArgument) } else { logrus.SetLevel(lvl) } @@ -228,8 +225,7 @@ func preRun(cmd *cobra.Command, args []string) { // check the right output format was passed format, found := feedback.ParseOutputFormat(outputFormat) if !found { - feedback.Errorf(tr("Invalid output format: %s"), outputFormat) - os.Exit(errorcodes.ErrBadCall) + feedback.Fatal(tr("Invalid output format: %s", outputFormat), errorcodes.ErrBadCall) } // use the output format to configure the Feedback @@ -250,8 +246,7 @@ func preRun(cmd *cobra.Command, args []string) { if outputFormat != "text" { cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { logrus.Warn("Calling help on JSON format") - feedback.Error(tr("Invalid Call : should show Help, but it is available only in TEXT mode.")) - os.Exit(errorcodes.ErrBadCall) + feedback.Fatal(tr("Invalid Call : should show Help, but it is available only in TEXT mode."), errorcodes.ErrBadCall) }) } } diff --git a/cli/compile/compile.go b/cli/compile/compile.go index 646afc6695c..a5997ec7fc2 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -148,17 +148,14 @@ func runCompileCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino-cli compile`") if dumpProfile && feedback.GetFormat() != feedback.Text { - feedback.Errorf(tr("You cannot use the %[1]s flag together with %[2]s.", "--dump-profile", "--format json")) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("You cannot use the %[1]s flag together with %[2]s.", "--dump-profile", "--format json"), errorcodes.ErrBadArgument) } if profileArg.Get() != "" { if len(libraries) > 0 { - feedback.Errorf(tr("You cannot use the %s flag while compiling with a profile.", "--libraries")) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("You cannot use the %s flag while compiling with a profile.", "--libraries"), errorcodes.ErrBadArgument) } if len(library) > 0 { - feedback.Errorf(tr("You cannot use the %s flag while compiling with a profile.", "--library")) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("You cannot use the %s flag while compiling with a profile.", "--library"), errorcodes.ErrBadArgument) } } @@ -185,15 +182,13 @@ func runCompileCommand(cmd *cobra.Command, args []string) { if sourceOverrides != "" { data, err := paths.New(sourceOverrides).ReadFile() if err != nil { - feedback.Errorf(tr("Error opening source code overrides data file: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error opening source code overrides data file: %v", err), errorcodes.ErrGeneric) } var o struct { Overrides map[string]string `json:"overrides"` } if err := json.Unmarshal(data, &o); err != nil { - feedback.Errorf(tr("Error: invalid source code overrides data file: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error: invalid source code overrides data file: %v", err), errorcodes.ErrGeneric) } overrides = o.Overrides } @@ -241,16 +236,14 @@ func runCompileCommand(cmd *cobra.Command, args []string) { Protocol: port.Protocol, }) if err != nil { - feedback.Errorf(tr("Error during Upload: %v", err)) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) } fields := map[string]string{} if len(userFieldRes.UserFields) > 0 { feedback.Print(tr("Uploading to specified board using %s protocol requires the following info:", port.Protocol)) if f, err := arguments.AskForUserFields(userFieldRes.UserFields); err != nil { - feedback.Error(err) - os.Exit(errorcodes.ErrBadArgument) + feedback.FatalError(err, errorcodes.ErrBadArgument) } else { fields = f } @@ -278,8 +271,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { uploadError = upload.Upload(context.Background(), uploadRequest, os.Stdout, os.Stderr) } if uploadError != nil { - feedback.Errorf(tr("Error during Upload: %v"), uploadError) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", uploadError), errorcodes.ErrGeneric) } } @@ -338,7 +330,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { Success: compileError == nil, }) if compileError != nil { - feedback.Errorf(tr("Error during build: %v"), compileError) + msg := tr("Error during build: %v", compileError) // Check the error type to give the user better feedback on how // to resolve it @@ -358,14 +350,16 @@ func runCompileCommand(cmd *cobra.Command, args []string) { release() if profileArg.String() == "" { + msg += "\n" if platform != nil { - feedback.Errorf(tr("Try running %s", fmt.Sprintf("`%s core install %s`", globals.VersionInfo.Application, platformErr.Platform))) + suggestion := fmt.Sprintf("`%s core install %s`", globals.VersionInfo.Application, platformErr.Platform) + msg += tr("Try running %s", suggestion) } else { - feedback.Errorf(tr("Platform %s is not found in any known index\nMaybe you need to add a 3rd party URL?", platformErr.Platform)) + msg += tr("Platform %s is not found in any known index\nMaybe you need to add a 3rd party URL?", platformErr.Platform) } } } - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(msg, errorcodes.ErrGeneric) } } diff --git a/cli/completion/completion.go b/cli/completion/completion.go index d7f822d016e..ad76ada3996 100644 --- a/cli/completion/completion.go +++ b/cli/completion/completion.go @@ -50,8 +50,7 @@ func NewCommand() *cobra.Command { func runCompletionCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino-cli completion`") if completionNoDesc && (args[0] == "powershell") { - feedback.Errorf(tr("Error: command description is not supported by %v"), args[0]) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error: command description is not supported by %v", args[0]), errorcodes.ErrGeneric) } switch args[0] { case "bash": diff --git a/cli/config/add.go b/cli/config/add.go index ab27aa316cc..39fe2b10b05 100644 --- a/cli/config/add.go +++ b/cli/config/add.go @@ -91,8 +91,8 @@ func runAddCommand(cmd *cobra.Command, args []string) { kind := validateKey(key) if kind != reflect.Slice { - feedback.Errorf(tr("The key '%[1]v' is not a list of items, can't add to it.\nMaybe use '%[2]s'?"), key, "config set") - os.Exit(errorcodes.ErrGeneric) + msg := tr("The key '%[1]v' is not a list of items, can't add to it.\nMaybe use '%[2]s'?", key, "config set") + feedback.Fatal(msg, errorcodes.ErrGeneric) } v := configuration.Settings.GetStringSlice(key) @@ -101,7 +101,6 @@ func runAddCommand(cmd *cobra.Command, args []string) { configuration.Settings.Set(key, v) if err := configuration.Settings.WriteConfig(); err != nil { - feedback.Errorf(tr("Can't write config file: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Can't write config file: %v", err), errorcodes.ErrGeneric) } } diff --git a/cli/config/delete.go b/cli/config/delete.go index 58a68b97ba8..bce6c7e8098 100644 --- a/cli/config/delete.go +++ b/cli/config/delete.go @@ -59,8 +59,7 @@ func runDeleteCommand(cmd *cobra.Command, args []string) { } if !exists { - feedback.Errorf(tr("Settings key doesn't exist")) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Settings key doesn't exist"), errorcodes.ErrGeneric) } updatedSettings := viper.New() @@ -69,7 +68,6 @@ func runDeleteCommand(cmd *cobra.Command, args []string) { } if err := updatedSettings.WriteConfigAs(configuration.Settings.ConfigFileUsed()); err != nil { - feedback.Errorf(tr("Can't write config file: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Can't write config file: %v", err), errorcodes.ErrGeneric) } } diff --git a/cli/config/dump.go b/cli/config/dump.go index 19f7885c8d3..748b51a2b81 100644 --- a/cli/config/dump.go +++ b/cli/config/dump.go @@ -55,9 +55,8 @@ func (dr dumpResult) Data() interface{} { func (dr dumpResult) String() string { bs, err := yaml.Marshal(dr.data) if err != nil { - feedback.Errorf(tr("unable to marshal config to YAML: %v"), err) - return "" + // Should never happen + panic(tr("unable to marshal config to YAML: %v", err)) } - return string(bs) } diff --git a/cli/config/init.go b/cli/config/init.go index 59f88d72184..fc856529f28 100644 --- a/cli/config/init.go +++ b/cli/config/init.go @@ -69,8 +69,7 @@ func runInitCommand(cmd *cobra.Command, args []string) { case destFile != "": configFileAbsPath, err = paths.New(destFile).Abs() if err != nil { - feedback.Errorf(tr("Cannot find absolute path: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Cannot find absolute path: %v", err), errorcodes.ErrGeneric) } absPath = configFileAbsPath.Parent() @@ -80,22 +79,19 @@ func runInitCommand(cmd *cobra.Command, args []string) { default: absPath, err = paths.New(destDir).Abs() if err != nil { - feedback.Errorf(tr("Cannot find absolute path: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Cannot find absolute path: %v", err), errorcodes.ErrGeneric) } configFileAbsPath = absPath.Join(defaultFileName) } if !overwrite && configFileAbsPath.Exist() { - feedback.Error(tr("Config file already exists, use --overwrite to discard the existing one.")) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Config file already exists, use --overwrite to discard the existing one."), errorcodes.ErrGeneric) } logrus.Infof("Writing config file to: %s", absPath) if err := absPath.MkdirAll(); err != nil { - feedback.Errorf(tr("Cannot create config file directory: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Cannot create config file directory: %v", err), errorcodes.ErrGeneric) } newSettings := viper.New() @@ -103,8 +99,7 @@ func runInitCommand(cmd *cobra.Command, args []string) { configuration.BindFlags(cmd, newSettings) if err := newSettings.WriteConfigAs(configFileAbsPath.String()); err != nil { - feedback.Errorf(tr("Cannot create config file: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Cannot create config file: %v", err), errorcodes.ErrGeneric) } msg := tr("Config file written to: %s", configFileAbsPath.String()) diff --git a/cli/config/remove.go b/cli/config/remove.go index 63b7a071e91..61f0cc2c5d9 100644 --- a/cli/config/remove.go +++ b/cli/config/remove.go @@ -49,8 +49,8 @@ func runRemoveCommand(cmd *cobra.Command, args []string) { kind := validateKey(key) if kind != reflect.Slice { - feedback.Errorf(tr("The key '%[1]v' is not a list of items, can't remove from it.\nMaybe use '%[2]s'?"), key, "config delete") - os.Exit(errorcodes.ErrGeneric) + msg := tr("The key '%[1]v' is not a list of items, can't remove from it.\nMaybe use '%[2]s'?", key, "config delete") + feedback.Fatal(msg, errorcodes.ErrGeneric) } mappedValues := map[string]bool{} @@ -67,7 +67,6 @@ func runRemoveCommand(cmd *cobra.Command, args []string) { configuration.Settings.Set(key, values) if err := configuration.Settings.WriteConfig(); err != nil { - feedback.Errorf(tr("Can't write config file: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Can't write config file: %v", err), errorcodes.ErrGeneric) } } diff --git a/cli/config/set.go b/cli/config/set.go index 9577915e755..4ae2ba07bf8 100644 --- a/cli/config/set.go +++ b/cli/config/set.go @@ -52,8 +52,7 @@ func runSetCommand(cmd *cobra.Command, args []string) { kind := validateKey(key) if kind != reflect.Slice && len(args) > 2 { - feedback.Errorf(tr("Can't set multiple values in key %v"), key) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Can't set multiple values in key %v", key), errorcodes.ErrGeneric) } var value interface{} @@ -66,15 +65,13 @@ func runSetCommand(cmd *cobra.Command, args []string) { var err error value, err = strconv.ParseBool(args[1]) if err != nil { - feedback.Errorf(tr("error parsing value: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("error parsing value: %v", err), errorcodes.ErrGeneric) } } configuration.Settings.Set(key, value) if err := configuration.Settings.WriteConfig(); err != nil { - feedback.Errorf(tr("Writing config file: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Writing config file: %v", err), errorcodes.ErrGeneric) } } diff --git a/cli/config/validate.go b/cli/config/validate.go index 1ac6c538e1f..aca9fa2860d 100644 --- a/cli/config/validate.go +++ b/cli/config/validate.go @@ -17,7 +17,6 @@ package config import ( "fmt" - "os" "reflect" "github.com/arduino/arduino-cli/cli/errorcodes" @@ -57,8 +56,7 @@ func typeOf(key string) (reflect.Kind, error) { func validateKey(key string) reflect.Kind { kind, err := typeOf(key) if err != nil { - feedback.Error(err) - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, errorcodes.ErrGeneric) } return kind } diff --git a/cli/core/download.go b/cli/core/download.go index f6415a96208..17f7ce49bba 100644 --- a/cli/core/download.go +++ b/cli/core/download.go @@ -54,8 +54,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { platformsRefs, err := arguments.ParseReferences(args) if err != nil { - feedback.Errorf(tr("Invalid argument passed: %v"), err) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) } for i, platformRef := range platformsRefs { @@ -67,8 +66,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { } _, err := core.PlatformDownload(context.Background(), platformDownloadreq, feedback.ProgressBar()) if err != nil { - feedback.Errorf(tr("Error downloading %[1]s: %[2]v"), args[i], err) - os.Exit(errorcodes.ErrNetwork) + feedback.Fatal(tr("Error downloading %[1]s: %[2]v", args[i], err), errorcodes.ErrNetwork) } } } diff --git a/cli/core/install.go b/cli/core/install.go index 0b23a3b1908..8841c0afefa 100644 --- a/cli/core/install.go +++ b/cli/core/install.go @@ -63,8 +63,7 @@ func runInstallCommand(args []string, postInstallFlags arguments.PostInstallFlag platformsRefs, err := arguments.ParseReferences(args) if err != nil { - feedback.Errorf(tr("Invalid argument passed: %v"), err) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) } for _, platformRef := range platformsRefs { @@ -78,8 +77,7 @@ func runInstallCommand(args []string, postInstallFlags arguments.PostInstallFlag } _, err := core.PlatformInstall(context.Background(), platformInstallRequest, feedback.ProgressBar(), feedback.TaskProgress()) if err != nil { - feedback.Errorf(tr("Error during install: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during install: %v", err), errorcodes.ErrGeneric) } } } diff --git a/cli/core/list.go b/cli/core/list.go index ce45b785eec..e5ad24ad2f0 100644 --- a/cli/core/list.go +++ b/cli/core/list.go @@ -61,8 +61,7 @@ func List(inst *rpc.Instance, all bool, updatableOnly bool) { All: all, }) if err != nil { - feedback.Errorf(tr("Error listing platforms: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error listing platforms: %v", err), errorcodes.ErrGeneric) } feedback.PrintResult(installedResult{platforms}) diff --git a/cli/core/search.go b/cli/core/search.go index 794143a8c19..fd70d2e217c 100644 --- a/cli/core/search.go +++ b/cli/core/search.go @@ -61,8 +61,7 @@ const indexUpdateInterval = "24h" func runSearchCommand(cmd *cobra.Command, args []string) { inst, status := instance.Create() if status != nil { - feedback.Errorf(tr("Error creating instance: %v"), status) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating instance: %v", status), errorcodes.ErrGeneric) } if indexesNeedUpdating(indexUpdateInterval) { @@ -83,8 +82,7 @@ func runSearchCommand(cmd *cobra.Command, args []string) { AllVersions: allVersions, }) if err != nil { - feedback.Errorf(tr("Error searching for platforms: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error searching for platforms: %v", err), errorcodes.ErrGeneric) } coreslist := resp.GetSearchOutput() @@ -128,8 +126,7 @@ func indexesNeedUpdating(duration string) bool { now := time.Now() modTimeThreshold, err := time.ParseDuration(duration) if err != nil { - feedback.Error(tr("Invalid timeout: %s", err)) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid timeout: %s", err), errorcodes.ErrBadArgument) } urls := []string{globals.DefaultIndexURL} diff --git a/cli/core/uninstall.go b/cli/core/uninstall.go index 927edf919d2..9d527016c2c 100644 --- a/cli/core/uninstall.go +++ b/cli/core/uninstall.go @@ -51,14 +51,12 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { platformsRefs, err := arguments.ParseReferences(args) if err != nil { - feedback.Errorf(tr("Invalid argument passed: %v"), err) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) } for _, platformRef := range platformsRefs { if platformRef.Version != "" { - feedback.Errorf(tr("Invalid parameter %s: version not allowed"), platformRef) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid parameter %s: version not allowed", platformRef), errorcodes.ErrBadArgument) } } for _, platformRef := range platformsRefs { @@ -68,8 +66,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { Architecture: platformRef.Architecture, }, feedback.NewTaskProgressCB()) if err != nil { - feedback.Errorf(tr("Error during uninstall: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during uninstall: %v", err), errorcodes.ErrGeneric) } } } diff --git a/cli/core/update_index.go b/cli/core/update_index.go index 0f9ae8cf179..c4d23b1326a 100644 --- a/cli/core/update_index.go +++ b/cli/core/update_index.go @@ -50,7 +50,6 @@ func runUpdateIndexCommand(cmd *cobra.Command, args []string) { func UpdateIndex(inst *rpc.Instance) { err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexRequest{Instance: inst}, feedback.ProgressBar()) if err != nil { - feedback.Error(err) - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, errorcodes.ErrGeneric) } } diff --git a/cli/core/upgrade.go b/cli/core/upgrade.go index 7f43aa4b785..d9bf23ca293 100644 --- a/cli/core/upgrade.go +++ b/cli/core/upgrade.go @@ -66,8 +66,7 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { UpdatableOnly: true, }) if err != nil { - feedback.Errorf(tr("Error retrieving core list: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error retrieving core list: %v", err), errorcodes.ErrGeneric) } if len(targets) == 0 { @@ -84,8 +83,7 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { exitErr := false platformsRefs, err := arguments.ParseReferences(args) if err != nil { - feedback.Errorf(tr("Invalid argument passed: %v"), err) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) } for i, platformRef := range platformsRefs { @@ -108,8 +106,7 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { continue } - feedback.Errorf(tr("Error during upgrade: %v", err)) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during upgrade: %v", err), errorcodes.ErrGeneric) } } diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index 26edfac21e9..1c93a1c08b5 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -79,8 +79,7 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { gRPCOptions := []grpc.ServerOption{} if debugFile != "" { if !debug { - feedback.Error(tr("The flag --debug-file must be used with --debug.")) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("The flag --debug-file must be used with --debug."), errorcodes.ErrBadArgument) } } if debug { @@ -88,8 +87,7 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { outFile := paths.New(debugFile) f, err := outFile.Append() if err != nil { - feedback.Error(tr("Error opening debug logging file: %s", err)) - os.Exit(errorcodes.ErrBadCall) + feedback.Fatal(tr("Error opening debug logging file: %s", err), errorcodes.ErrBadCall) } debugStdOut = f defer f.Close() @@ -128,23 +126,19 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { // Invalid port, such as "Foo" var dnsError *net.DNSError if errors.As(err, &dnsError) { - feedback.Errorf(tr("Failed to listen on TCP port: %[1]s. %[2]s is unknown name."), port, dnsError.Name) - os.Exit(errorcodes.ErrCoreConfig) + feedback.Fatal(tr("Failed to listen on TCP port: %[1]s. %[2]s is unknown name.", port, dnsError.Name), errorcodes.ErrCoreConfig) } // Invalid port number, such as -1 var addrError *net.AddrError if errors.As(err, &addrError) { - feedback.Errorf(tr("Failed to listen on TCP port: %[1]s. %[2]s is an invalid port."), port, addrError.Addr) - os.Exit(errorcodes.ErrCoreConfig) + feedback.Fatal(tr("Failed to listen on TCP port: %[1]s. %[2]s is an invalid port.", port, addrError.Addr), errorcodes.ErrCoreConfig) } // Port is already in use var syscallErr *os.SyscallError if errors.As(err, &syscallErr) && errors.Is(syscallErr.Err, syscall.EADDRINUSE) { - feedback.Errorf(tr("Failed to listen on TCP port: %s. Address already in use."), port) - os.Exit(errorcodes.ErrNetwork) + feedback.Fatal(tr("Failed to listen on TCP port: %s. Address already in use.", port), errorcodes.ErrNetwork) } - feedback.Errorf(tr("Failed to listen on TCP port: %[1]s. Unexpected error: %[2]v"), port, err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Failed to listen on TCP port: %[1]s. Unexpected error: %[2]v", port, err), errorcodes.ErrGeneric) } // We need to parse the port used only if the user let @@ -155,7 +149,7 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { split := strings.Split(address.String(), ":") if len(split) == 0 { - feedback.Error(tr("Failed choosing port, address: %s", address)) + feedback.Fatal(tr("Invalid TCP address: port is missing"), errorcodes.ErrBadArgument) } port = split[len(split)-1] diff --git a/cli/debug/debug.go b/cli/debug/debug.go index 1dd0d56da25..b9e99f3904a 100644 --- a/cli/debug/debug.go +++ b/cli/debug/debug.go @@ -91,8 +91,7 @@ func runDebugCommand(command *cobra.Command, args []string) { if printInfo { if res, err := debug.GetDebugConfig(context.Background(), debugConfigRequested); err != nil { - feedback.Errorf(tr("Error getting Debug info: %v", err)) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Error getting Debug info: %v", err), errorcodes.ErrBadArgument) } else { feedback.PrintResult(&debugInfoResult{res}) } @@ -104,8 +103,7 @@ func runDebugCommand(command *cobra.Command, args []string) { signal.Notify(ctrlc, os.Interrupt) if _, err := debug.Debug(context.Background(), debugConfigRequested, os.Stdin, os.Stdout, ctrlc); err != nil { - feedback.Errorf(tr("Error during Debug: %v", err)) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Debug: %v", err), errorcodes.ErrGeneric) } } diff --git a/cli/feedback/feedback.go b/cli/feedback/feedback.go index 5daaf4ed304..bdae6fbb392 100644 --- a/cli/feedback/feedback.go +++ b/cli/feedback/feedback.go @@ -25,6 +25,7 @@ import ( "io" "os" + "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/i18n" "github.com/sirupsen/logrus" "google.golang.org/grpc/status" @@ -175,6 +176,39 @@ func Error(v ...interface{}) { logrus.Error(fmt.Sprint(v...)) } +// FatalError outputs the error and exits with status exitCode. +func FatalError(err error, exitCode int) { + Fatal(err.Error(), exitCode) +} + +// Fatal outputs the errorMsg and exits with status exitCode. +func Fatal(errorMsg string, exitCode int) { + if format == Text { + fmt.Fprintln(stdErr, errorMsg) + os.Exit(exitCode) + } + + type FatalError struct { + Error string `json:"error"` + } + res := FatalError{ + Error: errorMsg, + } + var d []byte + switch format { + case JSON: + d, _ = json.MarshalIndent(res, "", " ") + case MinifiedJSON: + d, _ = json.Marshal(res) + case YAML: + d, _ = yaml.Marshal(res) + default: + panic("unknown output format") + } + fmt.Fprintln(stdErr, string(d)) + os.Exit(exitCode) +} + // PrintResult is a convenient wrapper to provide feedback for complex data, // where the contents can't be just serialized to JSON but requires more // structure. @@ -184,22 +218,19 @@ func PrintResult(res Result) { case JSON: d, err := json.MarshalIndent(res.Data(), "", " ") if err != nil { - Errorf("Error during JSON encoding of the output: %v", err) - return + Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), errorcodes.ErrGeneric) } data = string(d) case MinifiedJSON: d, err := json.Marshal(res.Data()) if err != nil { - Errorf("Error during JSON encoding of the output: %v", err) - return + Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), errorcodes.ErrGeneric) } data = string(d) case YAML: d, err := yaml.Marshal(res.Data()) if err != nil { - Errorf("Error during YAML encoding of the output: %v", err) - return + Fatal(fmt.Sprintf("Error during YAML encoding of the output: %v", err), errorcodes.ErrGeneric) } data = string(d) case Text: diff --git a/cli/feedback/feedback_cmd.go b/cli/feedback/feedback_cmd.go index e298134e9a9..d743a72ea76 100644 --- a/cli/feedback/feedback_cmd.go +++ b/cli/feedback/feedback_cmd.go @@ -16,7 +16,7 @@ package feedback import ( - "os" + "fmt" "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/spf13/cobra" @@ -38,18 +38,15 @@ func NewCommand() *cobra.Command { Run: func(cmd *cobra.Command, args []string) { user, err := InputUserField("User name", false) if err != nil { - Errorf("Error reading input: %v", err) - os.Exit(errorcodes.ErrGeneric) + Fatal(fmt.Sprintf("Error reading input: %v", err), errorcodes.ErrGeneric) } pass, err := InputUserField("Password", true) if err != nil { - Errorf("Error reading input: %v", err) - os.Exit(errorcodes.ErrGeneric) + Fatal(fmt.Sprintf("Error reading input: %v", err), errorcodes.ErrGeneric) } nick, err := InputUserField("Nickname", false) if err != nil { - Errorf("Error reading input: %v", err) - os.Exit(errorcodes.ErrGeneric) + Fatal(fmt.Sprintf("Error reading input: %v", err), errorcodes.ErrGeneric) } Print("Hello " + user + " (a.k.a " + nick + ")!") Print("Your password is " + pass + "!") diff --git a/cli/instance/instance.go b/cli/instance/instance.go index 9d66bd2c6a2..3e9fce7afc0 100644 --- a/cli/instance/instance.go +++ b/cli/instance/instance.go @@ -17,7 +17,6 @@ package instance import ( "context" - "os" "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" @@ -45,8 +44,7 @@ func CreateAndInit() *rpc.Instance { func CreateAndInitWithProfile(profileName string, sketchPath *paths.Path) (*rpc.Instance, *rpc.Profile) { instance, err := Create() if err != nil { - feedback.Errorf(tr("Error creating instance: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating instance: %v", err), errorcodes.ErrGeneric) } profile := InitWithProfile(instance, profileName, sketchPath) return instance, profile @@ -168,8 +166,7 @@ func CreateInstanceAndRunFirstUpdate() *rpc.Instance { // as argument but none would be obviously found. inst, status := Create() if status != nil { - feedback.Errorf(tr("Error creating instance: %v"), status) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating instance: %v", status), errorcodes.ErrGeneric) } // In case this is the first time the CLI is run we need to update indexes @@ -177,8 +174,7 @@ func CreateInstanceAndRunFirstUpdate() *rpc.Instance { // we must use instance.Create instead of instance.CreateAndInit for the // reason stated above. if err := FirstUpdate(inst); err != nil { - feedback.Errorf(tr("Error updating indexes: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error updating indexes: %v", err), errorcodes.ErrGeneric) } return inst } diff --git a/cli/lib/check_deps.go b/cli/lib/check_deps.go index ae2c6f4141c..57d0d33a216 100644 --- a/cli/lib/check_deps.go +++ b/cli/lib/check_deps.go @@ -54,8 +54,7 @@ func runDepsCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino-cli lib deps`") libRef, err := ParseLibraryReferenceArgAndAdjustCase(instance, args[0]) if err != nil { - feedback.Errorf(tr("Arguments error: %v"), err) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Arguments error: %v", err), errorcodes.ErrBadArgument) } deps, err := lib.LibraryResolveDependencies(context.Background(), &rpc.LibraryResolveDependenciesRequest{ @@ -64,7 +63,7 @@ func runDepsCommand(cmd *cobra.Command, args []string) { Version: libRef.Version, }) if err != nil { - feedback.Errorf(tr("Error resolving dependencies for %[1]s: %[2]s", libRef, err)) + feedback.Fatal(tr("Error resolving dependencies for %[1]s: %[2]s", libRef, err), errorcodes.ErrGeneric) } feedback.PrintResult(&checkDepResult{deps: deps}) diff --git a/cli/lib/download.go b/cli/lib/download.go index 920237d8676..d6fc7a7af15 100644 --- a/cli/lib/download.go +++ b/cli/lib/download.go @@ -52,8 +52,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino-cli lib download`") refs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args) if err != nil { - feedback.Errorf(tr("Invalid argument passed: %v"), err) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) } for _, library := range refs { @@ -64,8 +63,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { } _, err := lib.LibraryDownload(context.Background(), libraryDownloadRequest, feedback.ProgressBar()) if err != nil { - feedback.Errorf(tr("Error downloading %[1]s: %[2]v"), library, err) - os.Exit(errorcodes.ErrNetwork) + feedback.Fatal(tr("Error downloading %[1]s: %[2]v", library, err), errorcodes.ErrNetwork) } } } diff --git a/cli/lib/examples.go b/cli/lib/examples.go index 5e60728a825..69433576805 100644 --- a/cli/lib/examples.go +++ b/cli/lib/examples.go @@ -70,8 +70,7 @@ func runExamplesCommand(cmd *cobra.Command, args []string) { Fqbn: fqbn.String(), }) if err != nil { - feedback.Errorf(tr("Error getting libraries info: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error getting libraries info: %v", err), errorcodes.ErrGeneric) } found := []*libraryExamples{} diff --git a/cli/lib/install.go b/cli/lib/install.go index 807fae19494..91ad3b3d479 100644 --- a/cli/lib/install.go +++ b/cli/lib/install.go @@ -78,8 +78,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { split := strings.Split(globals.VersionInfo.VersionString, ".") documentationURL = fmt.Sprintf("https://arduino.github.io/arduino-cli/%s.%s/configuration/#configuration-keys", split[0], split[1]) } - feedback.Errorf(tr("--git-url and --zip-path are disabled by default, for more information see: %v"), documentationURL) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("--git-url and --zip-path are disabled by default, for more information see: %v", documentationURL), errorcodes.ErrGeneric) } feedback.Print(tr("--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")) } @@ -92,8 +91,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Overwrite: !noOverwrite, }, feedback.TaskProgress()) if err != nil { - feedback.Errorf(tr("Error installing Zip Library: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error installing Zip Library: %v", err), errorcodes.ErrGeneric) } } return @@ -104,8 +102,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { if url == "." { wd, err := paths.Getwd() if err != nil { - feedback.Errorf(tr("Couldn't get current working directory: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Couldn't get current working directory: %v", err), errorcodes.ErrGeneric) } url = wd.String() } @@ -115,8 +112,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Overwrite: !noOverwrite, }, feedback.TaskProgress()) if err != nil { - feedback.Errorf(tr("Error installing Git Library: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error installing Git Library: %v", err), errorcodes.ErrGeneric) } } return @@ -124,8 +120,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { libRefs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args) if err != nil { - feedback.Errorf(tr("Arguments error: %v"), err) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Arguments error: %v", err), errorcodes.ErrBadArgument) } for _, libRef := range libRefs { @@ -138,8 +133,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { } err := lib.LibraryInstall(context.Background(), libraryInstallRequest, feedback.ProgressBar(), feedback.TaskProgress()) if err != nil { - feedback.Errorf(tr("Error installing %s: %v"), libRef.Name, err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error installing %s: %v", libRef.Name, err), errorcodes.ErrGeneric) } } } diff --git a/cli/lib/list.go b/cli/lib/list.go index c8783da664e..e823a94f6cf 100644 --- a/cli/lib/list.go +++ b/cli/lib/list.go @@ -76,8 +76,7 @@ func List(instance *rpc.Instance, args []string, all bool, updatable bool) { Fqbn: fqbn.String(), }) if err != nil { - feedback.Errorf(tr("Error listing Libraries: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error listing Libraries: %v", err), errorcodes.ErrGeneric) } libs := []*rpc.InstalledLibrary{} diff --git a/cli/lib/search.go b/cli/lib/search.go index 6c75071a3a5..dc5d8474730 100644 --- a/cli/lib/search.go +++ b/cli/lib/search.go @@ -54,8 +54,7 @@ func runSearchCommand(args []string, namesOnly bool) { logrus.Info("Executing `arduino-cli lib search`") if status != nil { - feedback.Errorf(tr("Error creating instance: %v"), status) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating instance: %v", status), errorcodes.ErrGeneric) } if err := commands.UpdateLibrariesIndex( @@ -63,8 +62,7 @@ func runSearchCommand(args []string, namesOnly bool) { &rpc.UpdateLibrariesIndexRequest{Instance: inst}, feedback.ProgressBar(), ); err != nil { - feedback.Errorf(tr("Error updating library index: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error updating library index: %v", err), errorcodes.ErrGeneric) } instance.Init(inst) @@ -74,8 +72,7 @@ func runSearchCommand(args []string, namesOnly bool) { Query: strings.Join(args, " "), }) if err != nil { - feedback.Errorf(tr("Error searching for Libraries: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error searching for Libraries: %v", err), errorcodes.ErrGeneric) } feedback.PrintResult(result{ diff --git a/cli/lib/uninstall.go b/cli/lib/uninstall.go index b3e2124cef3..c3639514bc2 100644 --- a/cli/lib/uninstall.go +++ b/cli/lib/uninstall.go @@ -51,8 +51,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { refs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args) if err != nil { - feedback.Errorf(tr("Invalid argument passed: %v"), err) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) } for _, library := range refs { @@ -62,8 +61,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { Version: library.Version, }, feedback.TaskProgress()) if err != nil { - feedback.Errorf(tr("Error uninstalling %[1]s: %[2]v"), library, err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error uninstalling %[1]s: %[2]v", library, err), errorcodes.ErrGeneric) } } diff --git a/cli/lib/update_index.go b/cli/lib/update_index.go index 6775bd40165..4a178a6fe7f 100644 --- a/cli/lib/update_index.go +++ b/cli/lib/update_index.go @@ -52,7 +52,6 @@ func UpdateIndex(inst *rpc.Instance) { Instance: inst, }, feedback.ProgressBar()) if err != nil { - feedback.Errorf(tr("Error updating library index: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error updating library index: %v", err), errorcodes.ErrGeneric) } } diff --git a/cli/lib/upgrade.go b/cli/lib/upgrade.go index 72631e2de8c..deb1e027424 100644 --- a/cli/lib/upgrade.go +++ b/cli/lib/upgrade.go @@ -17,6 +17,7 @@ package lib import ( "context" + "fmt" "os" "github.com/arduino/arduino-cli/cli/errorcodes" @@ -68,8 +69,7 @@ func Upgrade(instance *rpc.Instance, libraries []string) { } if upgradeErr != nil { - feedback.Errorf("%s: %v", tr("Error upgrading libraries"), upgradeErr) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(fmt.Sprintf("%s: %v", tr("Error upgrading libraries"), upgradeErr), errorcodes.ErrGeneric) } logrus.Info("Done") diff --git a/cli/monitor/monitor.go b/cli/monitor/monitor.go index ce0d5937525..23b3b38090e 100644 --- a/cli/monitor/monitor.go +++ b/cli/monitor/monitor.go @@ -77,8 +77,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { portAddress, portProtocol, err := portArgs.GetPortAddressAndProtocol(instance, nil) if err != nil { - feedback.Error(err) - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, errorcodes.ErrGeneric) } enumerateResp, err := monitor.EnumerateMonitorPortSettings(context.Background(), &rpc.EnumerateMonitorPortSettingsRequest{ @@ -87,8 +86,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { Fqbn: fqbn.String(), }) if err != nil { - feedback.Error(tr("Error getting port settings details: %s", err)) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error getting port settings details: %s", err), errorcodes.ErrGeneric) } if describe { feedback.PrintResult(&detailsResult{Settings: enumerateResp.Settings}) @@ -97,8 +95,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { tty, err := newStdInOutTerminal() if err != nil { - feedback.Error(err) - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, errorcodes.ErrGeneric) } defer tty.Close() @@ -123,8 +120,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { } else { if strings.EqualFold(s.SettingId, k) { if !contains(s.EnumValues, v) { - feedback.Error(tr("invalid port configuration value for %s: %s", k, v)) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("invalid port configuration value for %s: %s", k, v), errorcodes.ErrBadArgument) } setting = s break @@ -132,8 +128,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { } } if setting == nil { - feedback.Error(tr("invalid port configuration: %s", config)) - os.Exit(errorcodes.ErrBadArgument) + feedback.Fatal(tr("invalid port configuration: %s", config), errorcodes.ErrBadArgument) } configuration.Settings = append(configuration.Settings, &rpc.MonitorPortSetting{ SettingId: setting.SettingId, @@ -152,8 +147,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { PortConfiguration: configuration, }) if err != nil { - feedback.Error(err) - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, errorcodes.ErrGeneric) } defer portProxy.Close() diff --git a/cli/sketch/archive.go b/cli/sketch/archive.go index 7e1058584e8..c9b93e5d280 100644 --- a/cli/sketch/archive.go +++ b/cli/sketch/archive.go @@ -78,7 +78,6 @@ func runArchiveCommand(args []string, includeBuildDir bool, overwrite bool) { }) if err != nil { - feedback.Errorf(tr("Error archiving: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error archiving: %v", err), errorcodes.ErrGeneric) } } diff --git a/cli/sketch/new.go b/cli/sketch/new.go index 6726bb67fbe..ec9d840cb2d 100644 --- a/cli/sketch/new.go +++ b/cli/sketch/new.go @@ -54,8 +54,7 @@ func runNewCommand(args []string, overwrite bool) { trimmedSketchName := strings.TrimSuffix(sketchName, globals.MainFileValidExtension) sketchDirPath, err := paths.New(trimmedSketchName).Abs() if err != nil { - feedback.Errorf(tr("Error creating sketch: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating sketch: %v", err), errorcodes.ErrGeneric) } _, err = sk.NewSketch(context.Background(), &rpc.NewSketchRequest{ Instance: nil, @@ -64,8 +63,7 @@ func runNewCommand(args []string, overwrite bool) { Overwrite: overwrite, }) if err != nil { - feedback.Errorf(tr("Error creating sketch: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating sketch: %v", err), errorcodes.ErrGeneric) } feedback.Print(tr("Sketch created in: %s", sketchDirPath)) diff --git a/cli/upload/upload.go b/cli/upload/upload.go index 92c2b083e82..850a222eb91 100644 --- a/cli/upload/upload.go +++ b/cli/upload/upload.go @@ -93,8 +93,7 @@ func runUploadCommand(command *cobra.Command, args []string) { sk, err := sketch.New(sketchPath) if err != nil && importDir == "" && importFile == "" { - feedback.Errorf(tr("Error during Upload: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) } instance, profile := instance.CreateAndInitWithProfile(profileArg.Get(), sketchPath) @@ -110,7 +109,7 @@ func runUploadCommand(command *cobra.Command, args []string) { Protocol: port.Protocol, }) if err != nil { - feedback.Errorf(tr("Error during Upload: %v"), err) + msg := tr("Error during Upload: %v", err) // Check the error type to give the user better feedback on how // to resolve it @@ -129,21 +128,22 @@ func runUploadCommand(command *cobra.Command, args []string) { }) release() + msg += "\n" if platform != nil { - feedback.Errorf(tr("Try running %s", fmt.Sprintf("`%s core install %s`", globals.VersionInfo.Application, platformErr.Platform))) + msg += tr("Try running %s", fmt.Sprintf("`%s core install %s`", globals.VersionInfo.Application, platformErr.Platform)) } else { - feedback.Errorf(tr("Platform %s is not found in any known index\nMaybe you need to add a 3rd party URL?", platformErr.Platform)) + msg += tr("Platform %s is not found in any known index\nMaybe you need to add a 3rd party URL?", platformErr.Platform) } } - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(msg, errorcodes.ErrGeneric) } fields := map[string]string{} if len(userFieldRes.UserFields) > 0 { feedback.Print(tr("Uploading to specified board using %s protocol requires the following info:", port.Protocol)) if f, err := arguments.AskForUserFields(userFieldRes.UserFields); err != nil { - feedback.Errorf("%s: %s", tr("Error getting user input"), err) - os.Exit(errorcodes.ErrGeneric) + msg := fmt.Sprintf("%s: %s", tr("Error getting user input"), err) + feedback.Fatal(msg, errorcodes.ErrGeneric) } else { fields = f } @@ -168,8 +168,7 @@ func runUploadCommand(command *cobra.Command, args []string) { UserFields: fields, } if err := upload.Upload(context.Background(), req, stdOut, stdErr); err != nil { - feedback.Errorf(tr("Error during Upload: %v"), err) - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, errorcodes.ErrGeneric) } feedback.PrintResult(stdIOResult()) } diff --git a/cli/version/version.go b/cli/version/version.go index 384d6d41d8e..18483d69a3e 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -16,6 +16,7 @@ package version import ( + "fmt" "os" "strings" @@ -55,8 +56,7 @@ func runVersionCommand(cmd *cobra.Command, args []string) { currentVersion, err := semver.Parse(globals.VersionInfo.VersionString) if err != nil { - feedback.Errorf("Error parsing current version: %s", err) - os.Exit(errorcodes.ErrGeneric) + feedback.Fatal(fmt.Sprintf("Error parsing current version: %s", err), errorcodes.ErrGeneric) } latestVersion := updater.ForceCheckForUpdate(currentVersion) diff --git a/internal/integrationtest/compile_1/compile_test.go b/internal/integrationtest/compile_1/compile_test.go index 7702ba0e4df..b6229139590 100644 --- a/internal/integrationtest/compile_1/compile_test.go +++ b/internal/integrationtest/compile_1/compile_test.go @@ -1071,7 +1071,7 @@ func compileWithFakeSecureBootCore(t *testing.T, env *integrationtest.Environmen "-v", ) require.Error(t, err) - require.Contains(t, string(stderr), "Flag --sign-key is mandatory when used in conjunction with flag --keys-keychain") + require.Contains(t, string(stderr), "Flag --sign-key is mandatory when used in conjunction with: --keys-keychain, --sign-key, --encrypt-key") // Verifies compilation works with secure boot enabled and when overriding the sign key and encryption key used keysDir := cli.SketchbookDir().Join("keys_dir") diff --git a/internal/integrationtest/config/config_test.go b/internal/integrationtest/config/config_test.go index ba395e210ed..b9f96878feb 100644 --- a/internal/integrationtest/config/config_test.go +++ b/internal/integrationtest/config/config_test.go @@ -177,7 +177,7 @@ func TestInitDestAndConfigFileFlags(t *testing.T) { _, stderr, err := cli.Run("config", "init", "--dest-file", "some_other_path", "--dest-dir", "some_path") require.Error(t, err) - require.Contains(t, string(stderr), "Can't use --dest-file and --dest-dir flags at the same time.") + require.Contains(t, string(stderr), "Can't use the following flags together: --dest-file, --dest-dir") } func TestInitConfigFileFlagAbsolutePath(t *testing.T) { From ad48671664624673b927381cdb0b996a98f7aa68 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 16:30:19 +0100 Subject: [PATCH 17/45] Added output buffers in error messages (if used) --- cli/feedback/feedback.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/feedback/feedback.go b/cli/feedback/feedback.go index bdae6fbb392..62da9c38e3e 100644 --- a/cli/feedback/feedback.go +++ b/cli/feedback/feedback.go @@ -189,11 +189,15 @@ func Fatal(errorMsg string, exitCode int) { } type FatalError struct { - Error string `json:"error"` + Error string `json:"error"` + Output *OutputStreamsResult `json:"output,omitempty"` } res := FatalError{ Error: errorMsg, } + if output := getOutputStreamResult(); !output.Empty() { + res.Output = output + } var d []byte switch format { case JSON: From 05635742e3dd248f2c8422711624100e8ef6d1cc Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 15:52:13 +0100 Subject: [PATCH 18/45] Removed direct access to stdio streams in monitor command --- cli/feedback/terminal.go | 23 ++++++++++++++++++++++- cli/monitor/term.go | 20 ++++++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/cli/feedback/terminal.go b/cli/feedback/terminal.go index 0bba6a55cc4..6eb029f3f39 100644 --- a/cli/feedback/terminal.go +++ b/cli/feedback/terminal.go @@ -19,17 +19,38 @@ import ( "bufio" "errors" "fmt" + "io" "os" "golang.org/x/term" ) +// InteractiveStreams returns the underlying io.Reader and io.Writer to directly stream to +// stdin and stdout. It errors if the selected output format is not Text or the terminal is +// not interactive. +func InteractiveStreams() (io.Reader, io.Writer, error) { + if !formatSelected { + panic("output format not yet selected") + } + if format != Text { + return nil, nil, errors.New(tr("interactive terminal not supported for the '%s' output format", format)) + } + if !isTerminal() { + return nil, nil, errors.New(tr("not running in a terminal")) + } + return os.Stdin, stdOut, nil +} + +func isTerminal() bool { + return term.IsTerminal(int(os.Stdin.Fd())) +} + // InputUserField prompts the user to input the provided user field. func InputUserField(prompt string, secret bool) (string, error) { if format != Text { return "", errors.New(tr("user input not supported for the '%s' output format", format)) } - if !term.IsTerminal(int(os.Stdin.Fd())) { + if !isTerminal() { return "", errors.New(tr("user input not supported in non interactive mode")) } diff --git a/cli/monitor/term.go b/cli/monitor/term.go index 31b1362eff5..0939e4bcb8c 100644 --- a/cli/monitor/term.go +++ b/cli/monitor/term.go @@ -16,14 +16,26 @@ package monitor import ( - "os" + "io" + + "github.com/arduino/arduino-cli/cli/feedback" ) type stdInOut struct { + in io.Reader + out io.Writer } func newStdInOutTerminal() (*stdInOut, error) { - return &stdInOut{}, nil + in, out, err := feedback.InteractiveStreams() + if err != nil { + return nil, err + } + + return &stdInOut{ + in: in, + out: out, + }, nil } func (n *stdInOut) Close() error { @@ -31,9 +43,9 @@ func (n *stdInOut) Close() error { } func (n *stdInOut) Read(buff []byte) (int, error) { - return os.Stdin.Read(buff) + return n.in.Read(buff) } func (n *stdInOut) Write(buff []byte) (int, error) { - return os.Stdout.Write(buff) + return n.out.Write(buff) } From 206370a640cfcec0d221862ba5868b587bad7adb Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 15:53:41 +0100 Subject: [PATCH 19/45] Removed direct access to stdio streams in debug command --- cli/debug/debug.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/debug/debug.go b/cli/debug/debug.go index b9e99f3904a..9b13edfd632 100644 --- a/cli/debug/debug.go +++ b/cli/debug/debug.go @@ -102,7 +102,11 @@ func runDebugCommand(command *cobra.Command, args []string) { ctrlc := make(chan os.Signal, 1) signal.Notify(ctrlc, os.Interrupt) - if _, err := debug.Debug(context.Background(), debugConfigRequested, os.Stdin, os.Stdout, ctrlc); err != nil { + in, out, err := feedback.InteractiveStreams() + if err != nil { + feedback.FatalError(err, errorcodes.ErrBadArgument) + } + if _, err := debug.Debug(context.Background(), debugConfigRequested, in, out, ctrlc); err != nil { feedback.Fatal(tr("Error during Debug: %v", err), errorcodes.ErrGeneric) } From 43d388940b3c988a13054a7096b1c014e240aa04 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 16:08:26 +0100 Subject: [PATCH 20/45] Removed direct access to stdio streams in daemon command --- cli/daemon/daemon.go | 9 ++++++++- cli/daemon/interceptors.go | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index 1c93a1c08b5..e3b4bce863e 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -89,8 +89,15 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { if err != nil { feedback.Fatal(tr("Error opening debug logging file: %s", err), errorcodes.ErrBadCall) } - debugStdOut = f defer f.Close() + debugStdOut = f + } else { + // Attach to os.Stdout only if we are in Text mode + if feedback.GetFormat() != feedback.Text { + feedback.Fatal(tr("Debug log is only available in text format"), errorcodes.ErrBadArgument) + } + out, _, _ := feedback.OutputStreams() + debugStdOut = out } gRPCOptions = append(gRPCOptions, grpc.UnaryInterceptor(unaryLoggerInterceptor), diff --git a/cli/daemon/interceptors.go b/cli/daemon/interceptors.go index 11272d72915..0da2307b1aa 100644 --- a/cli/daemon/interceptors.go +++ b/cli/daemon/interceptors.go @@ -19,14 +19,14 @@ import ( "context" "encoding/json" "fmt" - "os" + "io" "strings" "sync/atomic" "google.golang.org/grpc" ) -var debugStdOut = os.Stdout +var debugStdOut io.Writer var debugSeq uint32 func log(isRequest bool, seq uint32, msg interface{}) { From a8c0121604bcaf4ae5bd65df10db4a48dddd8bc2 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 16:09:37 +0100 Subject: [PATCH 21/45] Removed direct access to stdio streams in burn-bootlodaer command --- cli/burnbootloader/burnbootloader.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cli/burnbootloader/burnbootloader.go b/cli/burnbootloader/burnbootloader.go index 0f35e6ea6ea..50655c291ae 100644 --- a/cli/burnbootloader/burnbootloader.go +++ b/cli/burnbootloader/burnbootloader.go @@ -73,6 +73,7 @@ func runBootloaderCommand(command *cobra.Command, args []string) { feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) } + stdOut, stdErr, res := feedback.OutputStreams() if _, err := upload.BurnBootloader(context.Background(), &rpc.BurnBootloaderRequest{ Instance: instance, Fqbn: fqbn.String(), @@ -81,8 +82,8 @@ func runBootloaderCommand(command *cobra.Command, args []string) { Verify: verify, Programmer: programmer.String(), DryRun: dryRun, - }, os.Stdout, os.Stderr); err != nil { + }, stdOut, stdErr); err != nil { feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) } - os.Exit(0) + feedback.PrintResult(res()) } From 94faeab775d5a694ceeef7b8df288a1a8a3fa8e6 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 16:26:55 +0100 Subject: [PATCH 22/45] Removed direct access to stdio streams in compile command --- cli/compile/compile.go | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/cli/compile/compile.go b/cli/compile/compile.go index a5997ec7fc2..a0b0d7b13a8 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -16,7 +16,6 @@ package compile import ( - "bytes" "context" "encoding/json" "errors" @@ -218,16 +217,9 @@ func runCompileCommand(cmd *cobra.Command, args []string) { EncryptKey: encryptKey, SkipLibrariesDiscovery: skipLibrariesDiscovery, } - compileStdOut := new(bytes.Buffer) - compileStdErr := new(bytes.Buffer) + stdOut, stdErr, stdIORes := feedback.OutputStreams() verboseCompile := configuration.Settings.GetString("logging.level") == "debug" - var compileRes *rpc.CompileResponse - var compileError error - if feedback.GetFormat() == feedback.JSON { - compileRes, compileError = compile.Compile(context.Background(), compileRequest, compileStdOut, compileStdErr, nil, verboseCompile) - } else { - compileRes, compileError = compile.Compile(context.Background(), compileRequest, os.Stdout, os.Stderr, nil, verboseCompile) - } + compileRes, compileError := compile.Compile(context.Background(), compileRequest, stdOut, stdErr, nil, verboseCompile) if compileError == nil && uploadAfterCompile { userFieldRes, err := upload.SupportedUserFields(context.Background(), &rpc.SupportedUserFieldsRequest{ @@ -261,17 +253,8 @@ func runCompileCommand(cmd *cobra.Command, args []string) { UserFields: fields, } - var uploadError error - if feedback.GetFormat() == feedback.JSON { - // TODO: do not print upload output in json mode - uploadStdOut := new(bytes.Buffer) - uploadStdErr := new(bytes.Buffer) - uploadError = upload.Upload(context.Background(), uploadRequest, uploadStdOut, uploadStdErr) - } else { - uploadError = upload.Upload(context.Background(), uploadRequest, os.Stdout, os.Stderr) - } - if uploadError != nil { - feedback.Fatal(tr("Error during Upload: %v", uploadError), errorcodes.ErrGeneric) + if err := upload.Upload(context.Background(), uploadRequest, stdOut, stdErr); err != nil { + feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) } } @@ -323,9 +306,10 @@ func runCompileCommand(cmd *cobra.Command, args []string) { } } + stdIO := stdIORes() feedback.PrintResult(&compileResult{ - CompileOut: compileStdOut.String(), - CompileErr: compileStdErr.String(), + CompilerOut: stdIO.Stdout, + CompilerErr: stdIO.Stderr, BuilderResult: compileRes, Success: compileError == nil, }) @@ -364,8 +348,8 @@ func runCompileCommand(cmd *cobra.Command, args []string) { } type compileResult struct { - CompileOut string `json:"compiler_out"` - CompileErr string `json:"compiler_err"` + CompilerOut string `json:"compiler_out"` + CompilerErr string `json:"compiler_err"` BuilderResult *rpc.CompileResponse `json:"builder_result"` Success bool `json:"success"` } From c2fb4b0f9e329534faed162ebade931431599c44 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 16:38:30 +0100 Subject: [PATCH 23/45] Removed direct access to stdio streams in completion command --- cli/completion/completion.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cli/completion/completion.go b/cli/completion/completion.go index ad76ada3996..b0e24093106 100644 --- a/cli/completion/completion.go +++ b/cli/completion/completion.go @@ -48,22 +48,24 @@ func NewCommand() *cobra.Command { } func runCompletionCommand(cmd *cobra.Command, args []string) { + stdOut, _, res := feedback.OutputStreams() logrus.Info("Executing `arduino-cli completion`") if completionNoDesc && (args[0] == "powershell") { feedback.Fatal(tr("Error: command description is not supported by %v", args[0]), errorcodes.ErrGeneric) } switch args[0] { case "bash": - cmd.Root().GenBashCompletionV2(os.Stdout, !completionNoDesc) + cmd.Root().GenBashCompletionV2(stdOut, !completionNoDesc) case "zsh": if completionNoDesc { - cmd.Root().GenZshCompletionNoDesc(os.Stdout) + cmd.Root().GenZshCompletionNoDesc(stdOut) } else { - cmd.Root().GenZshCompletion(os.Stdout) + cmd.Root().GenZshCompletion(stdOut) } case "fish": - cmd.Root().GenFishCompletion(os.Stdout, !completionNoDesc) + cmd.Root().GenFishCompletion(stdOut, !completionNoDesc) case "powershell": - cmd.Root().GenPowerShellCompletion(os.Stdout) + cmd.Root().GenPowerShellCompletion(stdOut) } + feedback.PrintResult(res()) } From 9ae0d3939cdbd0c64991d8bec9b66f2af89253f2 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 6 Dec 2022 17:15:27 +0100 Subject: [PATCH 24/45] compile: print platforms stats only if present --- cli/compile/compile.go | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/cli/compile/compile.go b/cli/compile/compile.go index a0b0d7b13a8..c43370a536f 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -380,24 +380,25 @@ func (r *compileResult) String() string { } res += libraries.Render() + "\n" - platforms := table.New() - platforms.SetHeader( - table.NewCell(tr("Used platform"), titleColor), - table.NewCell(tr("Version"), titleColor), - table.NewCell(tr("Path"), pathColor)) - boardPlatform := build.GetBoardPlatform() - platforms.AddRow( - table.NewCell(boardPlatform.GetId(), nameColor), - boardPlatform.GetVersion(), - table.NewCell(boardPlatform.GetInstallDir(), pathColor)) - if buildPlatform := build.GetBuildPlatform(); buildPlatform != nil && - buildPlatform.Id != boardPlatform.Id && - buildPlatform.Version != boardPlatform.Version { + if boardPlatform := build.GetBoardPlatform(); boardPlatform != nil { + platforms := table.New() + platforms.SetHeader( + table.NewCell(tr("Used platform"), titleColor), + table.NewCell(tr("Version"), titleColor), + table.NewCell(tr("Path"), pathColor)) platforms.AddRow( - table.NewCell(buildPlatform.GetId(), nameColor), - buildPlatform.GetVersion(), - table.NewCell(buildPlatform.GetInstallDir(), pathColor)) + table.NewCell(boardPlatform.GetId(), nameColor), + boardPlatform.GetVersion(), + table.NewCell(boardPlatform.GetInstallDir(), pathColor)) + if buildPlatform := build.GetBuildPlatform(); buildPlatform != nil && + buildPlatform.Id != boardPlatform.Id && + buildPlatform.Version != boardPlatform.Version { + platforms.AddRow( + table.NewCell(buildPlatform.GetId(), nameColor), + buildPlatform.GetVersion(), + table.NewCell(buildPlatform.GetInstallDir(), pathColor)) + } + res += platforms.Render() } - res += platforms.Render() return res } From f64b08b2cb4833ae1f861dfcbf2f3a3157349972 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 7 Dec 2022 11:52:27 +0100 Subject: [PATCH 25/45] Removed direct access to stdio streams in --dump-profile command --- cli/compile/compile.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/cli/compile/compile.go b/cli/compile/compile.go index c43370a536f..151ad31b379 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -281,29 +281,36 @@ func runCompileCommand(cmd *cobra.Command, args []string) { if split := strings.Split(compileRequest.GetFqbn(), ":"); len(split) > 2 { newProfileName = split[2] } - fmt.Println() - fmt.Println("profiles:") - fmt.Println(" " + newProfileName + ":") - fmt.Println(" fqbn: " + compileRequest.GetFqbn()) - fmt.Println(" platforms:") + profile := fmt.Sprintln() + profile += fmt.Sprintln("profiles:") + profile += fmt.Sprintln(" " + newProfileName + ":") + profile += fmt.Sprintln(" fqbn: " + compileRequest.GetFqbn()) + profile += fmt.Sprintln(" platforms:") boardPlatform := compileRes.GetBoardPlatform() - fmt.Println(" - platform: " + boardPlatform.GetId() + " (" + boardPlatform.GetVersion() + ")") + profile += fmt.Sprintln(" - platform: " + boardPlatform.GetId() + " (" + boardPlatform.GetVersion() + ")") if url := boardPlatform.GetPackageUrl(); url != "" { - fmt.Println(" platform_index_url: " + url) + profile += fmt.Sprintln(" platform_index_url: " + url) } if buildPlatform := compileRes.GetBuildPlatform(); buildPlatform != nil && buildPlatform.Id != boardPlatform.Id && buildPlatform.Version != boardPlatform.Version { - fmt.Println(" - platform: " + buildPlatform.GetId() + " (" + buildPlatform.GetVersion() + ")") + profile += fmt.Sprintln(" - platform: " + buildPlatform.GetId() + " (" + buildPlatform.GetVersion() + ")") if url := buildPlatform.GetPackageUrl(); url != "" { - fmt.Println(" platform_index_url: " + url) + profile += fmt.Sprintln(" platform_index_url: " + url) } } if len(libs) > 0 { - fmt.Println(" libraries:") - fmt.Print(libs) + profile += fmt.Sprintln(" libraries:") + profile += fmt.Sprint(libs) } + + // Output profile as a result + if _, err := stdOut.Write([]byte(profile)); err != nil { + feedback.FatalError(err, errorcodes.ErrGeneric) + } + feedback.PrintResult(stdIORes()) + os.Exit(0) } stdIO := stdIORes() From bbc2a50b091335504220b4b9d03f2cf5477ff99d Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 7 Dec 2022 12:42:30 +0100 Subject: [PATCH 26/45] Added feedback functions to report warnings --- cli/arguments/sketch.go | 7 +++-- cli/board/list.go | 4 +-- cli/compile/compile.go | 7 +++-- cli/core/upgrade.go | 11 +++---- cli/feedback/feedback.go | 56 +++++++++++++++++++--------------- cli/instance/instance.go | 6 ++-- cli/monitor/monitor.go | 8 +++-- cli/updater/updater.go | 4 ++- configuration/configuration.go | 10 +++--- 9 files changed, 64 insertions(+), 49 deletions(-) diff --git a/cli/arguments/sketch.go b/cli/arguments/sketch.go index 922d4f32817..d1e014e6d8c 100644 --- a/cli/arguments/sketch.go +++ b/cli/arguments/sketch.go @@ -16,6 +16,8 @@ package arguments import ( + "fmt" + "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" @@ -54,9 +56,10 @@ func NewSketch(sketchPath *paths.Path) *sketch.Sketch { func WarnDeprecatedFiles(sketchPath *paths.Path) { // .pde files are still supported but deprecated, this warning urges the user to rename them if files := sketch.CheckForPdeFiles(sketchPath); len(files) > 0 { - feedback.Error(tr("Sketches with .pde extension are deprecated, please rename the following files to .ino:")) + msg := tr("Sketches with .pde extension are deprecated, please rename the following files to .ino:") for _, f := range files { - feedback.Error(f) + msg += fmt.Sprintf("\n - %s", f) } + feedback.Warning(msg) } } diff --git a/cli/board/list.go b/cli/board/list.go index 4b412d9cb86..0253334d230 100644 --- a/cli/board/list.go +++ b/cli/board/list.go @@ -69,10 +69,10 @@ func runListCommand(cmd *cobra.Command, args []string) { Timeout: timeoutArg.Get().Milliseconds(), }) if err != nil { - feedback.Errorf(tr("Error detecting boards: %v"), err) + feedback.Warning(tr("Error detecting boards: %v", err)) } for _, err := range discvoeryErrors { - feedback.Errorf(tr("Error starting discovery: %v"), err) + feedback.Warning(tr("Error starting discovery: %v", err)) } feedback.PrintResult(result{ports}) } diff --git a/cli/compile/compile.go b/cli/compile/compile.go index 151ad31b379..75ff5bc3707 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -272,9 +272,10 @@ func runCompileCommand(cmd *cobra.Command, args []string) { libs += fmt.Sprintln(" - " + lib.GetName() + " (" + lib.GetVersion() + ")") } if hasVendoredLibs { - fmt.Println() - fmt.Println(tr("WARNING: The sketch is compiled using one or more custom libraries.")) - fmt.Println(tr("Currently, Build Profiles only support libraries available through Arduino Library Manager.")) + msg := "\n" + msg += tr("WARNING: The sketch is compiled using one or more custom libraries.") + "\n" + msg += tr("Currently, Build Profiles only support libraries available through Arduino Library Manager.") + feedback.Warning(msg) } newProfileName := "my_profile_name" diff --git a/cli/core/upgrade.go b/cli/core/upgrade.go index d9bf23ca293..d76d5bc15d9 100644 --- a/cli/core/upgrade.go +++ b/cli/core/upgrade.go @@ -80,16 +80,16 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { } // proceed upgrading, if anything is upgradable - exitErr := false platformsRefs, err := arguments.ParseReferences(args) if err != nil { feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) } + hasBadArguments := false for i, platformRef := range platformsRefs { if platformRef.Version != "" { - feedback.Errorf(tr("Invalid item %s"), args[i]) - exitErr = true + feedback.Warning(tr("Invalid item %s", args[i])) + hasBadArguments = true continue } @@ -99,7 +99,6 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { Architecture: platformRef.Architecture, SkipPostInstall: skipPostInstall, } - if _, err := core.PlatformUpgrade(context.Background(), r, feedback.ProgressBar(), feedback.TaskProgress()); err != nil { if errors.Is(err, &arduino.PlatformAlreadyAtTheLatestVersionError{}) { feedback.Print(err.Error()) @@ -110,7 +109,7 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { } } - if exitErr { - os.Exit(errorcodes.ErrBadArgument) + if hasBadArguments { + feedback.Fatal(tr("Some upgrades failed, please check the output for details."), errorcodes.ErrBadArgument) } } diff --git a/cli/feedback/feedback.go b/cli/feedback/feedback.go index 62da9c38e3e..2c56f892ebd 100644 --- a/cli/feedback/feedback.go +++ b/cli/feedback/feedback.go @@ -20,7 +20,6 @@ package feedback import ( "bytes" "encoding/json" - "errors" "fmt" "io" "os" @@ -28,7 +27,6 @@ import ( "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/i18n" "github.com/sirupsen/logrus" - "google.golang.org/grpc/status" "gopkg.in/yaml.v2" ) @@ -76,6 +74,7 @@ var ( feedbackErr io.Writer bufferOut *bytes.Buffer bufferErr *bytes.Buffer + bufferWarnings []string format OutputFormat formatSelected bool ) @@ -92,6 +91,7 @@ func reset() { feedbackErr = os.Stderr bufferOut = &bytes.Buffer{} bufferErr = &bytes.Buffer{} + bufferWarnings = nil format = Text formatSelected = false } @@ -135,6 +135,7 @@ func SetFormat(f OutputFormat) { } else { feedbackOut = bufferOut feedbackErr = bufferErr + bufferWarnings = nil } } @@ -153,27 +154,14 @@ func Print(v string) { fmt.Fprintln(feedbackOut, v) } -// Errorf behaves like fmt.Printf but writes on the error writer and adds a -// newline. It also logs the error. -func Errorf(format string, v ...interface{}) { - // Unbox grpc status errors - for i := range v { - if s, isStatus := v[i].(*status.Status); isStatus { - v[i] = errors.New(s.Message()) - } else if err, isErr := v[i].(error); isErr { - if s, isStatus := status.FromError(err); isStatus { - v[i] = errors.New(s.Message()) - } - } +// Warning outputs a warning message. +func Warning(msg string) { + if format == Text { + fmt.Fprintln(feedbackErr, msg) + } else { + bufferWarnings = append(bufferWarnings, msg) } - Error(fmt.Sprintf(format, v...)) -} - -// Error behaves like fmt.Print but writes on the error writer and adds a -// newline. It also logs the error. -func Error(v ...interface{}) { - fmt.Fprintln(stdErr, v...) - logrus.Error(fmt.Sprint(v...)) + logrus.Warning(msg) } // FatalError outputs the error and exits with status exitCode. @@ -213,6 +201,24 @@ func Fatal(errorMsg string, exitCode int) { os.Exit(exitCode) } +func augment(data interface{}) interface{} { + if len(bufferWarnings) == 0 { + return data + } + d, err := json.Marshal(data) + if err != nil { + return data + } + var res interface{} + if err := json.Unmarshal(d, &res); err != nil { + return data + } + if m, ok := res.(map[string]interface{}); ok { + m["warnings"] = bufferWarnings + } + return res +} + // PrintResult is a convenient wrapper to provide feedback for complex data, // where the contents can't be just serialized to JSON but requires more // structure. @@ -220,19 +226,19 @@ func PrintResult(res Result) { var data string switch format { case JSON: - d, err := json.MarshalIndent(res.Data(), "", " ") + d, err := json.MarshalIndent(augment(res.Data()), "", " ") if err != nil { Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), errorcodes.ErrGeneric) } data = string(d) case MinifiedJSON: - d, err := json.Marshal(res.Data()) + d, err := json.Marshal(augment(res.Data())) if err != nil { Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), errorcodes.ErrGeneric) } data = string(d) case YAML: - d, err := yaml.Marshal(res.Data()) + d, err := yaml.Marshal(augment(res.Data())) if err != nil { Fatal(fmt.Sprintf("Error during YAML encoding of the output: %v", err), errorcodes.ErrGeneric) } diff --git a/cli/instance/instance.go b/cli/instance/instance.go index 3e9fce7afc0..df6bb57b91f 100644 --- a/cli/instance/instance.go +++ b/cli/instance/instance.go @@ -74,7 +74,7 @@ func Init(instance *rpc.Instance) { func InitWithProfile(instance *rpc.Instance, profileName string, sketchPath *paths.Path) *rpc.Profile { // In case the CLI is executed for the first time if err := FirstUpdate(instance); err != nil { - feedback.Errorf(tr("Error initializing instance: %v"), err) + feedback.Warning(tr("Error initializing instance: %v", err)) return nil } @@ -89,7 +89,7 @@ func InitWithProfile(instance *rpc.Instance, profileName string, sketchPath *pat var profile *rpc.Profile err := commands.Init(initReq, func(res *rpc.InitResponse) { if st := res.GetError(); st != nil { - feedback.Errorf(tr("Error initializing instance: %v"), st.Message) + feedback.Warning(tr("Error initializing instance: %v", st.Message)) } if progress := res.GetInitProgress(); progress != nil { @@ -106,7 +106,7 @@ func InitWithProfile(instance *rpc.Instance, profileName string, sketchPath *pat } }) if err != nil { - feedback.Errorf(tr("Error initializing instance: %v"), err) + feedback.Warning(tr("Error initializing instance: %v", err)) } return profile diff --git a/cli/monitor/monitor.go b/cli/monitor/monitor.go index 23b3b38090e..73f0193b851 100644 --- a/cli/monitor/monitor.go +++ b/cli/monitor/monitor.go @@ -155,14 +155,18 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { go func() { _, err := io.Copy(tty, portProxy) if err != nil && !errors.Is(err, io.EOF) { - feedback.Error(tr("Port closed:"), err) + if !quiet { + feedback.Print(tr("Port closed: %v", err)) + } } cancel() }() go func() { _, err := io.Copy(portProxy, tty) if err != nil && !errors.Is(err, io.EOF) { - feedback.Error(tr("Port closed:"), err) + if !quiet { + feedback.Print(tr("Port closed: %v", err)) + } } cancel() }() diff --git a/cli/updater/updater.go b/cli/updater/updater.go index b6f5372ea77..7cf7220d955 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -16,6 +16,7 @@ package updater import ( + "fmt" "os" "strings" "time" @@ -66,11 +67,12 @@ func ForceCheckForUpdate(currentVersion *semver.Version) *semver.Version { // NotifyNewVersionIsAvailable prints information about the new latestVersion func NotifyNewVersionIsAvailable(latestVersion string) { - feedback.Errorf("\n\n%s %s → %s\n%s", + msg := fmt.Sprintf("\n\n%s %s → %s\n%s", color.YellowString(tr("A new release of Arduino CLI is available:")), color.CyanString(globals.VersionInfo.VersionString), color.CyanString(latestVersion), color.YellowString("https://arduino.github.io/arduino-cli/latest/installation/#latest-packages")) + feedback.Warning(msg) } // shouldCheckForUpdate return true if it actually makes sense to check for new updates, diff --git a/configuration/configuration.go b/configuration/configuration.go index 3b22e0eb3c6..cc742146cd9 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -65,7 +65,7 @@ func Init(configFile string) *viper.Viper { // ConfigFileNotFoundError is acceptable, anything else // should be reported to the user if _, ok := err.(viper.ConfigFileNotFoundError); !ok { - feedback.Errorf(tr("Error reading config file: %v"), err) + feedback.Warning(tr("Error reading config file: %v", err)) } } @@ -85,7 +85,7 @@ func BindFlags(cmd *cobra.Command, settings *viper.Viper) { func getDefaultArduinoDataDir() string { userHomeDir, err := os.UserHomeDir() if err != nil { - feedback.Errorf(tr("Unable to get user home dir: %v"), err) + feedback.Warning(tr("Unable to get user home dir: %v", err)) return "." } @@ -97,7 +97,7 @@ func getDefaultArduinoDataDir() string { case "windows": localAppDataPath, err := win32.GetLocalAppDataFolder() if err != nil { - feedback.Errorf(tr("Unable to get Local App Data Folder: %v"), err) + feedback.Warning(tr("Unable to get Local App Data Folder: %v", err)) return "." } return filepath.Join(localAppDataPath, "Arduino15") @@ -110,7 +110,7 @@ func getDefaultArduinoDataDir() string { func getDefaultUserDir() string { userHomeDir, err := os.UserHomeDir() if err != nil { - feedback.Errorf(tr("Unable to get user home dir: %v"), err) + feedback.Warning(tr("Unable to get user home dir: %v", err)) return "." } @@ -122,7 +122,7 @@ func getDefaultUserDir() string { case "windows": documentsPath, err := win32.GetDocumentsFolder() if err != nil { - feedback.Errorf(tr("Unable to get Documents Folder: %v"), err) + feedback.Warning(tr("Unable to get Documents Folder: %v", err)) return "." } return filepath.Join(documentsPath, "Arduino") From 2d0d667713a32d7a6b8ac87378d749e814986817 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 9 Dec 2022 10:56:44 +0100 Subject: [PATCH 27/45] Moved `errorcodes` into `feedback` --- cli/arguments/arguments.go | 5 ++-- cli/arguments/fqbn.go | 7 +++-- cli/arguments/port.go | 7 +++-- cli/arguments/sketch.go | 5 ++-- cli/board/attach.go | 5 ++-- cli/board/details.go | 3 +-- cli/board/list.go | 3 +-- cli/board/listall.go | 3 +-- cli/board/search.go | 3 +-- cli/burnbootloader/burnbootloader.go | 5 ++-- cli/cache/clean.go | 3 +-- cli/cli.go | 11 ++++---- cli/compile/compile.go | 21 ++++++++------- cli/completion/completion.go | 3 +-- cli/config/add.go | 5 ++-- cli/config/delete.go | 5 ++-- cli/config/init.go | 11 ++++---- cli/config/remove.go | 5 ++-- cli/config/set.go | 7 +++-- cli/config/validate.go | 3 +-- cli/core/download.go | 5 ++-- cli/core/install.go | 5 ++-- cli/core/list.go | 3 +-- cli/core/search.go | 9 +++---- cli/core/uninstall.go | 7 +++-- cli/core/update_index.go | 3 +-- cli/core/upgrade.go | 9 +++---- cli/daemon/daemon.go | 17 ++++++------ cli/debug/debug.go | 7 +++-- cli/{errorcodes => feedback}/errorcodes.go | 30 ++++++++++++++++------ cli/feedback/feedback.go | 15 +++++------ cli/feedback/feedback_cmd.go | 7 +++-- cli/generatedocs/generatedocs.go | 6 ++--- cli/instance/instance.go | 7 +++-- cli/lib/check_deps.go | 5 ++-- cli/lib/download.go | 5 ++-- cli/lib/examples.go | 3 +-- cli/lib/install.go | 13 +++++----- cli/lib/list.go | 3 +-- cli/lib/search.go | 7 +++-- cli/lib/uninstall.go | 5 ++-- cli/lib/update_index.go | 3 +-- cli/lib/upgrade.go | 3 +-- cli/monitor/monitor.go | 13 +++++----- cli/sketch/archive.go | 3 +-- cli/sketch/new.go | 5 ++-- cli/upload/upload.go | 9 +++---- cli/version/version.go | 3 +-- main.go | 4 +-- 49 files changed, 151 insertions(+), 183 deletions(-) rename cli/{errorcodes => feedback}/errorcodes.go (59%) diff --git a/cli/arguments/arguments.go b/cli/arguments/arguments.go index 9e028670814..5526d30a6d3 100644 --- a/cli/arguments/arguments.go +++ b/cli/arguments/arguments.go @@ -18,7 +18,6 @@ package arguments import ( "strings" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/i18n" "github.com/spf13/cobra" @@ -35,7 +34,7 @@ func CheckFlagsConflicts(command *cobra.Command, flagNames ...string) { } flags := "--" + strings.Join(flagNames, ", --") msg := tr("Can't use the following flags together: %s", flags) - feedback.Fatal(msg, errorcodes.ErrBadArgument) + feedback.Fatal(msg, feedback.ErrBadArgument) } // CheckFlagsMandatory is a helper function useful to report errors when at least one flag is not used in a group of "required" flags @@ -46,6 +45,6 @@ func CheckFlagsMandatory(command *cobra.Command, flagNames ...string) { } flags := "--" + strings.Join(flagNames, ", --") msg := tr("Flag %[1]s is mandatory when used in conjunction with: %[2]s", "--"+flagName, flags) - feedback.Fatal(msg, errorcodes.ErrBadArgument) + feedback.Fatal(msg, feedback.ErrBadArgument) } } diff --git a/cli/arguments/fqbn.go b/cli/arguments/fqbn.go index 8004c6a9a05..973aa0aa3ac 100644 --- a/cli/arguments/fqbn.go +++ b/cli/arguments/fqbn.go @@ -20,7 +20,6 @@ import ( "github.com/arduino/arduino-cli/arduino" "github.com/arduino/arduino-cli/arduino/sketch" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/spf13/cobra" @@ -80,18 +79,18 @@ func CalculateFQBNAndPort(portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance, } if fqbn == "" { if portArgs == nil || portArgs.address == "" { - feedback.FatalError(&arduino.MissingFQBNError{}, errorcodes.ErrGeneric) + feedback.FatalError(&arduino.MissingFQBNError{}, feedback.ErrGeneric) } fqbn, port := portArgs.DetectFQBN(instance) if fqbn == "" { - feedback.FatalError(&arduino.MissingFQBNError{}, errorcodes.ErrGeneric) + feedback.FatalError(&arduino.MissingFQBNError{}, feedback.ErrGeneric) } return fqbn, port } port, err := portArgs.GetPort(instance, sk) if err != nil { - feedback.Fatal(tr("Error getting port metadata: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error getting port metadata: %v", err), feedback.ErrGeneric) } return fqbn, port.ToRPC() } diff --git a/cli/arguments/port.go b/cli/arguments/port.go index d52b9f46488..94c62088bf7 100644 --- a/cli/arguments/port.go +++ b/cli/arguments/port.go @@ -22,7 +22,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/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/board" @@ -146,7 +145,7 @@ func (p *Port) DetectFQBN(inst *rpc.Instance) (string, *rpc.Port) { Timeout: p.timeout.Get().Milliseconds(), }) if err != nil { - feedback.Fatal(tr("Error during FQBN detection: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during FQBN detection: %v", err), feedback.ErrGeneric) } for _, detectedPort := range detectedPorts { port := detectedPort.GetPort() @@ -157,10 +156,10 @@ func (p *Port) DetectFQBN(inst *rpc.Instance) (string, *rpc.Port) { continue } if len(detectedPort.MatchingBoards) > 1 { - feedback.FatalError(&arduino.MultipleBoardsDetectedError{Port: port}, errorcodes.ErrBadArgument) + feedback.FatalError(&arduino.MultipleBoardsDetectedError{Port: port}, feedback.ErrBadArgument) } if len(detectedPort.MatchingBoards) == 0 { - feedback.FatalError(&arduino.NoBoardsDetectedError{Port: port}, errorcodes.ErrBadArgument) + feedback.FatalError(&arduino.NoBoardsDetectedError{Port: port}, feedback.ErrBadArgument) } return detectedPort.MatchingBoards[0].Fqbn, port } diff --git a/cli/arguments/sketch.go b/cli/arguments/sketch.go index d1e014e6d8c..40a85a0ed87 100644 --- a/cli/arguments/sketch.go +++ b/cli/arguments/sketch.go @@ -19,7 +19,6 @@ import ( "fmt" "github.com/arduino/arduino-cli/arduino/sketch" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" @@ -34,7 +33,7 @@ func InitSketchPath(path string) (sketchPath *paths.Path) { } else { wd, err := paths.Getwd() if err != nil { - feedback.Fatal(tr("Couldn't get current working directory: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Couldn't get current working directory: %v", err), feedback.ErrGeneric) } logrus.Infof("Reading sketch from dir: %s", wd) sketchPath = wd @@ -47,7 +46,7 @@ func InitSketchPath(path string) (sketchPath *paths.Path) { func NewSketch(sketchPath *paths.Path) *sketch.Sketch { sketch, err := sketch.New(sketchPath) if err != nil { - feedback.Fatal(tr("Error opening sketch: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error opening sketch: %v", err), feedback.ErrGeneric) } return sketch } diff --git a/cli/board/attach.go b/cli/board/attach.go index ca50eb97924..46764c3f45a 100644 --- a/cli/board/attach.go +++ b/cli/board/attach.go @@ -20,7 +20,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/spf13/cobra" ) @@ -67,7 +66,7 @@ func runAttachCommand(path string, port *arguments.Port, fqbn string) { 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), errorcodes.ErrGeneric) + feedback.Fatal(fmt.Sprintf("%s: %s", tr("Error saving sketch metadata"), err), feedback.ErrGeneric) } current.Port = &boardAttachPortResult{ Address: address, @@ -76,7 +75,7 @@ func runAttachCommand(path string, port *arguments.Port, fqbn string) { } if fqbn != "" { if err := sk.SetDefaultFQBN(fqbn); err != nil { - feedback.Fatal(fmt.Sprintf("%s: %s", tr("Error saving sketch metadata"), err), errorcodes.ErrGeneric) + feedback.Fatal(fmt.Sprintf("%s: %s", tr("Error saving sketch metadata"), err), feedback.ErrGeneric) } current.Fqbn = fqbn } diff --git a/cli/board/details.go b/cli/board/details.go index ba9de2fa356..98ef0688a68 100644 --- a/cli/board/details.go +++ b/cli/board/details.go @@ -21,7 +21,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/board" @@ -67,7 +66,7 @@ func runDetailsCommand(cmd *cobra.Command, args []string) { }) if err != nil { - feedback.Fatal(tr("Error getting board details: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error getting board details: %v", err), feedback.ErrGeneric) } feedback.PrintResult(detailsResult{details: res}) diff --git a/cli/board/list.go b/cli/board/list.go index 0253334d230..41052ded7b2 100644 --- a/cli/board/list.go +++ b/cli/board/list.go @@ -22,7 +22,6 @@ import ( "github.com/arduino/arduino-cli/arduino/cores" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/board" @@ -80,7 +79,7 @@ func runListCommand(cmd *cobra.Command, args []string) { func watchList(cmd *cobra.Command, inst *rpc.Instance) { eventsChan, closeCB, err := board.Watch(&rpc.BoardListWatchRequest{Instance: inst}) if err != nil { - feedback.Fatal(tr("Error detecting boards: %v", err), errorcodes.ErrNetwork) + feedback.Fatal(tr("Error detecting boards: %v", err), feedback.ErrNetwork) } defer closeCB() diff --git a/cli/board/listall.go b/cli/board/listall.go index 429daf00b11..ce47f31dd22 100644 --- a/cli/board/listall.go +++ b/cli/board/listall.go @@ -21,7 +21,6 @@ import ( "os" "sort" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/board" @@ -61,7 +60,7 @@ func runListAllCommand(cmd *cobra.Command, args []string) { IncludeHiddenBoards: showHiddenBoard, }) if err != nil { - feedback.Fatal(tr("Error listing boards: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error listing boards: %v", err), feedback.ErrGeneric) } feedback.PrintResult(resultAll{list}) diff --git a/cli/board/search.go b/cli/board/search.go index 12cf7499d73..dcbcb053930 100644 --- a/cli/board/search.go +++ b/cli/board/search.go @@ -22,7 +22,6 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/board" @@ -59,7 +58,7 @@ func runSearchCommand(cmd *cobra.Command, args []string) { IncludeHiddenBoards: showHiddenBoard, }) if err != nil { - feedback.Fatal(tr("Error searching boards: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error searching boards: %v", err), feedback.ErrGeneric) } feedback.PrintResult(searchResults{res.Boards}) diff --git a/cli/burnbootloader/burnbootloader.go b/cli/burnbootloader/burnbootloader.go index 50655c291ae..d7bc7319a64 100644 --- a/cli/burnbootloader/burnbootloader.go +++ b/cli/burnbootloader/burnbootloader.go @@ -20,7 +20,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/upload" @@ -70,7 +69,7 @@ func runBootloaderCommand(command *cobra.Command, args []string) { // We don't need a Sketch to upload a board's bootloader discoveryPort, err := port.GetPort(instance, nil) if err != nil { - feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", err), feedback.ErrGeneric) } stdOut, stdErr, res := feedback.OutputStreams() @@ -83,7 +82,7 @@ func runBootloaderCommand(command *cobra.Command, args []string) { Programmer: programmer.String(), DryRun: dryRun, }, stdOut, stdErr); err != nil { - feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", err), feedback.ErrGeneric) } feedback.PrintResult(res()) } diff --git a/cli/cache/clean.go b/cli/cache/clean.go index fddb0e5e3c8..2acb39448de 100644 --- a/cli/cache/clean.go +++ b/cli/cache/clean.go @@ -18,7 +18,6 @@ package cache import ( "os" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" "github.com/sirupsen/logrus" @@ -43,6 +42,6 @@ func runCleanCommand(cmd *cobra.Command, args []string) { cachePath := configuration.DownloadsDir(configuration.Settings) err := cachePath.RemoveAll() if err != nil { - feedback.Fatal(tr("Error cleaning caches: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error cleaning caches: %v", err), feedback.ErrGeneric) } } diff --git a/cli/cli.go b/cli/cli.go index 441e15c0e62..bc593aa2ffe 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -30,7 +30,6 @@ import ( "github.com/arduino/arduino-cli/cli/core" "github.com/arduino/arduino-cli/cli/daemon" "github.com/arduino/arduino-cli/cli/debug" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/generatedocs" "github.com/arduino/arduino-cli/cli/globals" @@ -149,7 +148,7 @@ func preRun(cmd *cobra.Command, args []string) { // initialize inventory err := inventory.Init(configuration.DataDir(configuration.Settings).String()) if err != nil { - feedback.Fatal(fmt.Sprintf("Error: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(fmt.Sprintf("Error: %v", err), feedback.ErrBadArgument) } // https://no-color.org/ @@ -200,7 +199,7 @@ func preRun(cmd *cobra.Command, args []string) { if logFile != "" { file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { - feedback.Fatal(tr("Unable to open file for logging: %s", logFile), errorcodes.ErrBadCall) + feedback.Fatal(tr("Unable to open file for logging: %s", logFile), feedback.ErrGeneric) } // we use a hook so we don't get color codes in the log file @@ -213,7 +212,7 @@ func preRun(cmd *cobra.Command, args []string) { // configure logging filter if lvl, found := toLogLevel(configuration.Settings.GetString("logging.level")); !found { - feedback.Fatal(tr("Invalid option for --log-level: %s", configuration.Settings.GetString("logging.level")), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid option for --log-level: %s", configuration.Settings.GetString("logging.level")), feedback.ErrBadArgument) } else { logrus.SetLevel(lvl) } @@ -225,7 +224,7 @@ func preRun(cmd *cobra.Command, args []string) { // check the right output format was passed format, found := feedback.ParseOutputFormat(outputFormat) if !found { - feedback.Fatal(tr("Invalid output format: %s", outputFormat), errorcodes.ErrBadCall) + feedback.Fatal(tr("Invalid output format: %s", outputFormat), feedback.ErrBadArgument) } // use the output format to configure the Feedback @@ -246,7 +245,7 @@ func preRun(cmd *cobra.Command, args []string) { if outputFormat != "text" { cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { logrus.Warn("Calling help on JSON format") - feedback.Fatal(tr("Invalid Call : should show Help, but it is available only in TEXT mode."), errorcodes.ErrBadCall) + feedback.Fatal(tr("Invalid Call : should show Help, but it is available only in TEXT mode."), feedback.ErrBadArgument) }) } } diff --git a/cli/compile/compile.go b/cli/compile/compile.go index 75ff5bc3707..cffd4f58971 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -35,7 +35,6 @@ import ( "github.com/fatih/color" "github.com/sirupsen/logrus" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/compile" "github.com/arduino/arduino-cli/commands/upload" @@ -147,14 +146,14 @@ func runCompileCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino-cli compile`") if dumpProfile && feedback.GetFormat() != feedback.Text { - feedback.Fatal(tr("You cannot use the %[1]s flag together with %[2]s.", "--dump-profile", "--format json"), errorcodes.ErrBadArgument) + feedback.Fatal(tr("You cannot use the %[1]s flag together with %[2]s.", "--dump-profile", "--format json"), feedback.ErrBadArgument) } if profileArg.Get() != "" { if len(libraries) > 0 { - feedback.Fatal(tr("You cannot use the %s flag while compiling with a profile.", "--libraries"), errorcodes.ErrBadArgument) + feedback.Fatal(tr("You cannot use the %s flag while compiling with a profile.", "--libraries"), feedback.ErrBadArgument) } if len(library) > 0 { - feedback.Fatal(tr("You cannot use the %s flag while compiling with a profile.", "--library"), errorcodes.ErrBadArgument) + feedback.Fatal(tr("You cannot use the %s flag while compiling with a profile.", "--library"), feedback.ErrBadArgument) } } @@ -181,13 +180,13 @@ func runCompileCommand(cmd *cobra.Command, args []string) { if sourceOverrides != "" { data, err := paths.New(sourceOverrides).ReadFile() if err != nil { - feedback.Fatal(tr("Error opening source code overrides data file: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error opening source code overrides data file: %v", err), feedback.ErrGeneric) } var o struct { Overrides map[string]string `json:"overrides"` } if err := json.Unmarshal(data, &o); err != nil { - feedback.Fatal(tr("Error: invalid source code overrides data file: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error: invalid source code overrides data file: %v", err), feedback.ErrGeneric) } overrides = o.Overrides } @@ -228,14 +227,14 @@ func runCompileCommand(cmd *cobra.Command, args []string) { Protocol: port.Protocol, }) if err != nil { - feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", err), feedback.ErrGeneric) } fields := map[string]string{} if len(userFieldRes.UserFields) > 0 { feedback.Print(tr("Uploading to specified board using %s protocol requires the following info:", port.Protocol)) if f, err := arguments.AskForUserFields(userFieldRes.UserFields); err != nil { - feedback.FatalError(err, errorcodes.ErrBadArgument) + feedback.FatalError(err, feedback.ErrBadArgument) } else { fields = f } @@ -254,7 +253,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { } if err := upload.Upload(context.Background(), uploadRequest, stdOut, stdErr); err != nil { - feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", err), feedback.ErrGeneric) } } @@ -308,7 +307,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { // Output profile as a result if _, err := stdOut.Write([]byte(profile)); err != nil { - feedback.FatalError(err, errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } feedback.PrintResult(stdIORes()) os.Exit(0) @@ -351,7 +350,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { } } } - feedback.Fatal(msg, errorcodes.ErrGeneric) + feedback.Fatal(msg, feedback.ErrGeneric) } } diff --git a/cli/completion/completion.go b/cli/completion/completion.go index b0e24093106..92bc4f292c0 100644 --- a/cli/completion/completion.go +++ b/cli/completion/completion.go @@ -18,7 +18,6 @@ package completion import ( "os" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/i18n" "github.com/sirupsen/logrus" @@ -51,7 +50,7 @@ func runCompletionCommand(cmd *cobra.Command, args []string) { stdOut, _, res := feedback.OutputStreams() logrus.Info("Executing `arduino-cli completion`") if completionNoDesc && (args[0] == "powershell") { - feedback.Fatal(tr("Error: command description is not supported by %v", args[0]), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error: command description is not supported by %v", args[0]), feedback.ErrGeneric) } switch args[0] { case "bash": diff --git a/cli/config/add.go b/cli/config/add.go index 39fe2b10b05..171deb287cc 100644 --- a/cli/config/add.go +++ b/cli/config/add.go @@ -19,7 +19,6 @@ import ( "os" "reflect" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" "github.com/sirupsen/logrus" @@ -92,7 +91,7 @@ func runAddCommand(cmd *cobra.Command, args []string) { if kind != reflect.Slice { msg := tr("The key '%[1]v' is not a list of items, can't add to it.\nMaybe use '%[2]s'?", key, "config set") - feedback.Fatal(msg, errorcodes.ErrGeneric) + feedback.Fatal(msg, feedback.ErrGeneric) } v := configuration.Settings.GetStringSlice(key) @@ -101,6 +100,6 @@ func runAddCommand(cmd *cobra.Command, args []string) { configuration.Settings.Set(key, v) if err := configuration.Settings.WriteConfig(); err != nil { - feedback.Fatal(tr("Can't write config file: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Can't write config file: %v", err), feedback.ErrGeneric) } } diff --git a/cli/config/delete.go b/cli/config/delete.go index bce6c7e8098..c5f761dcf53 100644 --- a/cli/config/delete.go +++ b/cli/config/delete.go @@ -19,7 +19,6 @@ import ( "os" "strings" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" "github.com/sirupsen/logrus" @@ -59,7 +58,7 @@ func runDeleteCommand(cmd *cobra.Command, args []string) { } if !exists { - feedback.Fatal(tr("Settings key doesn't exist"), errorcodes.ErrGeneric) + feedback.Fatal(tr("Settings key doesn't exist"), feedback.ErrGeneric) } updatedSettings := viper.New() @@ -68,6 +67,6 @@ func runDeleteCommand(cmd *cobra.Command, args []string) { } if err := updatedSettings.WriteConfigAs(configuration.Settings.ConfigFileUsed()); err != nil { - feedback.Fatal(tr("Can't write config file: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Can't write config file: %v", err), feedback.ErrGeneric) } } diff --git a/cli/config/init.go b/cli/config/init.go index fc856529f28..b38f9d4dc21 100644 --- a/cli/config/init.go +++ b/cli/config/init.go @@ -19,7 +19,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/go-paths-helper" @@ -69,7 +68,7 @@ func runInitCommand(cmd *cobra.Command, args []string) { case destFile != "": configFileAbsPath, err = paths.New(destFile).Abs() if err != nil { - feedback.Fatal(tr("Cannot find absolute path: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Cannot find absolute path: %v", err), feedback.ErrGeneric) } absPath = configFileAbsPath.Parent() @@ -79,19 +78,19 @@ func runInitCommand(cmd *cobra.Command, args []string) { default: absPath, err = paths.New(destDir).Abs() if err != nil { - feedback.Fatal(tr("Cannot find absolute path: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Cannot find absolute path: %v", err), feedback.ErrGeneric) } configFileAbsPath = absPath.Join(defaultFileName) } if !overwrite && configFileAbsPath.Exist() { - feedback.Fatal(tr("Config file already exists, use --overwrite to discard the existing one."), errorcodes.ErrGeneric) + feedback.Fatal(tr("Config file already exists, use --overwrite to discard the existing one."), feedback.ErrGeneric) } logrus.Infof("Writing config file to: %s", absPath) if err := absPath.MkdirAll(); err != nil { - feedback.Fatal(tr("Cannot create config file directory: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Cannot create config file directory: %v", err), feedback.ErrGeneric) } newSettings := viper.New() @@ -99,7 +98,7 @@ func runInitCommand(cmd *cobra.Command, args []string) { configuration.BindFlags(cmd, newSettings) if err := newSettings.WriteConfigAs(configFileAbsPath.String()); err != nil { - feedback.Fatal(tr("Cannot create config file: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Cannot create config file: %v", err), feedback.ErrGeneric) } msg := tr("Config file written to: %s", configFileAbsPath.String()) diff --git a/cli/config/remove.go b/cli/config/remove.go index 61f0cc2c5d9..4ddff81af60 100644 --- a/cli/config/remove.go +++ b/cli/config/remove.go @@ -19,7 +19,6 @@ import ( "os" "reflect" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" "github.com/sirupsen/logrus" @@ -50,7 +49,7 @@ func runRemoveCommand(cmd *cobra.Command, args []string) { if kind != reflect.Slice { msg := tr("The key '%[1]v' is not a list of items, can't remove from it.\nMaybe use '%[2]s'?", key, "config delete") - feedback.Fatal(msg, errorcodes.ErrGeneric) + feedback.Fatal(msg, feedback.ErrGeneric) } mappedValues := map[string]bool{} @@ -67,6 +66,6 @@ func runRemoveCommand(cmd *cobra.Command, args []string) { configuration.Settings.Set(key, values) if err := configuration.Settings.WriteConfig(); err != nil { - feedback.Fatal(tr("Can't write config file: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Can't write config file: %v", err), feedback.ErrGeneric) } } diff --git a/cli/config/set.go b/cli/config/set.go index 4ae2ba07bf8..f8f882e628d 100644 --- a/cli/config/set.go +++ b/cli/config/set.go @@ -20,7 +20,6 @@ import ( "reflect" "strconv" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" "github.com/sirupsen/logrus" @@ -52,7 +51,7 @@ func runSetCommand(cmd *cobra.Command, args []string) { kind := validateKey(key) if kind != reflect.Slice && len(args) > 2 { - feedback.Fatal(tr("Can't set multiple values in key %v", key), errorcodes.ErrGeneric) + feedback.Fatal(tr("Can't set multiple values in key %v", key), feedback.ErrGeneric) } var value interface{} @@ -65,13 +64,13 @@ func runSetCommand(cmd *cobra.Command, args []string) { var err error value, err = strconv.ParseBool(args[1]) if err != nil { - feedback.Fatal(tr("error parsing value: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("error parsing value: %v", err), feedback.ErrGeneric) } } configuration.Settings.Set(key, value) if err := configuration.Settings.WriteConfig(); err != nil { - feedback.Fatal(tr("Writing config file: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Writing config file: %v", err), feedback.ErrGeneric) } } diff --git a/cli/config/validate.go b/cli/config/validate.go index aca9fa2860d..c7a3af1e821 100644 --- a/cli/config/validate.go +++ b/cli/config/validate.go @@ -19,7 +19,6 @@ import ( "fmt" "reflect" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" ) @@ -56,7 +55,7 @@ func typeOf(key string) (reflect.Kind, error) { func validateKey(key string) reflect.Kind { kind, err := typeOf(key) if err != nil { - feedback.FatalError(err, errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } return kind } diff --git a/cli/core/download.go b/cli/core/download.go index 17f7ce49bba..a828ea40fb4 100644 --- a/cli/core/download.go +++ b/cli/core/download.go @@ -21,7 +21,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" @@ -54,7 +53,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { platformsRefs, err := arguments.ParseReferences(args) if err != nil { - feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), feedback.ErrBadArgument) } for i, platformRef := range platformsRefs { @@ -66,7 +65,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { } _, err := core.PlatformDownload(context.Background(), platformDownloadreq, feedback.ProgressBar()) if err != nil { - feedback.Fatal(tr("Error downloading %[1]s: %[2]v", args[i], err), errorcodes.ErrNetwork) + feedback.Fatal(tr("Error downloading %[1]s: %[2]v", args[i], err), feedback.ErrNetwork) } } } diff --git a/cli/core/install.go b/cli/core/install.go index 8841c0afefa..d787e8be6a5 100644 --- a/cli/core/install.go +++ b/cli/core/install.go @@ -21,7 +21,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" @@ -63,7 +62,7 @@ func runInstallCommand(args []string, postInstallFlags arguments.PostInstallFlag platformsRefs, err := arguments.ParseReferences(args) if err != nil { - feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), feedback.ErrBadArgument) } for _, platformRef := range platformsRefs { @@ -77,7 +76,7 @@ func runInstallCommand(args []string, postInstallFlags arguments.PostInstallFlag } _, err := core.PlatformInstall(context.Background(), platformInstallRequest, feedback.ProgressBar(), feedback.TaskProgress()) if err != nil { - feedback.Fatal(tr("Error during install: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during install: %v", err), feedback.ErrGeneric) } } } diff --git a/cli/core/list.go b/cli/core/list.go index e5ad24ad2f0..a60a672d4af 100644 --- a/cli/core/list.go +++ b/cli/core/list.go @@ -19,7 +19,6 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" @@ -61,7 +60,7 @@ func List(inst *rpc.Instance, all bool, updatableOnly bool) { All: all, }) if err != nil { - feedback.Fatal(tr("Error listing platforms: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error listing platforms: %v", err), feedback.ErrGeneric) } feedback.PrintResult(installedResult{platforms}) diff --git a/cli/core/search.go b/cli/core/search.go index fd70d2e217c..b4418bb1037 100644 --- a/cli/core/search.go +++ b/cli/core/search.go @@ -25,7 +25,6 @@ import ( "github.com/arduino/arduino-cli/arduino/globals" "github.com/arduino/arduino-cli/arduino/utils" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" @@ -61,13 +60,13 @@ const indexUpdateInterval = "24h" func runSearchCommand(cmd *cobra.Command, args []string) { inst, status := instance.Create() if status != nil { - feedback.Fatal(tr("Error creating instance: %v", status), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating instance: %v", status), feedback.ErrGeneric) } if indexesNeedUpdating(indexUpdateInterval) { err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexRequest{Instance: inst}, feedback.ProgressBar()) if err != nil { - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } } @@ -82,7 +81,7 @@ func runSearchCommand(cmd *cobra.Command, args []string) { AllVersions: allVersions, }) if err != nil { - feedback.Fatal(tr("Error searching for platforms: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error searching for platforms: %v", err), feedback.ErrGeneric) } coreslist := resp.GetSearchOutput() @@ -126,7 +125,7 @@ func indexesNeedUpdating(duration string) bool { now := time.Now() modTimeThreshold, err := time.ParseDuration(duration) if err != nil { - feedback.Fatal(tr("Invalid timeout: %s", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid timeout: %s", err), feedback.ErrBadArgument) } urls := []string{globals.DefaultIndexURL} diff --git a/cli/core/uninstall.go b/cli/core/uninstall.go index 9d527016c2c..260fa009871 100644 --- a/cli/core/uninstall.go +++ b/cli/core/uninstall.go @@ -21,7 +21,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" @@ -51,12 +50,12 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { platformsRefs, err := arguments.ParseReferences(args) if err != nil { - feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), feedback.ErrBadArgument) } for _, platformRef := range platformsRefs { if platformRef.Version != "" { - feedback.Fatal(tr("Invalid parameter %s: version not allowed", platformRef), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid parameter %s: version not allowed", platformRef), feedback.ErrBadArgument) } } for _, platformRef := range platformsRefs { @@ -66,7 +65,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { Architecture: platformRef.Architecture, }, feedback.NewTaskProgressCB()) if err != nil { - feedback.Fatal(tr("Error during uninstall: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during uninstall: %v", err), feedback.ErrGeneric) } } } diff --git a/cli/core/update_index.go b/cli/core/update_index.go index c4d23b1326a..034e79642f7 100644 --- a/cli/core/update_index.go +++ b/cli/core/update_index.go @@ -19,7 +19,6 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" @@ -50,6 +49,6 @@ func runUpdateIndexCommand(cmd *cobra.Command, args []string) { func UpdateIndex(inst *rpc.Instance) { err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexRequest{Instance: inst}, feedback.ProgressBar()) if err != nil { - feedback.FatalError(err, errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } } diff --git a/cli/core/upgrade.go b/cli/core/upgrade.go index d76d5bc15d9..96090010b27 100644 --- a/cli/core/upgrade.go +++ b/cli/core/upgrade.go @@ -23,7 +23,6 @@ import ( "github.com/arduino/arduino-cli/arduino" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" @@ -66,7 +65,7 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { UpdatableOnly: true, }) if err != nil { - feedback.Fatal(tr("Error retrieving core list: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error retrieving core list: %v", err), feedback.ErrGeneric) } if len(targets) == 0 { @@ -82,7 +81,7 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { // proceed upgrading, if anything is upgradable platformsRefs, err := arguments.ParseReferences(args) if err != nil { - feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), feedback.ErrBadArgument) } hasBadArguments := false @@ -105,11 +104,11 @@ func Upgrade(inst *rpc.Instance, args []string, skipPostInstall bool) { continue } - feedback.Fatal(tr("Error during upgrade: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during upgrade: %v", err), feedback.ErrGeneric) } } if hasBadArguments { - feedback.Fatal(tr("Some upgrades failed, please check the output for details."), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Some upgrades failed, please check the output for details."), feedback.ErrBadArgument) } } diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index e3b4bce863e..abea873e9ea 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -25,7 +25,6 @@ import ( "strings" "syscall" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/commands/daemon" @@ -79,7 +78,7 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { gRPCOptions := []grpc.ServerOption{} if debugFile != "" { if !debug { - feedback.Fatal(tr("The flag --debug-file must be used with --debug."), errorcodes.ErrBadArgument) + feedback.Fatal(tr("The flag --debug-file must be used with --debug."), feedback.ErrBadArgument) } } if debug { @@ -87,14 +86,14 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { outFile := paths.New(debugFile) f, err := outFile.Append() if err != nil { - feedback.Fatal(tr("Error opening debug logging file: %s", err), errorcodes.ErrBadCall) + feedback.Fatal(tr("Error opening debug logging file: %s", err), feedback.ErrGeneric) } defer f.Close() debugStdOut = f } else { // Attach to os.Stdout only if we are in Text mode if feedback.GetFormat() != feedback.Text { - feedback.Fatal(tr("Debug log is only available in text format"), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Debug log is only available in text format"), feedback.ErrBadArgument) } out, _, _ := feedback.OutputStreams() debugStdOut = out @@ -133,19 +132,19 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { // Invalid port, such as "Foo" var dnsError *net.DNSError if errors.As(err, &dnsError) { - feedback.Fatal(tr("Failed to listen on TCP port: %[1]s. %[2]s is unknown name.", port, dnsError.Name), errorcodes.ErrCoreConfig) + feedback.Fatal(tr("Failed to listen on TCP port: %[1]s. %[2]s is unknown name.", port, dnsError.Name), feedback.ErrCoreConfig) } // Invalid port number, such as -1 var addrError *net.AddrError if errors.As(err, &addrError) { - feedback.Fatal(tr("Failed to listen on TCP port: %[1]s. %[2]s is an invalid port.", port, addrError.Addr), errorcodes.ErrCoreConfig) + feedback.Fatal(tr("Failed to listen on TCP port: %[1]s. %[2]s is an invalid port.", port, addrError.Addr), feedback.ErrCoreConfig) } // Port is already in use var syscallErr *os.SyscallError if errors.As(err, &syscallErr) && errors.Is(syscallErr.Err, syscall.EADDRINUSE) { - feedback.Fatal(tr("Failed to listen on TCP port: %s. Address already in use.", port), errorcodes.ErrNetwork) + feedback.Fatal(tr("Failed to listen on TCP port: %s. Address already in use.", port), feedback.ErrNetwork) } - feedback.Fatal(tr("Failed to listen on TCP port: %[1]s. Unexpected error: %[2]v", port, err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Failed to listen on TCP port: %[1]s. Unexpected error: %[2]v", port, err), feedback.ErrGeneric) } // We need to parse the port used only if the user let @@ -156,7 +155,7 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { split := strings.Split(address.String(), ":") if len(split) == 0 { - feedback.Fatal(tr("Invalid TCP address: port is missing"), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid TCP address: port is missing"), feedback.ErrBadArgument) } port = split[len(split)-1] diff --git a/cli/debug/debug.go b/cli/debug/debug.go index 9b13edfd632..ca9f43e0caf 100644 --- a/cli/debug/debug.go +++ b/cli/debug/debug.go @@ -22,7 +22,6 @@ import ( "sort" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/debug" @@ -91,7 +90,7 @@ func runDebugCommand(command *cobra.Command, args []string) { if printInfo { if res, err := debug.GetDebugConfig(context.Background(), debugConfigRequested); err != nil { - feedback.Fatal(tr("Error getting Debug info: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Error getting Debug info: %v", err), feedback.ErrBadArgument) } else { feedback.PrintResult(&debugInfoResult{res}) } @@ -104,10 +103,10 @@ func runDebugCommand(command *cobra.Command, args []string) { in, out, err := feedback.InteractiveStreams() if err != nil { - feedback.FatalError(err, errorcodes.ErrBadArgument) + feedback.FatalError(err, feedback.ErrBadArgument) } if _, err := debug.Debug(context.Background(), debugConfigRequested, in, out, ctrlc); err != nil { - feedback.Fatal(tr("Error during Debug: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Debug: %v", err), feedback.ErrGeneric) } } diff --git a/cli/errorcodes/errorcodes.go b/cli/feedback/errorcodes.go similarity index 59% rename from cli/errorcodes/errorcodes.go rename to cli/feedback/errorcodes.go index 777967e9460..1e1a0edf19e 100644 --- a/cli/errorcodes/errorcodes.go +++ b/cli/feedback/errorcodes.go @@ -1,6 +1,6 @@ // This file is part of arduino-cli. // -// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) +// Copyright 2022 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. @@ -13,19 +13,33 @@ // Arduino software without disclosing the source code of your own applications. // To purchase a commercial license, send an email to license@arduino.cc. -package errorcodes +package feedback + +// ExitCode to be used for Fatal. +type ExitCode int -// Error codes to be used for os.Exit(). const ( - _ = iota // 0 is not a valid exit error code - ErrGeneric // 1 is the reserved "catchall" code in Unix - _ // 2 is reserved in Unix + // Success (0 is the no-error return code in Unix) + Success ExitCode = iota + + // ErrGeneric Generic error (1 is the reserved "catchall" code in Unix) + ErrGeneric + + _ // (2 Is reserved in Unix) + + // ErrNoConfigFile is returned when the config file is not found (3) ErrNoConfigFile - ErrBadCall + + _ // (4 was ErrBadCall and has been removed) + + // ErrNetwork is returned when a network error occurs (5) ErrNetwork + // ErrCoreConfig represents an error in the cli core config, for example some basic // files shipped with the installation are missing, or cannot create or get basic - // directories vital for the CLI to work. + // directories vital for the CLI to work. (6) ErrCoreConfig + + // ErrBadArgument is returned when the arguments are not valid (7) ErrBadArgument ) diff --git a/cli/feedback/feedback.go b/cli/feedback/feedback.go index 2c56f892ebd..4e18d5a2efe 100644 --- a/cli/feedback/feedback.go +++ b/cli/feedback/feedback.go @@ -24,7 +24,6 @@ import ( "io" "os" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/i18n" "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" @@ -165,15 +164,15 @@ func Warning(msg string) { } // FatalError outputs the error and exits with status exitCode. -func FatalError(err error, exitCode int) { +func FatalError(err error, exitCode ExitCode) { Fatal(err.Error(), exitCode) } // Fatal outputs the errorMsg and exits with status exitCode. -func Fatal(errorMsg string, exitCode int) { +func Fatal(errorMsg string, exitCode ExitCode) { if format == Text { fmt.Fprintln(stdErr, errorMsg) - os.Exit(exitCode) + os.Exit(int(exitCode)) } type FatalError struct { @@ -198,7 +197,7 @@ func Fatal(errorMsg string, exitCode int) { panic("unknown output format") } fmt.Fprintln(stdErr, string(d)) - os.Exit(exitCode) + os.Exit(int(exitCode)) } func augment(data interface{}) interface{} { @@ -228,19 +227,19 @@ func PrintResult(res Result) { case JSON: d, err := json.MarshalIndent(augment(res.Data()), "", " ") if err != nil { - Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), errorcodes.ErrGeneric) + Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), ErrGeneric) } data = string(d) case MinifiedJSON: d, err := json.Marshal(augment(res.Data())) if err != nil { - Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), errorcodes.ErrGeneric) + Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), ErrGeneric) } data = string(d) case YAML: d, err := yaml.Marshal(augment(res.Data())) if err != nil { - Fatal(fmt.Sprintf("Error during YAML encoding of the output: %v", err), errorcodes.ErrGeneric) + Fatal(fmt.Sprintf("Error during YAML encoding of the output: %v", err), ErrGeneric) } data = string(d) case Text: diff --git a/cli/feedback/feedback_cmd.go b/cli/feedback/feedback_cmd.go index d743a72ea76..ce66d18f1ac 100644 --- a/cli/feedback/feedback_cmd.go +++ b/cli/feedback/feedback_cmd.go @@ -18,7 +18,6 @@ package feedback import ( "fmt" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/spf13/cobra" ) @@ -38,15 +37,15 @@ func NewCommand() *cobra.Command { Run: func(cmd *cobra.Command, args []string) { user, err := InputUserField("User name", false) if err != nil { - Fatal(fmt.Sprintf("Error reading input: %v", err), errorcodes.ErrGeneric) + Fatal(fmt.Sprintf("Error reading input: %v", err), ErrGeneric) } pass, err := InputUserField("Password", true) if err != nil { - Fatal(fmt.Sprintf("Error reading input: %v", err), errorcodes.ErrGeneric) + Fatal(fmt.Sprintf("Error reading input: %v", err), ErrGeneric) } nick, err := InputUserField("Nickname", false) if err != nil { - Fatal(fmt.Sprintf("Error reading input: %v", err), errorcodes.ErrGeneric) + Fatal(fmt.Sprintf("Error reading input: %v", err), ErrGeneric) } Print("Hello " + user + " (a.k.a " + nick + ")!") Print("Your password is " + pass + "!") diff --git a/cli/generatedocs/generatedocs.go b/cli/generatedocs/generatedocs.go index 99657d6874d..70e5bb5a1f4 100644 --- a/cli/generatedocs/generatedocs.go +++ b/cli/generatedocs/generatedocs.go @@ -19,7 +19,7 @@ import ( "os" "path/filepath" - "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/i18n" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -66,7 +66,7 @@ func generateBashCompletions(cmd *cobra.Command, args []string) { err := cmd.Root().GenBashCompletionFile(filepath.Join(outputDir, "arduino")) if err != nil { logrus.WithError(err).Warn("Error Generating bash autocompletions") - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } } @@ -83,6 +83,6 @@ func generateManPages(cmd *cobra.Command, args []string) { err := doc.GenManTree(cmd.Root(), header, outputDir) if err != nil { logrus.WithError(err).Warn("Error Generating manpages") - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } } diff --git a/cli/instance/instance.go b/cli/instance/instance.go index df6bb57b91f..4e2fd19b0b7 100644 --- a/cli/instance/instance.go +++ b/cli/instance/instance.go @@ -18,7 +18,6 @@ package instance import ( "context" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/configuration" @@ -44,7 +43,7 @@ func CreateAndInit() *rpc.Instance { func CreateAndInitWithProfile(profileName string, sketchPath *paths.Path) (*rpc.Instance, *rpc.Profile) { instance, err := Create() if err != nil { - feedback.Fatal(tr("Error creating instance: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating instance: %v", err), feedback.ErrGeneric) } profile := InitWithProfile(instance, profileName, sketchPath) return instance, profile @@ -166,7 +165,7 @@ func CreateInstanceAndRunFirstUpdate() *rpc.Instance { // as argument but none would be obviously found. inst, status := Create() if status != nil { - feedback.Fatal(tr("Error creating instance: %v", status), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating instance: %v", status), feedback.ErrGeneric) } // In case this is the first time the CLI is run we need to update indexes @@ -174,7 +173,7 @@ func CreateInstanceAndRunFirstUpdate() *rpc.Instance { // we must use instance.Create instead of instance.CreateAndInit for the // reason stated above. if err := FirstUpdate(inst); err != nil { - feedback.Fatal(tr("Error updating indexes: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error updating indexes: %v", err), feedback.ErrGeneric) } return inst } diff --git a/cli/lib/check_deps.go b/cli/lib/check_deps.go index 57d0d33a216..f3c91308420 100644 --- a/cli/lib/check_deps.go +++ b/cli/lib/check_deps.go @@ -22,7 +22,6 @@ import ( "sort" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" @@ -54,7 +53,7 @@ func runDepsCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino-cli lib deps`") libRef, err := ParseLibraryReferenceArgAndAdjustCase(instance, args[0]) if err != nil { - feedback.Fatal(tr("Arguments error: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Arguments error: %v", err), feedback.ErrBadArgument) } deps, err := lib.LibraryResolveDependencies(context.Background(), &rpc.LibraryResolveDependenciesRequest{ @@ -63,7 +62,7 @@ func runDepsCommand(cmd *cobra.Command, args []string) { Version: libRef.Version, }) if err != nil { - feedback.Fatal(tr("Error resolving dependencies for %[1]s: %[2]s", libRef, err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error resolving dependencies for %[1]s: %[2]s", libRef, err), feedback.ErrGeneric) } feedback.PrintResult(&checkDepResult{deps: deps}) diff --git a/cli/lib/download.go b/cli/lib/download.go index d6fc7a7af15..5ca4669ecdf 100644 --- a/cli/lib/download.go +++ b/cli/lib/download.go @@ -21,7 +21,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" @@ -52,7 +51,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino-cli lib download`") refs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args) if err != nil { - feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), feedback.ErrBadArgument) } for _, library := range refs { @@ -63,7 +62,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { } _, err := lib.LibraryDownload(context.Background(), libraryDownloadRequest, feedback.ProgressBar()) if err != nil { - feedback.Fatal(tr("Error downloading %[1]s: %[2]v", library, err), errorcodes.ErrNetwork) + feedback.Fatal(tr("Error downloading %[1]s: %[2]v", library, err), feedback.ErrNetwork) } } } diff --git a/cli/lib/examples.go b/cli/lib/examples.go index 69433576805..4f4439ecb25 100644 --- a/cli/lib/examples.go +++ b/cli/lib/examples.go @@ -23,7 +23,6 @@ import ( "strings" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" @@ -70,7 +69,7 @@ func runExamplesCommand(cmd *cobra.Command, args []string) { Fqbn: fqbn.String(), }) if err != nil { - feedback.Fatal(tr("Error getting libraries info: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error getting libraries info: %v", err), feedback.ErrGeneric) } found := []*libraryExamples{} diff --git a/cli/lib/install.go b/cli/lib/install.go index 91ad3b3d479..c5ac60f4c5c 100644 --- a/cli/lib/install.go +++ b/cli/lib/install.go @@ -22,7 +22,6 @@ import ( "strings" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/cli/instance" @@ -78,7 +77,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { split := strings.Split(globals.VersionInfo.VersionString, ".") documentationURL = fmt.Sprintf("https://arduino.github.io/arduino-cli/%s.%s/configuration/#configuration-keys", split[0], split[1]) } - feedback.Fatal(tr("--git-url and --zip-path are disabled by default, for more information see: %v", documentationURL), errorcodes.ErrGeneric) + feedback.Fatal(tr("--git-url and --zip-path are disabled by default, for more information see: %v", documentationURL), feedback.ErrGeneric) } feedback.Print(tr("--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")) } @@ -91,7 +90,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Overwrite: !noOverwrite, }, feedback.TaskProgress()) if err != nil { - feedback.Fatal(tr("Error installing Zip Library: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error installing Zip Library: %v", err), feedback.ErrGeneric) } } return @@ -102,7 +101,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { if url == "." { wd, err := paths.Getwd() if err != nil { - feedback.Fatal(tr("Couldn't get current working directory: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Couldn't get current working directory: %v", err), feedback.ErrGeneric) } url = wd.String() } @@ -112,7 +111,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Overwrite: !noOverwrite, }, feedback.TaskProgress()) if err != nil { - feedback.Fatal(tr("Error installing Git Library: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error installing Git Library: %v", err), feedback.ErrGeneric) } } return @@ -120,7 +119,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { libRefs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args) if err != nil { - feedback.Fatal(tr("Arguments error: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Arguments error: %v", err), feedback.ErrBadArgument) } for _, libRef := range libRefs { @@ -133,7 +132,7 @@ func runInstallCommand(cmd *cobra.Command, args []string) { } err := lib.LibraryInstall(context.Background(), libraryInstallRequest, feedback.ProgressBar(), feedback.TaskProgress()) if err != nil { - feedback.Fatal(tr("Error installing %s: %v", libRef.Name, err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error installing %s: %v", libRef.Name, err), feedback.ErrGeneric) } } } diff --git a/cli/lib/list.go b/cli/lib/list.go index e823a94f6cf..90258df4a5f 100644 --- a/cli/lib/list.go +++ b/cli/lib/list.go @@ -22,7 +22,6 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" @@ -76,7 +75,7 @@ func List(instance *rpc.Instance, args []string, all bool, updatable bool) { Fqbn: fqbn.String(), }) if err != nil { - feedback.Fatal(tr("Error listing Libraries: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error listing Libraries: %v", err), feedback.ErrGeneric) } libs := []*rpc.InstalledLibrary{} diff --git a/cli/lib/search.go b/cli/lib/search.go index dc5d8474730..5e87bfdbda9 100644 --- a/cli/lib/search.go +++ b/cli/lib/search.go @@ -22,7 +22,6 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" @@ -54,7 +53,7 @@ func runSearchCommand(args []string, namesOnly bool) { logrus.Info("Executing `arduino-cli lib search`") if status != nil { - feedback.Fatal(tr("Error creating instance: %v", status), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating instance: %v", status), feedback.ErrGeneric) } if err := commands.UpdateLibrariesIndex( @@ -62,7 +61,7 @@ func runSearchCommand(args []string, namesOnly bool) { &rpc.UpdateLibrariesIndexRequest{Instance: inst}, feedback.ProgressBar(), ); err != nil { - feedback.Fatal(tr("Error updating library index: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error updating library index: %v", err), feedback.ErrGeneric) } instance.Init(inst) @@ -72,7 +71,7 @@ func runSearchCommand(args []string, namesOnly bool) { Query: strings.Join(args, " "), }) if err != nil { - feedback.Fatal(tr("Error searching for Libraries: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error searching for Libraries: %v", err), feedback.ErrGeneric) } feedback.PrintResult(result{ diff --git a/cli/lib/uninstall.go b/cli/lib/uninstall.go index c3639514bc2..96907e679c1 100644 --- a/cli/lib/uninstall.go +++ b/cli/lib/uninstall.go @@ -21,7 +21,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" @@ -51,7 +50,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { refs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args) if err != nil { - feedback.Fatal(tr("Invalid argument passed: %v", err), errorcodes.ErrBadArgument) + feedback.Fatal(tr("Invalid argument passed: %v", err), feedback.ErrBadArgument) } for _, library := range refs { @@ -61,7 +60,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { Version: library.Version, }, feedback.TaskProgress()) if err != nil { - feedback.Fatal(tr("Error uninstalling %[1]s: %[2]v", library, err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error uninstalling %[1]s: %[2]v", library, err), feedback.ErrGeneric) } } diff --git a/cli/lib/update_index.go b/cli/lib/update_index.go index 4a178a6fe7f..741b051cca6 100644 --- a/cli/lib/update_index.go +++ b/cli/lib/update_index.go @@ -19,7 +19,6 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" @@ -52,6 +51,6 @@ func UpdateIndex(inst *rpc.Instance) { Instance: inst, }, feedback.ProgressBar()) if err != nil { - feedback.Fatal(tr("Error updating library index: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error updating library index: %v", err), feedback.ErrGeneric) } } diff --git a/cli/lib/upgrade.go b/cli/lib/upgrade.go index deb1e027424..6acddeaa9b9 100644 --- a/cli/lib/upgrade.go +++ b/cli/lib/upgrade.go @@ -20,7 +20,6 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" @@ -69,7 +68,7 @@ func Upgrade(instance *rpc.Instance, libraries []string) { } if upgradeErr != nil { - feedback.Fatal(fmt.Sprintf("%s: %v", tr("Error upgrading libraries"), upgradeErr), errorcodes.ErrGeneric) + feedback.Fatal(fmt.Sprintf("%s: %v", tr("Error upgrading libraries"), upgradeErr), feedback.ErrGeneric) } logrus.Info("Done") diff --git a/cli/monitor/monitor.go b/cli/monitor/monitor.go index 73f0193b851..770f9a210f5 100644 --- a/cli/monitor/monitor.go +++ b/cli/monitor/monitor.go @@ -25,7 +25,6 @@ import ( "strings" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/monitor" @@ -77,7 +76,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { portAddress, portProtocol, err := portArgs.GetPortAddressAndProtocol(instance, nil) if err != nil { - feedback.FatalError(err, errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } enumerateResp, err := monitor.EnumerateMonitorPortSettings(context.Background(), &rpc.EnumerateMonitorPortSettingsRequest{ @@ -86,7 +85,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { Fqbn: fqbn.String(), }) if err != nil { - feedback.Fatal(tr("Error getting port settings details: %s", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error getting port settings details: %s", err), feedback.ErrGeneric) } if describe { feedback.PrintResult(&detailsResult{Settings: enumerateResp.Settings}) @@ -95,7 +94,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { tty, err := newStdInOutTerminal() if err != nil { - feedback.FatalError(err, errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } defer tty.Close() @@ -120,7 +119,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { } else { if strings.EqualFold(s.SettingId, k) { if !contains(s.EnumValues, v) { - feedback.Fatal(tr("invalid port configuration value for %s: %s", k, v), errorcodes.ErrBadArgument) + feedback.Fatal(tr("invalid port configuration value for %s: %s", k, v), feedback.ErrBadArgument) } setting = s break @@ -128,7 +127,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { } } if setting == nil { - feedback.Fatal(tr("invalid port configuration: %s", config), errorcodes.ErrBadArgument) + feedback.Fatal(tr("invalid port configuration: %s", config), feedback.ErrBadArgument) } configuration.Settings = append(configuration.Settings, &rpc.MonitorPortSetting{ SettingId: setting.SettingId, @@ -147,7 +146,7 @@ func runMonitorCmd(cmd *cobra.Command, args []string) { PortConfiguration: configuration, }) if err != nil { - feedback.FatalError(err, errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } defer portProxy.Close() diff --git a/cli/sketch/archive.go b/cli/sketch/archive.go index c9b93e5d280..b507d587d8c 100644 --- a/cli/sketch/archive.go +++ b/cli/sketch/archive.go @@ -21,7 +21,6 @@ import ( "os" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" sk "github.com/arduino/arduino-cli/commands/sketch" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" @@ -78,6 +77,6 @@ func runArchiveCommand(args []string, includeBuildDir bool, overwrite bool) { }) if err != nil { - feedback.Fatal(tr("Error archiving: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error archiving: %v", err), feedback.ErrGeneric) } } diff --git a/cli/sketch/new.go b/cli/sketch/new.go index ec9d840cb2d..18a1c86852b 100644 --- a/cli/sketch/new.go +++ b/cli/sketch/new.go @@ -21,7 +21,6 @@ import ( "strings" "github.com/arduino/arduino-cli/arduino/globals" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" sk "github.com/arduino/arduino-cli/commands/sketch" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" @@ -54,7 +53,7 @@ func runNewCommand(args []string, overwrite bool) { trimmedSketchName := strings.TrimSuffix(sketchName, globals.MainFileValidExtension) sketchDirPath, err := paths.New(trimmedSketchName).Abs() if err != nil { - feedback.Fatal(tr("Error creating sketch: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating sketch: %v", err), feedback.ErrGeneric) } _, err = sk.NewSketch(context.Background(), &rpc.NewSketchRequest{ Instance: nil, @@ -63,7 +62,7 @@ func runNewCommand(args []string, overwrite bool) { Overwrite: overwrite, }) if err != nil { - feedback.Fatal(tr("Error creating sketch: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error creating sketch: %v", err), feedback.ErrGeneric) } feedback.Print(tr("Sketch created in: %s", sketchDirPath)) diff --git a/cli/upload/upload.go b/cli/upload/upload.go index 850a222eb91..8121ec32807 100644 --- a/cli/upload/upload.go +++ b/cli/upload/upload.go @@ -26,7 +26,6 @@ import ( "github.com/arduino/arduino-cli/arduino/cores/packagemanager" "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/cli/instance" @@ -93,7 +92,7 @@ func runUploadCommand(command *cobra.Command, args []string) { sk, err := sketch.New(sketchPath) if err != nil && importDir == "" && importFile == "" { - feedback.Fatal(tr("Error during Upload: %v", err), errorcodes.ErrGeneric) + feedback.Fatal(tr("Error during Upload: %v", err), feedback.ErrGeneric) } instance, profile := instance.CreateAndInitWithProfile(profileArg.Get(), sketchPath) @@ -135,7 +134,7 @@ func runUploadCommand(command *cobra.Command, args []string) { msg += tr("Platform %s is not found in any known index\nMaybe you need to add a 3rd party URL?", platformErr.Platform) } } - feedback.Fatal(msg, errorcodes.ErrGeneric) + feedback.Fatal(msg, feedback.ErrGeneric) } fields := map[string]string{} @@ -143,7 +142,7 @@ func runUploadCommand(command *cobra.Command, args []string) { feedback.Print(tr("Uploading to specified board using %s protocol requires the following info:", port.Protocol)) if f, err := arguments.AskForUserFields(userFieldRes.UserFields); err != nil { msg := fmt.Sprintf("%s: %s", tr("Error getting user input"), err) - feedback.Fatal(msg, errorcodes.ErrGeneric) + feedback.Fatal(msg, feedback.ErrGeneric) } else { fields = f } @@ -168,7 +167,7 @@ func runUploadCommand(command *cobra.Command, args []string) { UserFields: fields, } if err := upload.Upload(context.Background(), req, stdOut, stdErr); err != nil { - feedback.FatalError(err, errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } feedback.PrintResult(stdIOResult()) } diff --git a/cli/version/version.go b/cli/version/version.go index 18483d69a3e..9cad16e5142 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -20,7 +20,6 @@ import ( "os" "strings" - "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/cli/updater" @@ -56,7 +55,7 @@ func runVersionCommand(cmd *cobra.Command, args []string) { currentVersion, err := semver.Parse(globals.VersionInfo.VersionString) if err != nil { - feedback.Fatal(fmt.Sprintf("Error parsing current version: %s", err), errorcodes.ErrGeneric) + feedback.Fatal(fmt.Sprintf("Error parsing current version: %s", err), feedback.ErrGeneric) } latestVersion := updater.ForceCheckForUpdate(currentVersion) diff --git a/main.go b/main.go index 2405f612188..98b3a317cbd 100644 --- a/main.go +++ b/main.go @@ -19,7 +19,7 @@ import ( "os" "github.com/arduino/arduino-cli/cli" - "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" ) @@ -29,6 +29,6 @@ func main() { i18n.Init(configuration.Settings.GetString("locale")) arduinoCmd := cli.NewCommand() if err := arduinoCmd.Execute(); err != nil { - os.Exit(errorcodes.ErrGeneric) + feedback.FatalError(err, feedback.ErrGeneric) } } From 61fb1c85c3627c4020e27612f9115a54918fd25d Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 9 Dec 2022 11:30:42 +0100 Subject: [PATCH 28/45] Remove direct os.Stdin access from daemon command --- cli/cli_test.go | 1 + cli/daemon/daemon.go | 8 +------- cli/feedback/terminal.go | 10 ++++++++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cli/cli_test.go b/cli/cli_test.go index ac36a819665..9986c292ee6 100644 --- a/cli/cli_test.go +++ b/cli/cli_test.go @@ -73,6 +73,7 @@ func inspect(t *testing.T, fset *token.FileSet, node ast.Node) bool { wanted := map[string]bool{ "os.Stdout": true, "os.Stderr": true, + "os.Stdin": true, } name := expr(n) if wanted[name] { diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index abea873e9ea..38934dd2a34 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -18,8 +18,6 @@ package daemon import ( "errors" "fmt" - "io" - "io/ioutil" "net" "os" "strings" @@ -120,11 +118,7 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { if !daemonize { // When parent process ends terminate also the daemon - go func() { - // Stdin is closed when the controlling parent process ends - _, _ = io.Copy(ioutil.Discard, os.Stdin) - os.Exit(0) - }() + go feedback.ExitWhenParentProcessEnds() } lis, err := net.Listen("tcp", fmt.Sprintf("%s:%s", ip, port)) diff --git a/cli/feedback/terminal.go b/cli/feedback/terminal.go index 6eb029f3f39..2783571d077 100644 --- a/cli/feedback/terminal.go +++ b/cli/feedback/terminal.go @@ -72,3 +72,13 @@ func InputUserField(prompt string, secret bool) (string, error) { return string(value), nil } + +// ExitWhenParentProcessEnds waits until the controlling parent process ends and then exits +// the current process. This is useful to terminate the current process when it is daemonized +// and the controlling parent process is terminated to avoid leaving zombie processes. +// It is recommended to call this function as a goroutine. +func ExitWhenParentProcessEnds() { + // Stdin is closed when the controlling parent process ends + _, _ = io.Copy(io.Discard, os.Stdin) + os.Exit(0) +} From bb0c707d23111d3c5d2b22019aa2b101ef8fad71 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 12 Dec 2022 12:36:28 +0100 Subject: [PATCH 29/45] Removed redundant `cli/globals` package This will help later to make the whole `cli` package internal. --- arduino/discovery/discovery.go | 4 ++-- arduino/monitor/monitor.go | 4 ++-- cli/cli.go | 6 +++--- cli/compile/compile.go | 15 +++++++-------- cli/daemon/daemon.go | 4 ++-- cli/globals/globals.go | 28 ---------------------------- cli/lib/install.go | 6 +++--- cli/updater/updater.go | 4 ++-- cli/upload/upload.go | 4 ++-- cli/version/version.go | 15 ++++++++------- commands/instances.go | 4 ++-- configuration/network.go | 8 ++++---- version/version.go | 8 ++++++++ 13 files changed, 45 insertions(+), 65 deletions(-) delete mode 100644 cli/globals/globals.go diff --git a/arduino/discovery/discovery.go b/arduino/discovery/discovery.go index 9def18596e7..1de61f3c9bb 100644 --- a/arduino/discovery/discovery.go +++ b/arduino/discovery/discovery.go @@ -23,10 +23,10 @@ import ( "sync" "time" - "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/executils" "github.com/arduino/arduino-cli/i18n" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" + "github.com/arduino/arduino-cli/version" "github.com/arduino/go-properties-orderedmap" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -301,7 +301,7 @@ func (disc *PluggableDiscovery) Run() (err error) { } }() - if err = disc.sendCommand("HELLO 1 \"arduino-cli " + globals.VersionInfo.VersionString + "\"\n"); err != nil { + if err = disc.sendCommand("HELLO 1 \"arduino-cli " + version.VersionInfo.VersionString + "\"\n"); err != nil { return err } if msg, err := disc.waitMessage(time.Second * 10); err != nil { diff --git a/arduino/monitor/monitor.go b/arduino/monitor/monitor.go index 4e53435ebc7..10650dcebc3 100644 --- a/arduino/monitor/monitor.go +++ b/arduino/monitor/monitor.go @@ -26,9 +26,9 @@ import ( "strings" "time" - "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/executils" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/version" "github.com/sirupsen/logrus" ) @@ -227,7 +227,7 @@ func (mon *PluggableMonitor) Run() (err error) { } }() - if err = mon.sendCommand("HELLO 1 \"arduino-cli " + globals.VersionInfo.VersionString + "\"\n"); err != nil { + if err = mon.sendCommand("HELLO 1 \"arduino-cli " + version.VersionInfo.VersionString + "\"\n"); err != nil { return err } if msg, err := mon.waitMessage(time.Second*10, "hello"); err != nil { diff --git a/cli/cli.go b/cli/cli.go index bc593aa2ffe..9341919f4d0 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -32,7 +32,6 @@ import ( "github.com/arduino/arduino-cli/cli/debug" "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/generatedocs" - "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/cli/lib" "github.com/arduino/arduino-cli/cli/monitor" "github.com/arduino/arduino-cli/cli/outdated" @@ -45,6 +44,7 @@ import ( "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" "github.com/arduino/arduino-cli/inventory" + versioninfo "github.com/arduino/arduino-cli/version" "github.com/fatih/color" "github.com/mattn/go-colorable" "github.com/rifflock/lfshook" @@ -165,7 +165,7 @@ func preRun(cmd *cobra.Command, args []string) { updaterMessageChan <- nil } // Starts checking for updates - currentVersion, err := semver.Parse(globals.VersionInfo.VersionString) + currentVersion, err := semver.Parse(versioninfo.VersionInfo.VersionString) if err != nil { updaterMessageChan <- nil } @@ -240,7 +240,7 @@ func preRun(cmd *cobra.Command, args []string) { logrus.Info("Config file not found, using default values") } - logrus.Info(globals.VersionInfo.Application + " version " + globals.VersionInfo.VersionString) + logrus.Info(versioninfo.VersionInfo.Application + " version " + versioninfo.VersionInfo.VersionString) if outputFormat != "text" { cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { diff --git a/cli/compile/compile.go b/cli/compile/compile.go index cffd4f58971..72ead84a79c 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -27,19 +27,18 @@ import ( "github.com/arduino/arduino-cli/arduino/cores/packagemanager" "github.com/arduino/arduino-cli/cli/arguments" "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/globals" + "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" + "github.com/arduino/arduino-cli/commands/compile" + "github.com/arduino/arduino-cli/commands/upload" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" + rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" + "github.com/arduino/arduino-cli/version" + "github.com/arduino/go-paths-helper" "github.com/fatih/color" "github.com/sirupsen/logrus" - - "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/commands/compile" - "github.com/arduino/arduino-cli/commands/upload" - rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" - "github.com/arduino/go-paths-helper" "github.com/spf13/cobra" ) @@ -343,7 +342,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { if profileArg.String() == "" { msg += "\n" if platform != nil { - suggestion := fmt.Sprintf("`%s core install %s`", globals.VersionInfo.Application, platformErr.Platform) + suggestion := fmt.Sprintf("`%s core install %s`", version.VersionInfo.Application, platformErr.Platform) msg += tr("Try running %s", suggestion) } else { msg += tr("Platform %s is not found in any known index\nMaybe you need to add a 3rd party URL?", platformErr.Platform) diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index 38934dd2a34..9164c4ab30a 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -24,13 +24,13 @@ import ( "syscall" "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/commands/daemon" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" srv_commands "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" srv_debug "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/debug/v1" srv_settings "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/settings/v1" + "github.com/arduino/arduino-cli/version" "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -107,7 +107,7 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { // register the commands service srv_commands.RegisterArduinoCoreServiceServer(s, &daemon.ArduinoCoreServerImpl{ - VersionString: globals.VersionInfo.VersionString, + VersionString: version.VersionInfo.VersionString, }) // Register the settings service diff --git a/cli/globals/globals.go b/cli/globals/globals.go deleted file mode 100644 index f48339ddd72..00000000000 --- a/cli/globals/globals.go +++ /dev/null @@ -1,28 +0,0 @@ -// 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 globals - -import ( - "os" - "path/filepath" - - "github.com/arduino/arduino-cli/version" -) - -var ( - // VersionInfo contains all info injected during build - VersionInfo = version.NewInfo(filepath.Base(os.Args[0])) -) diff --git a/cli/lib/install.go b/cli/lib/install.go index c5ac60f4c5c..91d11ca954a 100644 --- a/cli/lib/install.go +++ b/cli/lib/install.go @@ -23,11 +23,11 @@ import ( "github.com/arduino/arduino-cli/cli/arguments" "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" "github.com/arduino/arduino-cli/configuration" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" + "github.com/arduino/arduino-cli/version" "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -72,9 +72,9 @@ func runInstallCommand(cmd *cobra.Command, args []string) { if zipPath || gitURL { if !configuration.Settings.GetBool("library.enable_unsafe_install") { documentationURL := "https://arduino.github.io/arduino-cli/latest/configuration/#configuration-keys" - _, err := semver.Parse(globals.VersionInfo.VersionString) + _, err := semver.Parse(version.VersionInfo.VersionString) if err == nil { - split := strings.Split(globals.VersionInfo.VersionString, ".") + split := strings.Split(version.VersionInfo.VersionString, ".") documentationURL = fmt.Sprintf("https://arduino.github.io/arduino-cli/%s.%s/configuration/#configuration-keys", split[0], split[1]) } feedback.Fatal(tr("--git-url and --zip-path are disabled by default, for more information see: %v", documentationURL), feedback.ErrGeneric) diff --git a/cli/updater/updater.go b/cli/updater/updater.go index 7cf7220d955..42d4d31d263 100644 --- a/cli/updater/updater.go +++ b/cli/updater/updater.go @@ -23,10 +23,10 @@ import ( "github.com/arduino/arduino-cli/arduino/httpclient" "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" "github.com/arduino/arduino-cli/inventory" + "github.com/arduino/arduino-cli/version" "github.com/fatih/color" semver "go.bug.st/relaxed-semver" ) @@ -69,7 +69,7 @@ func ForceCheckForUpdate(currentVersion *semver.Version) *semver.Version { func NotifyNewVersionIsAvailable(latestVersion string) { msg := fmt.Sprintf("\n\n%s %s → %s\n%s", color.YellowString(tr("A new release of Arduino CLI is available:")), - color.CyanString(globals.VersionInfo.VersionString), + color.CyanString(version.VersionInfo.VersionString), color.CyanString(latestVersion), color.YellowString("https://arduino.github.io/arduino-cli/latest/installation/#latest-packages")) feedback.Warning(msg) diff --git a/cli/upload/upload.go b/cli/upload/upload.go index 8121ec32807..866f625b1c3 100644 --- a/cli/upload/upload.go +++ b/cli/upload/upload.go @@ -27,12 +27,12 @@ import ( "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/cli/arguments" "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/upload" "github.com/arduino/arduino-cli/i18n" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" + "github.com/arduino/arduino-cli/version" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -129,7 +129,7 @@ func runUploadCommand(command *cobra.Command, args []string) { msg += "\n" if platform != nil { - msg += tr("Try running %s", fmt.Sprintf("`%s core install %s`", globals.VersionInfo.Application, platformErr.Platform)) + msg += tr("Try running %s", fmt.Sprintf("`%s core install %s`", version.VersionInfo.Application, platformErr.Platform)) } else { msg += tr("Platform %s is not found in any known index\nMaybe you need to add a 3rd party URL?", platformErr.Platform) } diff --git a/cli/version/version.go b/cli/version/version.go index 9cad16e5142..cd7f6b22177 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -21,9 +21,9 @@ import ( "strings" "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/cli/updater" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/version" "github.com/sirupsen/logrus" "github.com/spf13/cobra" semver "go.bug.st/relaxed-semver" @@ -46,26 +46,27 @@ func NewCommand() *cobra.Command { func runVersionCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino-cli version`") - if strings.Contains(globals.VersionInfo.VersionString, "git-snapshot") || strings.Contains(globals.VersionInfo.VersionString, "nightly") { + + info := version.VersionInfo + if strings.Contains(info.VersionString, "git-snapshot") || strings.Contains(info.VersionString, "nightly") { // We're using a development version, no need to check if there's a // new release available - feedback.PrintResult(globals.VersionInfo) + feedback.PrintResult(info) return } - currentVersion, err := semver.Parse(globals.VersionInfo.VersionString) + currentVersion, err := semver.Parse(info.VersionString) if err != nil { feedback.Fatal(fmt.Sprintf("Error parsing current version: %s", err), feedback.ErrGeneric) } latestVersion := updater.ForceCheckForUpdate(currentVersion) - versionInfo := globals.VersionInfo if feedback.GetFormat() != feedback.Text && latestVersion != nil { // Set this only we managed to get the latest version - versionInfo.LatestVersion = latestVersion.String() + info.LatestVersion = latestVersion.String() } - feedback.PrintResult(versionInfo) + feedback.PrintResult(info) if feedback.GetFormat() == feedback.Text && latestVersion != nil { updater.NotifyNewVersionIsAvailable(latestVersion.String()) diff --git a/commands/instances.go b/commands/instances.go index 259e002cfc3..83aef5ea844 100644 --- a/commands/instances.go +++ b/commands/instances.go @@ -34,10 +34,10 @@ import ( "github.com/arduino/arduino-cli/arduino/resources" "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/arduino/utils" - cliglobals "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" + "github.com/arduino/arduino-cli/version" paths "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" "google.golang.org/grpc/codes" @@ -168,7 +168,7 @@ func Create(req *rpc.CreateRequest, extraUserAgent ...string) (*rpc.CreateRespon } // Create package manager - userAgent := "arduino-cli/" + cliglobals.VersionInfo.VersionString + userAgent := "arduino-cli/" + version.VersionInfo.VersionString for _, ua := range extraUserAgent { userAgent += " " + ua } diff --git a/configuration/network.go b/configuration/network.go index e2e81d937bb..793c67de155 100644 --- a/configuration/network.go +++ b/configuration/network.go @@ -21,7 +21,7 @@ import ( "os" "runtime" - "github.com/arduino/arduino-cli/cli/globals" + "github.com/arduino/arduino-cli/version" "github.com/spf13/viper" ) @@ -41,11 +41,11 @@ func UserAgent(settings *viper.Viper) string { } return fmt.Sprintf("%s/%s%s (%s; %s; %s) Commit:%s%s", - globals.VersionInfo.Application, - globals.VersionInfo.VersionString, + version.VersionInfo.Application, + version.VersionInfo.VersionString, subComponent, runtime.GOARCH, runtime.GOOS, runtime.Version(), - globals.VersionInfo.Commit, + version.VersionInfo.Commit, extendedUA) } diff --git a/version/version.go b/version/version.go index 8302740782f..8a207bfa75d 100644 --- a/version/version.go +++ b/version/version.go @@ -16,9 +16,15 @@ package version import ( + "os" + "path/filepath" + "github.com/arduino/arduino-cli/i18n" ) +// VersionInfo contains all info injected during build +var VersionInfo *Info + var ( defaultVersionString = "0.0.0-git" versionString = "" @@ -63,4 +69,6 @@ func init() { if versionString == "" { versionString = defaultVersionString } + + VersionInfo = NewInfo(filepath.Base(os.Args[0])) } From 744093af01987ead9d4a10788b3951ff371d4a4d Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 12 Dec 2022 12:19:07 +0100 Subject: [PATCH 30/45] Made `cli` package internal --- commands/core/search_test.go | 2 +- configuration/configuration.go | 2 +- docsgen/main.go | 2 +- {cli => internal/cli}/arguments/arguments.go | 2 +- {cli => internal/cli}/arguments/completion.go | 2 +- .../cli}/arguments/discovery_timeout.go | 0 {cli => internal/cli}/arguments/fqbn.go | 2 +- {cli => internal/cli}/arguments/port.go | 2 +- .../cli}/arguments/post_install.go | 0 {cli => internal/cli}/arguments/profiles.go | 0 {cli => internal/cli}/arguments/programmer.go | 0 {cli => internal/cli}/arguments/reference.go | 2 +- .../cli}/arguments/reference_test.go | 2 +- {cli => internal/cli}/arguments/sketch.go | 2 +- .../cli}/arguments/user_fields.go | 2 +- {cli => internal/cli}/board/attach.go | 4 +- {cli => internal/cli}/board/board.go | 0 {cli => internal/cli}/board/details.go | 6 +-- {cli => internal/cli}/board/list.go | 6 +-- {cli => internal/cli}/board/listall.go | 4 +- {cli => internal/cli}/board/search.go | 4 +- .../cli}/burnbootloader/burnbootloader.go | 6 +-- {cli => internal/cli}/cache/cache.go | 0 {cli => internal/cli}/cache/clean.go | 2 +- {cli => internal/cli}/cli.go | 40 +++++++++---------- {cli => internal/cli}/cli_test.go | 0 {cli => internal/cli}/compile/compile.go | 6 +-- .../cli}/completion/completion.go | 2 +- {cli => internal/cli}/config/add.go | 2 +- {cli => internal/cli}/config/config.go | 0 {cli => internal/cli}/config/delete.go | 2 +- {cli => internal/cli}/config/dump.go | 2 +- {cli => internal/cli}/config/init.go | 4 +- {cli => internal/cli}/config/remove.go | 2 +- {cli => internal/cli}/config/set.go | 2 +- {cli => internal/cli}/config/validate.go | 2 +- {cli => internal/cli}/core/core.go | 0 {cli => internal/cli}/core/download.go | 6 +-- {cli => internal/cli}/core/install.go | 6 +-- {cli => internal/cli}/core/list.go | 4 +- {cli => internal/cli}/core/search.go | 4 +- {cli => internal/cli}/core/uninstall.go | 6 +-- {cli => internal/cli}/core/update_index.go | 4 +- {cli => internal/cli}/core/upgrade.go | 6 +-- {cli => internal/cli}/daemon/daemon.go | 2 +- {cli => internal/cli}/daemon/interceptors.go | 0 {cli => internal/cli}/debug/debug.go | 6 +-- {cli => internal/cli}/feedback/errorcodes.go | 0 {cli => internal/cli}/feedback/feedback.go | 0 .../cli}/feedback/feedback_cmd.go | 0 .../cli}/feedback/feedback_test.go | 0 .../cli}/feedback/rpc_progress.go | 0 {cli => internal/cli}/feedback/stdio.go | 0 {cli => internal/cli}/feedback/terminal.go | 0 .../cli}/generatedocs/generatedocs.go | 2 +- {cli => internal/cli}/instance/instance.go | 2 +- {cli => internal/cli}/lib/args.go | 0 {cli => internal/cli}/lib/args_test.go | 0 {cli => internal/cli}/lib/check_deps.go | 6 +-- {cli => internal/cli}/lib/download.go | 6 +-- {cli => internal/cli}/lib/examples.go | 6 +-- {cli => internal/cli}/lib/install.go | 6 +-- {cli => internal/cli}/lib/lib.go | 0 {cli => internal/cli}/lib/list.go | 4 +- {cli => internal/cli}/lib/search.go | 4 +- {cli => internal/cli}/lib/uninstall.go | 6 +-- {cli => internal/cli}/lib/update_index.go | 4 +- {cli => internal/cli}/lib/upgrade.go | 4 +- {cli => internal/cli}/monitor/monitor.go | 6 +-- {cli => internal/cli}/monitor/term.go | 2 +- {cli => internal/cli}/outdated/outdated.go | 6 +-- {cli => internal/cli}/sketch/archive.go | 4 +- {cli => internal/cli}/sketch/new.go | 2 +- {cli => internal/cli}/sketch/sketch.go | 0 .../custom_hardware/TestSketch/TestSketch.ino | 0 .../TestSketch.test.avr.testboard.hex | 0 .../TestSketch2/TestSketch2.ino | 0 .../hardware/test/avr/boards.txt | 0 .../hardware/test/avr/platform.txt | 0 .../hardware/test2/avr/boards.txt | 0 .../hardware/test2/avr/platform.txt | 0 .../cli}/testdata/custom_hardware/test.hex | 0 .../cli}/testdata/libs/MyLib/MyLib.h | 0 .../testdata/libs/MyLib/library.properties | 0 .../testdata/libs/MyLibPre15/MyLibPre15.h | 0 .../testdata/libs/MyLibPre15/utility/util.h | 0 .../MyLibWithWrongVersion.h | 0 .../MyLibWithWrongVersion/library.properties | 0 {cli => internal/cli}/update/update.go | 8 ++-- {cli => internal/cli}/updater/updater.go | 2 +- {cli => internal/cli}/upgrade/upgrade.go | 8 ++-- {cli => internal/cli}/upload/upload.go | 6 +-- {cli => internal/cli}/usage.go | 0 {cli => internal/cli}/version/version.go | 4 +- main.go | 4 +- 95 files changed, 132 insertions(+), 132 deletions(-) rename {cli => internal/cli}/arguments/arguments.go (96%) rename {cli => internal/cli}/arguments/completion.go (99%) rename {cli => internal/cli}/arguments/discovery_timeout.go (100%) rename {cli => internal/cli}/arguments/fqbn.go (98%) rename {cli => internal/cli}/arguments/port.go (99%) rename {cli => internal/cli}/arguments/post_install.go (100%) rename {cli => internal/cli}/arguments/profiles.go (100%) rename {cli => internal/cli}/arguments/programmer.go (100%) rename {cli => internal/cli}/arguments/reference.go (98%) rename {cli => internal/cli}/arguments/reference_test.go (97%) rename {cli => internal/cli}/arguments/sketch.go (97%) rename {cli => internal/cli}/arguments/user_fields.go (95%) rename {cli => internal/cli}/board/attach.go (96%) rename {cli => internal/cli}/board/board.go (100%) rename {cli => internal/cli}/board/details.go (97%) rename {cli => internal/cli}/board/list.go (97%) rename {cli => internal/cli}/board/listall.go (96%) rename {cli => internal/cli}/board/search.go (96%) rename {cli => internal/cli}/burnbootloader/burnbootloader.go (94%) rename {cli => internal/cli}/cache/cache.go (100%) rename {cli => internal/cli}/cache/clean.go (96%) rename {cli => internal/cli}/cli.go (88%) rename {cli => internal/cli}/cli_test.go (100%) rename {cli => internal/cli}/compile/compile.go (99%) rename {cli => internal/cli}/completion/completion.go (97%) rename {cli => internal/cli}/config/add.go (98%) rename {cli => internal/cli}/config/config.go (100%) rename {cli => internal/cli}/config/delete.go (97%) rename {cli => internal/cli}/config/dump.go (96%) rename {cli => internal/cli}/config/init.go (96%) rename {cli => internal/cli}/config/remove.go (97%) rename {cli => internal/cli}/config/set.go (97%) rename {cli => internal/cli}/config/validate.go (97%) rename {cli => internal/cli}/core/core.go (100%) rename {cli => internal/cli}/core/download.go (93%) rename {cli => internal/cli}/core/install.go (95%) rename {cli => internal/cli}/core/list.go (96%) rename {cli => internal/cli}/core/search.go (97%) rename {cli => internal/cli}/core/uninstall.go (93%) rename {cli => internal/cli}/core/update_index.go (94%) rename {cli => internal/cli}/core/upgrade.go (95%) rename {cli => internal/cli}/daemon/daemon.go (99%) rename {cli => internal/cli}/daemon/interceptors.go (100%) rename {cli => internal/cli}/debug/debug.go (96%) rename {cli => internal/cli}/feedback/errorcodes.go (100%) rename {cli => internal/cli}/feedback/feedback.go (100%) rename {cli => internal/cli}/feedback/feedback_cmd.go (100%) rename {cli => internal/cli}/feedback/feedback_test.go (100%) rename {cli => internal/cli}/feedback/rpc_progress.go (100%) rename {cli => internal/cli}/feedback/stdio.go (100%) rename {cli => internal/cli}/feedback/terminal.go (100%) rename {cli => internal/cli}/generatedocs/generatedocs.go (98%) rename {cli => internal/cli}/instance/instance.go (99%) rename {cli => internal/cli}/lib/args.go (100%) rename {cli => internal/cli}/lib/args_test.go (100%) rename {cli => internal/cli}/lib/check_deps.go (95%) rename {cli => internal/cli}/lib/download.go (93%) rename {cli => internal/cli}/lib/examples.go (95%) rename {cli => internal/cli}/lib/install.go (96%) rename {cli => internal/cli}/lib/lib.go (100%) rename {cli => internal/cli}/lib/list.go (97%) rename {cli => internal/cli}/lib/search.go (98%) rename {cli => internal/cli}/lib/uninstall.go (92%) rename {cli => internal/cli}/lib/update_index.go (94%) rename {cli => internal/cli}/lib/upgrade.go (95%) rename {cli => internal/cli}/monitor/monitor.go (97%) rename {cli => internal/cli}/monitor/term.go (95%) rename {cli => internal/cli}/outdated/outdated.go (91%) rename {cli => internal/cli}/sketch/archive.go (96%) rename {cli => internal/cli}/sketch/new.go (97%) rename {cli => internal/cli}/sketch/sketch.go (100%) rename {cli => internal/cli}/testdata/custom_hardware/TestSketch/TestSketch.ino (100%) rename {cli => internal/cli}/testdata/custom_hardware/TestSketch/TestSketch.test.avr.testboard.hex (100%) rename {cli => internal/cli}/testdata/custom_hardware/TestSketch2/TestSketch2.ino (100%) rename {cli => internal/cli}/testdata/custom_hardware/hardware/test/avr/boards.txt (100%) rename {cli => internal/cli}/testdata/custom_hardware/hardware/test/avr/platform.txt (100%) rename {cli => internal/cli}/testdata/custom_hardware/hardware/test2/avr/boards.txt (100%) rename {cli => internal/cli}/testdata/custom_hardware/hardware/test2/avr/platform.txt (100%) rename {cli => internal/cli}/testdata/custom_hardware/test.hex (100%) rename {cli => internal/cli}/testdata/libs/MyLib/MyLib.h (100%) rename {cli => internal/cli}/testdata/libs/MyLib/library.properties (100%) rename {cli => internal/cli}/testdata/libs/MyLibPre15/MyLibPre15.h (100%) rename {cli => internal/cli}/testdata/libs/MyLibPre15/utility/util.h (100%) rename {cli => internal/cli}/testdata/libs/MyLibWithWrongVersion/MyLibWithWrongVersion.h (100%) rename {cli => internal/cli}/testdata/libs/MyLibWithWrongVersion/library.properties (100%) rename {cli => internal/cli}/update/update.go (88%) rename {cli => internal/cli}/updater/updater.go (98%) rename {cli => internal/cli}/upgrade/upgrade.go (88%) rename {cli => internal/cli}/upload/upload.go (97%) rename {cli => internal/cli}/usage.go (100%) rename {cli => internal/cli}/version/version.go (95%) diff --git a/commands/core/search_test.go b/commands/core/search_test.go index 8d65c39096a..3fb86782457 100644 --- a/commands/core/search_test.go +++ b/commands/core/search_test.go @@ -19,8 +19,8 @@ import ( "os" "testing" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/go-paths-helper" "github.com/stretchr/testify/require" diff --git a/configuration/configuration.go b/configuration/configuration.go index cc742146cd9..0afcd015bf3 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -21,8 +21,8 @@ import ( "runtime" "strings" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/feedback" paths "github.com/arduino/go-paths-helper" "github.com/arduino/go-win32-utils" "github.com/spf13/cobra" diff --git a/docsgen/main.go b/docsgen/main.go index af85af55c48..aaac2d3bd0e 100644 --- a/docsgen/main.go +++ b/docsgen/main.go @@ -18,8 +18,8 @@ package main import ( "os" - "github.com/arduino/arduino-cli/cli" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli" "github.com/spf13/cobra/doc" ) diff --git a/cli/arguments/arguments.go b/internal/cli/arguments/arguments.go similarity index 96% rename from cli/arguments/arguments.go rename to internal/cli/arguments/arguments.go index 5526d30a6d3..e3aa6a8dded 100644 --- a/cli/arguments/arguments.go +++ b/internal/cli/arguments/arguments.go @@ -18,8 +18,8 @@ package arguments import ( "strings" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/spf13/cobra" ) diff --git a/cli/arguments/completion.go b/internal/cli/arguments/completion.go similarity index 99% rename from cli/arguments/completion.go rename to internal/cli/arguments/completion.go index 06e35e7d6c2..60844ed03cd 100644 --- a/cli/arguments/completion.go +++ b/internal/cli/arguments/completion.go @@ -4,11 +4,11 @@ import ( "context" "github.com/arduino/arduino-cli/arduino/cores" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/board" "github.com/arduino/arduino-cli/commands/core" "github.com/arduino/arduino-cli/commands/lib" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" ) diff --git a/cli/arguments/discovery_timeout.go b/internal/cli/arguments/discovery_timeout.go similarity index 100% rename from cli/arguments/discovery_timeout.go rename to internal/cli/arguments/discovery_timeout.go diff --git a/cli/arguments/fqbn.go b/internal/cli/arguments/fqbn.go similarity index 98% rename from cli/arguments/fqbn.go rename to internal/cli/arguments/fqbn.go index 973aa0aa3ac..4d81a3c86b8 100644 --- a/cli/arguments/fqbn.go +++ b/internal/cli/arguments/fqbn.go @@ -20,7 +20,7 @@ import ( "github.com/arduino/arduino-cli/arduino" "github.com/arduino/arduino-cli/arduino/sketch" - "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/feedback" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/spf13/cobra" ) diff --git a/cli/arguments/port.go b/internal/cli/arguments/port.go similarity index 99% rename from cli/arguments/port.go rename to internal/cli/arguments/port.go index 94c62088bf7..eb90f092302 100644 --- a/cli/arguments/port.go +++ b/internal/cli/arguments/port.go @@ -22,9 +22,9 @@ 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/cli/feedback" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/board" + "github.com/arduino/arduino-cli/internal/cli/feedback" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/arguments/post_install.go b/internal/cli/arguments/post_install.go similarity index 100% rename from cli/arguments/post_install.go rename to internal/cli/arguments/post_install.go diff --git a/cli/arguments/profiles.go b/internal/cli/arguments/profiles.go similarity index 100% rename from cli/arguments/profiles.go rename to internal/cli/arguments/profiles.go diff --git a/cli/arguments/programmer.go b/internal/cli/arguments/programmer.go similarity index 100% rename from cli/arguments/programmer.go rename to internal/cli/arguments/programmer.go diff --git a/cli/arguments/reference.go b/internal/cli/arguments/reference.go similarity index 98% rename from cli/arguments/reference.go rename to internal/cli/arguments/reference.go index b06a3ef52c5..cdfdba7f496 100644 --- a/cli/arguments/reference.go +++ b/internal/cli/arguments/reference.go @@ -20,8 +20,8 @@ import ( "strings" "github.com/arduino/arduino-cli/arduino" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" ) diff --git a/cli/arguments/reference_test.go b/internal/cli/arguments/reference_test.go similarity index 97% rename from cli/arguments/reference_test.go rename to internal/cli/arguments/reference_test.go index 9895ae89e90..29f20300c78 100644 --- a/cli/arguments/reference_test.go +++ b/internal/cli/arguments/reference_test.go @@ -18,8 +18,8 @@ package arguments_test import ( "testing" - "github.com/arduino/arduino-cli/cli/arguments" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/arguments" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/cli/arguments/sketch.go b/internal/cli/arguments/sketch.go similarity index 97% rename from cli/arguments/sketch.go rename to internal/cli/arguments/sketch.go index 40a85a0ed87..974426044c6 100644 --- a/cli/arguments/sketch.go +++ b/internal/cli/arguments/sketch.go @@ -19,7 +19,7 @@ import ( "fmt" "github.com/arduino/arduino-cli/arduino/sketch" - "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" ) diff --git a/cli/arguments/user_fields.go b/internal/cli/arguments/user_fields.go similarity index 95% rename from cli/arguments/user_fields.go rename to internal/cli/arguments/user_fields.go index d1287c0509f..8f799d4c650 100644 --- a/cli/arguments/user_fields.go +++ b/internal/cli/arguments/user_fields.go @@ -16,7 +16,7 @@ package arguments import ( - "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/feedback" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" ) diff --git a/cli/board/attach.go b/internal/cli/board/attach.go similarity index 96% rename from cli/board/attach.go rename to internal/cli/board/attach.go index 46764c3f45a..d701ad15e8a 100644 --- a/cli/board/attach.go +++ b/internal/cli/board/attach.go @@ -19,8 +19,8 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/spf13/cobra" ) diff --git a/cli/board/board.go b/internal/cli/board/board.go similarity index 100% rename from cli/board/board.go rename to internal/cli/board/board.go diff --git a/cli/board/details.go b/internal/cli/board/details.go similarity index 97% rename from cli/board/details.go rename to internal/cli/board/details.go index 98ef0688a68..b8b710b1878 100644 --- a/cli/board/details.go +++ b/internal/cli/board/details.go @@ -20,10 +20,10 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/board" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" "github.com/fatih/color" diff --git a/cli/board/list.go b/internal/cli/board/list.go similarity index 97% rename from cli/board/list.go rename to internal/cli/board/list.go index 41052ded7b2..2ae365e145b 100644 --- a/cli/board/list.go +++ b/internal/cli/board/list.go @@ -21,10 +21,10 @@ import ( "sort" "github.com/arduino/arduino-cli/arduino/cores" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/board" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" "github.com/sirupsen/logrus" diff --git a/cli/board/listall.go b/internal/cli/board/listall.go similarity index 96% rename from cli/board/listall.go rename to internal/cli/board/listall.go index ce47f31dd22..0f47cba710a 100644 --- a/cli/board/listall.go +++ b/internal/cli/board/listall.go @@ -21,9 +21,9 @@ import ( "os" "sort" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/board" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" "github.com/sirupsen/logrus" diff --git a/cli/board/search.go b/internal/cli/board/search.go similarity index 96% rename from cli/board/search.go rename to internal/cli/board/search.go index dcbcb053930..0225374bc31 100644 --- a/cli/board/search.go +++ b/internal/cli/board/search.go @@ -22,9 +22,9 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/board" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" "github.com/sirupsen/logrus" diff --git a/cli/burnbootloader/burnbootloader.go b/internal/cli/burnbootloader/burnbootloader.go similarity index 94% rename from cli/burnbootloader/burnbootloader.go rename to internal/cli/burnbootloader/burnbootloader.go index d7bc7319a64..1f32e930c2c 100644 --- a/cli/burnbootloader/burnbootloader.go +++ b/internal/cli/burnbootloader/burnbootloader.go @@ -19,11 +19,11 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/upload" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/cache/cache.go b/internal/cli/cache/cache.go similarity index 100% rename from cli/cache/cache.go rename to internal/cli/cache/cache.go diff --git a/cli/cache/clean.go b/internal/cli/cache/clean.go similarity index 96% rename from cli/cache/clean.go rename to internal/cli/cache/clean.go index 2acb39448de..f5fbb18c4ec 100644 --- a/cli/cache/clean.go +++ b/internal/cli/cache/clean.go @@ -18,8 +18,8 @@ package cache import ( "os" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cli/cli.go b/internal/cli/cli.go similarity index 88% rename from cli/cli.go rename to internal/cli/cli.go index 9341919f4d0..61a33e75464 100644 --- a/cli/cli.go +++ b/internal/cli/cli.go @@ -21,28 +21,28 @@ import ( "os" "strings" - "github.com/arduino/arduino-cli/cli/board" - "github.com/arduino/arduino-cli/cli/burnbootloader" - "github.com/arduino/arduino-cli/cli/cache" - "github.com/arduino/arduino-cli/cli/compile" - "github.com/arduino/arduino-cli/cli/completion" - "github.com/arduino/arduino-cli/cli/config" - "github.com/arduino/arduino-cli/cli/core" - "github.com/arduino/arduino-cli/cli/daemon" - "github.com/arduino/arduino-cli/cli/debug" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/generatedocs" - "github.com/arduino/arduino-cli/cli/lib" - "github.com/arduino/arduino-cli/cli/monitor" - "github.com/arduino/arduino-cli/cli/outdated" - "github.com/arduino/arduino-cli/cli/sketch" - "github.com/arduino/arduino-cli/cli/update" - "github.com/arduino/arduino-cli/cli/updater" - "github.com/arduino/arduino-cli/cli/upgrade" - "github.com/arduino/arduino-cli/cli/upload" - "github.com/arduino/arduino-cli/cli/version" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/board" + "github.com/arduino/arduino-cli/internal/cli/burnbootloader" + "github.com/arduino/arduino-cli/internal/cli/cache" + "github.com/arduino/arduino-cli/internal/cli/compile" + "github.com/arduino/arduino-cli/internal/cli/completion" + "github.com/arduino/arduino-cli/internal/cli/config" + "github.com/arduino/arduino-cli/internal/cli/core" + "github.com/arduino/arduino-cli/internal/cli/daemon" + "github.com/arduino/arduino-cli/internal/cli/debug" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/generatedocs" + "github.com/arduino/arduino-cli/internal/cli/lib" + "github.com/arduino/arduino-cli/internal/cli/monitor" + "github.com/arduino/arduino-cli/internal/cli/outdated" + "github.com/arduino/arduino-cli/internal/cli/sketch" + "github.com/arduino/arduino-cli/internal/cli/update" + "github.com/arduino/arduino-cli/internal/cli/updater" + "github.com/arduino/arduino-cli/internal/cli/upgrade" + "github.com/arduino/arduino-cli/internal/cli/upload" + "github.com/arduino/arduino-cli/internal/cli/version" "github.com/arduino/arduino-cli/inventory" versioninfo "github.com/arduino/arduino-cli/version" "github.com/fatih/color" diff --git a/cli/cli_test.go b/internal/cli/cli_test.go similarity index 100% rename from cli/cli_test.go rename to internal/cli/cli_test.go diff --git a/cli/compile/compile.go b/internal/cli/compile/compile.go similarity index 99% rename from cli/compile/compile.go rename to internal/cli/compile/compile.go index 72ead84a79c..55cd345a255 100644 --- a/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -25,14 +25,14 @@ import ( "github.com/arduino/arduino-cli/arduino" "github.com/arduino/arduino-cli/arduino/cores/packagemanager" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/compile" "github.com/arduino/arduino-cli/commands/upload" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" "github.com/arduino/arduino-cli/version" diff --git a/cli/completion/completion.go b/internal/cli/completion/completion.go similarity index 97% rename from cli/completion/completion.go rename to internal/cli/completion/completion.go index 92bc4f292c0..d119d57f120 100644 --- a/cli/completion/completion.go +++ b/internal/cli/completion/completion.go @@ -18,8 +18,8 @@ package completion import ( "os" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cli/config/add.go b/internal/cli/config/add.go similarity index 98% rename from cli/config/add.go rename to internal/cli/config/add.go index 171deb287cc..d375a0c578e 100644 --- a/cli/config/add.go +++ b/internal/cli/config/add.go @@ -19,8 +19,8 @@ import ( "os" "reflect" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cli/config/config.go b/internal/cli/config/config.go similarity index 100% rename from cli/config/config.go rename to internal/cli/config/config.go diff --git a/cli/config/delete.go b/internal/cli/config/delete.go similarity index 97% rename from cli/config/delete.go rename to internal/cli/config/delete.go index c5f761dcf53..6e3cf58d6f1 100644 --- a/cli/config/delete.go +++ b/internal/cli/config/delete.go @@ -19,8 +19,8 @@ import ( "os" "strings" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" diff --git a/cli/config/dump.go b/internal/cli/config/dump.go similarity index 96% rename from cli/config/dump.go rename to internal/cli/config/dump.go index 748b51a2b81..cb365d1c57e 100644 --- a/cli/config/dump.go +++ b/internal/cli/config/dump.go @@ -18,8 +18,8 @@ package config import ( "os" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "gopkg.in/yaml.v2" diff --git a/cli/config/init.go b/internal/cli/config/init.go similarity index 96% rename from cli/config/init.go rename to internal/cli/config/init.go index b38f9d4dc21..42073c32e60 100644 --- a/cli/config/init.go +++ b/internal/cli/config/init.go @@ -18,9 +18,9 @@ package config import ( "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/config/remove.go b/internal/cli/config/remove.go similarity index 97% rename from cli/config/remove.go rename to internal/cli/config/remove.go index 4ddff81af60..1be518448e4 100644 --- a/cli/config/remove.go +++ b/internal/cli/config/remove.go @@ -19,8 +19,8 @@ import ( "os" "reflect" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cli/config/set.go b/internal/cli/config/set.go similarity index 97% rename from cli/config/set.go rename to internal/cli/config/set.go index f8f882e628d..f620fa183f5 100644 --- a/cli/config/set.go +++ b/internal/cli/config/set.go @@ -20,8 +20,8 @@ import ( "reflect" "strconv" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cli/config/validate.go b/internal/cli/config/validate.go similarity index 97% rename from cli/config/validate.go rename to internal/cli/config/validate.go index c7a3af1e821..f494bfaac0b 100644 --- a/cli/config/validate.go +++ b/internal/cli/config/validate.go @@ -19,7 +19,7 @@ import ( "fmt" "reflect" - "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/feedback" ) var validMap = map[string]reflect.Kind{ diff --git a/cli/core/core.go b/internal/cli/core/core.go similarity index 100% rename from cli/core/core.go rename to internal/cli/core/core.go diff --git a/cli/core/download.go b/internal/cli/core/download.go similarity index 93% rename from cli/core/download.go rename to internal/cli/core/download.go index a828ea40fb4..daa87f04ef2 100644 --- a/cli/core/download.go +++ b/internal/cli/core/download.go @@ -20,10 +20,10 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/core/install.go b/internal/cli/core/install.go similarity index 95% rename from cli/core/install.go rename to internal/cli/core/install.go index d787e8be6a5..9aa367740c5 100644 --- a/cli/core/install.go +++ b/internal/cli/core/install.go @@ -20,10 +20,10 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/core/list.go b/internal/cli/core/list.go similarity index 96% rename from cli/core/list.go rename to internal/cli/core/list.go index a60a672d4af..b53a75e25b1 100644 --- a/cli/core/list.go +++ b/internal/cli/core/list.go @@ -19,9 +19,9 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" "github.com/sirupsen/logrus" diff --git a/cli/core/search.go b/internal/cli/core/search.go similarity index 97% rename from cli/core/search.go rename to internal/cli/core/search.go index b4418bb1037..ce42c1b41ac 100644 --- a/cli/core/search.go +++ b/internal/cli/core/search.go @@ -25,11 +25,11 @@ import ( "github.com/arduino/arduino-cli/arduino/globals" "github.com/arduino/arduino-cli/arduino/utils" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/core" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" "github.com/sirupsen/logrus" diff --git a/cli/core/uninstall.go b/internal/cli/core/uninstall.go similarity index 93% rename from cli/core/uninstall.go rename to internal/cli/core/uninstall.go index 260fa009871..fb31d4ea1b5 100644 --- a/cli/core/uninstall.go +++ b/internal/cli/core/uninstall.go @@ -20,10 +20,10 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/core/update_index.go b/internal/cli/core/update_index.go similarity index 94% rename from cli/core/update_index.go rename to internal/cli/core/update_index.go index 034e79642f7..6274e39cde9 100644 --- a/cli/core/update_index.go +++ b/internal/cli/core/update_index.go @@ -19,9 +19,9 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/core/upgrade.go b/internal/cli/core/upgrade.go similarity index 95% rename from cli/core/upgrade.go rename to internal/cli/core/upgrade.go index 96090010b27..bee890dcac5 100644 --- a/cli/core/upgrade.go +++ b/internal/cli/core/upgrade.go @@ -22,10 +22,10 @@ import ( "os" "github.com/arduino/arduino-cli/arduino" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/core" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/daemon/daemon.go b/internal/cli/daemon/daemon.go similarity index 99% rename from cli/daemon/daemon.go rename to internal/cli/daemon/daemon.go index 9164c4ab30a..16c6d9af83a 100644 --- a/cli/daemon/daemon.go +++ b/internal/cli/daemon/daemon.go @@ -23,10 +23,10 @@ import ( "strings" "syscall" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/commands/daemon" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/feedback" srv_commands "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" srv_debug "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/debug/v1" srv_settings "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/settings/v1" diff --git a/cli/daemon/interceptors.go b/internal/cli/daemon/interceptors.go similarity index 100% rename from cli/daemon/interceptors.go rename to internal/cli/daemon/interceptors.go diff --git a/cli/debug/debug.go b/internal/cli/debug/debug.go similarity index 96% rename from cli/debug/debug.go rename to internal/cli/debug/debug.go index ca9f43e0caf..3078fd8d1c8 100644 --- a/cli/debug/debug.go +++ b/internal/cli/debug/debug.go @@ -21,11 +21,11 @@ import ( "os/signal" "sort" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/debug" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" dbg "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/debug/v1" "github.com/arduino/arduino-cli/table" "github.com/arduino/go-properties-orderedmap" diff --git a/cli/feedback/errorcodes.go b/internal/cli/feedback/errorcodes.go similarity index 100% rename from cli/feedback/errorcodes.go rename to internal/cli/feedback/errorcodes.go diff --git a/cli/feedback/feedback.go b/internal/cli/feedback/feedback.go similarity index 100% rename from cli/feedback/feedback.go rename to internal/cli/feedback/feedback.go diff --git a/cli/feedback/feedback_cmd.go b/internal/cli/feedback/feedback_cmd.go similarity index 100% rename from cli/feedback/feedback_cmd.go rename to internal/cli/feedback/feedback_cmd.go diff --git a/cli/feedback/feedback_test.go b/internal/cli/feedback/feedback_test.go similarity index 100% rename from cli/feedback/feedback_test.go rename to internal/cli/feedback/feedback_test.go diff --git a/cli/feedback/rpc_progress.go b/internal/cli/feedback/rpc_progress.go similarity index 100% rename from cli/feedback/rpc_progress.go rename to internal/cli/feedback/rpc_progress.go diff --git a/cli/feedback/stdio.go b/internal/cli/feedback/stdio.go similarity index 100% rename from cli/feedback/stdio.go rename to internal/cli/feedback/stdio.go diff --git a/cli/feedback/terminal.go b/internal/cli/feedback/terminal.go similarity index 100% rename from cli/feedback/terminal.go rename to internal/cli/feedback/terminal.go diff --git a/cli/generatedocs/generatedocs.go b/internal/cli/generatedocs/generatedocs.go similarity index 98% rename from cli/generatedocs/generatedocs.go rename to internal/cli/generatedocs/generatedocs.go index 70e5bb5a1f4..0be07a768cb 100644 --- a/cli/generatedocs/generatedocs.go +++ b/internal/cli/generatedocs/generatedocs.go @@ -19,8 +19,8 @@ import ( "os" "path/filepath" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" diff --git a/cli/instance/instance.go b/internal/cli/instance/instance.go similarity index 99% rename from cli/instance/instance.go rename to internal/cli/instance/instance.go index 4e2fd19b0b7..2c1ebaa7155 100644 --- a/cli/instance/instance.go +++ b/internal/cli/instance/instance.go @@ -18,10 +18,10 @@ package instance import ( "context" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/feedback" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/go-paths-helper" ) diff --git a/cli/lib/args.go b/internal/cli/lib/args.go similarity index 100% rename from cli/lib/args.go rename to internal/cli/lib/args.go diff --git a/cli/lib/args_test.go b/internal/cli/lib/args_test.go similarity index 100% rename from cli/lib/args_test.go rename to internal/cli/lib/args_test.go diff --git a/cli/lib/check_deps.go b/internal/cli/lib/check_deps.go similarity index 95% rename from cli/lib/check_deps.go rename to internal/cli/lib/check_deps.go index f3c91308420..5f92a207ff4 100644 --- a/cli/lib/check_deps.go +++ b/internal/cli/lib/check_deps.go @@ -21,10 +21,10 @@ import ( "os" "sort" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/fatih/color" "github.com/sirupsen/logrus" diff --git a/cli/lib/download.go b/internal/cli/lib/download.go similarity index 93% rename from cli/lib/download.go rename to internal/cli/lib/download.go index 5ca4669ecdf..3616584a91d 100644 --- a/cli/lib/download.go +++ b/internal/cli/lib/download.go @@ -20,10 +20,10 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/lib/examples.go b/internal/cli/lib/examples.go similarity index 95% rename from cli/lib/examples.go rename to internal/cli/lib/examples.go index 4f4439ecb25..a6564ec6378 100644 --- a/cli/lib/examples.go +++ b/internal/cli/lib/examples.go @@ -22,10 +22,10 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/go-paths-helper" "github.com/fatih/color" diff --git a/cli/lib/install.go b/internal/cli/lib/install.go similarity index 96% rename from cli/lib/install.go rename to internal/cli/lib/install.go index 91d11ca954a..bb6ff217fda 100644 --- a/cli/lib/install.go +++ b/internal/cli/lib/install.go @@ -21,11 +21,11 @@ import ( "os" "strings" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" "github.com/arduino/arduino-cli/configuration" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/version" "github.com/arduino/go-paths-helper" diff --git a/cli/lib/lib.go b/internal/cli/lib/lib.go similarity index 100% rename from cli/lib/lib.go rename to internal/cli/lib/lib.go diff --git a/cli/lib/list.go b/internal/cli/lib/list.go similarity index 97% rename from cli/lib/list.go rename to internal/cli/lib/list.go index 90258df4a5f..ce0cf478c30 100644 --- a/cli/lib/list.go +++ b/internal/cli/lib/list.go @@ -22,9 +22,9 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" "github.com/sirupsen/logrus" diff --git a/cli/lib/search.go b/internal/cli/lib/search.go similarity index 98% rename from cli/lib/search.go rename to internal/cli/lib/search.go index 5e87bfdbda9..af56994d4cc 100644 --- a/cli/lib/search.go +++ b/internal/cli/lib/search.go @@ -22,10 +22,10 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/lib" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/lib/uninstall.go b/internal/cli/lib/uninstall.go similarity index 92% rename from cli/lib/uninstall.go rename to internal/cli/lib/uninstall.go index 96907e679c1..897b0203320 100644 --- a/cli/lib/uninstall.go +++ b/internal/cli/lib/uninstall.go @@ -20,10 +20,10 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/lib/update_index.go b/internal/cli/lib/update_index.go similarity index 94% rename from cli/lib/update_index.go rename to internal/cli/lib/update_index.go index 741b051cca6..57bb5558a2e 100644 --- a/cli/lib/update_index.go +++ b/internal/cli/lib/update_index.go @@ -19,9 +19,9 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/lib/upgrade.go b/internal/cli/lib/upgrade.go similarity index 95% rename from cli/lib/upgrade.go rename to internal/cli/lib/upgrade.go index 6acddeaa9b9..5375e5d6795 100644 --- a/cli/lib/upgrade.go +++ b/internal/cli/lib/upgrade.go @@ -20,9 +20,9 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/lib" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/monitor/monitor.go b/internal/cli/monitor/monitor.go similarity index 97% rename from cli/monitor/monitor.go rename to internal/cli/monitor/monitor.go index 770f9a210f5..af7037e78c1 100644 --- a/cli/monitor/monitor.go +++ b/internal/cli/monitor/monitor.go @@ -24,12 +24,12 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/monitor" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/table" "github.com/fatih/color" diff --git a/cli/monitor/term.go b/internal/cli/monitor/term.go similarity index 95% rename from cli/monitor/term.go rename to internal/cli/monitor/term.go index 0939e4bcb8c..34e444b5591 100644 --- a/cli/monitor/term.go +++ b/internal/cli/monitor/term.go @@ -18,7 +18,7 @@ package monitor import ( "io" - "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/feedback" ) type stdInOut struct { diff --git a/cli/outdated/outdated.go b/internal/cli/outdated/outdated.go similarity index 91% rename from cli/outdated/outdated.go rename to internal/cli/outdated/outdated.go index 0747e7ef5f4..35dfab911da 100644 --- a/cli/outdated/outdated.go +++ b/internal/cli/outdated/outdated.go @@ -18,10 +18,10 @@ package outdated import ( "os" - "github.com/arduino/arduino-cli/cli/core" - "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/lib" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/core" + "github.com/arduino/arduino-cli/internal/cli/instance" + "github.com/arduino/arduino-cli/internal/cli/lib" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cli/sketch/archive.go b/internal/cli/sketch/archive.go similarity index 96% rename from cli/sketch/archive.go rename to internal/cli/sketch/archive.go index b507d587d8c..9410bb0d0c6 100644 --- a/cli/sketch/archive.go +++ b/internal/cli/sketch/archive.go @@ -20,9 +20,9 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" sk "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/arduino/go-paths-helper" "github.com/sirupsen/logrus" diff --git a/cli/sketch/new.go b/internal/cli/sketch/new.go similarity index 97% rename from cli/sketch/new.go rename to internal/cli/sketch/new.go index 18a1c86852b..3b361f3d8ea 100644 --- a/cli/sketch/new.go +++ b/internal/cli/sketch/new.go @@ -21,8 +21,8 @@ import ( "strings" "github.com/arduino/arduino-cli/arduino/globals" - "github.com/arduino/arduino-cli/cli/feedback" sk "github.com/arduino/arduino-cli/commands/sketch" + "github.com/arduino/arduino-cli/internal/cli/feedback" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" paths "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" diff --git a/cli/sketch/sketch.go b/internal/cli/sketch/sketch.go similarity index 100% rename from cli/sketch/sketch.go rename to internal/cli/sketch/sketch.go diff --git a/cli/testdata/custom_hardware/TestSketch/TestSketch.ino b/internal/cli/testdata/custom_hardware/TestSketch/TestSketch.ino similarity index 100% rename from cli/testdata/custom_hardware/TestSketch/TestSketch.ino rename to internal/cli/testdata/custom_hardware/TestSketch/TestSketch.ino diff --git a/cli/testdata/custom_hardware/TestSketch/TestSketch.test.avr.testboard.hex b/internal/cli/testdata/custom_hardware/TestSketch/TestSketch.test.avr.testboard.hex similarity index 100% rename from cli/testdata/custom_hardware/TestSketch/TestSketch.test.avr.testboard.hex rename to internal/cli/testdata/custom_hardware/TestSketch/TestSketch.test.avr.testboard.hex diff --git a/cli/testdata/custom_hardware/TestSketch2/TestSketch2.ino b/internal/cli/testdata/custom_hardware/TestSketch2/TestSketch2.ino similarity index 100% rename from cli/testdata/custom_hardware/TestSketch2/TestSketch2.ino rename to internal/cli/testdata/custom_hardware/TestSketch2/TestSketch2.ino diff --git a/cli/testdata/custom_hardware/hardware/test/avr/boards.txt b/internal/cli/testdata/custom_hardware/hardware/test/avr/boards.txt similarity index 100% rename from cli/testdata/custom_hardware/hardware/test/avr/boards.txt rename to internal/cli/testdata/custom_hardware/hardware/test/avr/boards.txt diff --git a/cli/testdata/custom_hardware/hardware/test/avr/platform.txt b/internal/cli/testdata/custom_hardware/hardware/test/avr/platform.txt similarity index 100% rename from cli/testdata/custom_hardware/hardware/test/avr/platform.txt rename to internal/cli/testdata/custom_hardware/hardware/test/avr/platform.txt diff --git a/cli/testdata/custom_hardware/hardware/test2/avr/boards.txt b/internal/cli/testdata/custom_hardware/hardware/test2/avr/boards.txt similarity index 100% rename from cli/testdata/custom_hardware/hardware/test2/avr/boards.txt rename to internal/cli/testdata/custom_hardware/hardware/test2/avr/boards.txt diff --git a/cli/testdata/custom_hardware/hardware/test2/avr/platform.txt b/internal/cli/testdata/custom_hardware/hardware/test2/avr/platform.txt similarity index 100% rename from cli/testdata/custom_hardware/hardware/test2/avr/platform.txt rename to internal/cli/testdata/custom_hardware/hardware/test2/avr/platform.txt diff --git a/cli/testdata/custom_hardware/test.hex b/internal/cli/testdata/custom_hardware/test.hex similarity index 100% rename from cli/testdata/custom_hardware/test.hex rename to internal/cli/testdata/custom_hardware/test.hex diff --git a/cli/testdata/libs/MyLib/MyLib.h b/internal/cli/testdata/libs/MyLib/MyLib.h similarity index 100% rename from cli/testdata/libs/MyLib/MyLib.h rename to internal/cli/testdata/libs/MyLib/MyLib.h diff --git a/cli/testdata/libs/MyLib/library.properties b/internal/cli/testdata/libs/MyLib/library.properties similarity index 100% rename from cli/testdata/libs/MyLib/library.properties rename to internal/cli/testdata/libs/MyLib/library.properties diff --git a/cli/testdata/libs/MyLibPre15/MyLibPre15.h b/internal/cli/testdata/libs/MyLibPre15/MyLibPre15.h similarity index 100% rename from cli/testdata/libs/MyLibPre15/MyLibPre15.h rename to internal/cli/testdata/libs/MyLibPre15/MyLibPre15.h diff --git a/cli/testdata/libs/MyLibPre15/utility/util.h b/internal/cli/testdata/libs/MyLibPre15/utility/util.h similarity index 100% rename from cli/testdata/libs/MyLibPre15/utility/util.h rename to internal/cli/testdata/libs/MyLibPre15/utility/util.h diff --git a/cli/testdata/libs/MyLibWithWrongVersion/MyLibWithWrongVersion.h b/internal/cli/testdata/libs/MyLibWithWrongVersion/MyLibWithWrongVersion.h similarity index 100% rename from cli/testdata/libs/MyLibWithWrongVersion/MyLibWithWrongVersion.h rename to internal/cli/testdata/libs/MyLibWithWrongVersion/MyLibWithWrongVersion.h diff --git a/cli/testdata/libs/MyLibWithWrongVersion/library.properties b/internal/cli/testdata/libs/MyLibWithWrongVersion/library.properties similarity index 100% rename from cli/testdata/libs/MyLibWithWrongVersion/library.properties rename to internal/cli/testdata/libs/MyLibWithWrongVersion/library.properties diff --git a/cli/update/update.go b/internal/cli/update/update.go similarity index 88% rename from cli/update/update.go rename to internal/cli/update/update.go index 45ef225fe36..7733745c2e2 100644 --- a/cli/update/update.go +++ b/internal/cli/update/update.go @@ -18,11 +18,11 @@ package update import ( "os" - "github.com/arduino/arduino-cli/cli/core" - "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/lib" - "github.com/arduino/arduino-cli/cli/outdated" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/core" + "github.com/arduino/arduino-cli/internal/cli/instance" + "github.com/arduino/arduino-cli/internal/cli/lib" + "github.com/arduino/arduino-cli/internal/cli/outdated" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cli/updater/updater.go b/internal/cli/updater/updater.go similarity index 98% rename from cli/updater/updater.go rename to internal/cli/updater/updater.go index 42d4d31d263..09b9ab18125 100644 --- a/cli/updater/updater.go +++ b/internal/cli/updater/updater.go @@ -22,9 +22,9 @@ import ( "time" "github.com/arduino/arduino-cli/arduino/httpclient" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/arduino/arduino-cli/inventory" "github.com/arduino/arduino-cli/version" "github.com/fatih/color" diff --git a/cli/upgrade/upgrade.go b/internal/cli/upgrade/upgrade.go similarity index 88% rename from cli/upgrade/upgrade.go rename to internal/cli/upgrade/upgrade.go index bedb3ee359f..0cc93735d43 100644 --- a/cli/upgrade/upgrade.go +++ b/internal/cli/upgrade/upgrade.go @@ -18,11 +18,11 @@ package upgrade import ( "os" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/core" - "github.com/arduino/arduino-cli/cli/instance" - "github.com/arduino/arduino-cli/cli/lib" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/core" + "github.com/arduino/arduino-cli/internal/cli/instance" + "github.com/arduino/arduino-cli/internal/cli/lib" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) diff --git a/cli/upload/upload.go b/internal/cli/upload/upload.go similarity index 97% rename from cli/upload/upload.go rename to internal/cli/upload/upload.go index 866f625b1c3..9c194a11239 100644 --- a/cli/upload/upload.go +++ b/internal/cli/upload/upload.go @@ -25,12 +25,12 @@ import ( "github.com/arduino/arduino-cli/arduino" "github.com/arduino/arduino-cli/arduino/cores/packagemanager" "github.com/arduino/arduino-cli/arduino/sketch" - "github.com/arduino/arduino-cli/cli/arguments" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/upload" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/arguments" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/instance" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" "github.com/arduino/arduino-cli/version" "github.com/sirupsen/logrus" diff --git a/cli/usage.go b/internal/cli/usage.go similarity index 100% rename from cli/usage.go rename to internal/cli/usage.go diff --git a/cli/version/version.go b/internal/cli/version/version.go similarity index 95% rename from cli/version/version.go rename to internal/cli/version/version.go index cd7f6b22177..e4b52155ec7 100644 --- a/cli/version/version.go +++ b/internal/cli/version/version.go @@ -20,9 +20,9 @@ import ( "os" "strings" - "github.com/arduino/arduino-cli/cli/feedback" - "github.com/arduino/arduino-cli/cli/updater" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli/feedback" + "github.com/arduino/arduino-cli/internal/cli/updater" "github.com/arduino/arduino-cli/version" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/main.go b/main.go index 98b3a317cbd..4063632a42d 100644 --- a/main.go +++ b/main.go @@ -18,10 +18,10 @@ package main import ( "os" - "github.com/arduino/arduino-cli/cli" - "github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/i18n" + "github.com/arduino/arduino-cli/internal/cli" + "github.com/arduino/arduino-cli/internal/cli/feedback" ) func main() { From 6310e1ef72559b9722e8815142baf63374af73f2 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 12 Dec 2022 16:41:25 +0100 Subject: [PATCH 31/45] updated docs --- docs/UPGRADING.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md index 3ab8b55d26a..edda26504db 100644 --- a/docs/UPGRADING.md +++ b/docs/UPGRADING.md @@ -16,6 +16,27 @@ The `sketch.json` file is now completely ignored. The `cc.arduino.cli.commands.v1.BoardAttach` gRPC command has been removed. This feature is no longer available through gRPC. +### golang API: methods in `github.com/arduino/arduino-cli/commands/upload` changed return type + +The following methods in `github.com/arduino/arduino-cli/commands/upload`: + +```go +func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, errStream io.Writer) (*rpc.UploadResponse, error) { ... } +func UsingProgrammer(ctx context.Context, req *rpc.UploadUsingProgrammerRequest, outStream io.Writer, errStream io.Writer) (*rpc.UploadUsingProgrammerResponse, error) { ... } +``` + +do not return anymore the response (because it's always empty): + +```go +func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, errStream io.Writer) error { ... } +func UsingProgrammer(ctx context.Context, req *rpc.UploadUsingProgrammerRequest, outStream io.Writer, errStream io.Writer) error { ... } +``` + +### golang API: package `github.com/arduino/arduino-cli/cli` is no more public + +The package `cli` has been made internal. The code in this package is no more public API and can not be directly +imported in other projects. + ### golang API change in `github.com/arduino/arduino-cli/arduino/libraries/librariesmanager.LibrariesManager` The following `LibrariesManager.InstallPrerequisiteCheck` methods have changed prototype, from: From 8e70a6142ca8fcb3c5bcf5a8ba1f996b6d3138c2 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 3 Jan 2023 16:48:05 +0100 Subject: [PATCH 32/45] Removed redundant logic in getter for stdio streams Co-authored-by: per1234 --- internal/cli/feedback/stdio.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/cli/feedback/stdio.go b/internal/cli/feedback/stdio.go index 39a85fe058b..900bad2896f 100644 --- a/internal/cli/feedback/stdio.go +++ b/internal/cli/feedback/stdio.go @@ -31,10 +31,7 @@ func OutputStreams() (io.Writer, io.Writer, func() *OutputStreamsResult) { if !formatSelected { panic("output format not yet selected") } - if format == Text { - return stdOut, stdErr, getOutputStreamResult - } - return bufferOut, bufferErr, getOutputStreamResult + return feedbackOut, feedbackErr, getOutputStreamResult } func getOutputStreamResult() *OutputStreamsResult { From 68be5fa6fe3f677fd75684f4820cea9ff8050e37 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 3 Jan 2023 17:00:13 +0100 Subject: [PATCH 33/45] Internationalize more strings Co-authored-by: per1234 --- internal/cli/feedback/feedback.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/cli/feedback/feedback.go b/internal/cli/feedback/feedback.go index 4e18d5a2efe..d73fd7cfd9d 100644 --- a/internal/cli/feedback/feedback.go +++ b/internal/cli/feedback/feedback.go @@ -227,19 +227,19 @@ func PrintResult(res Result) { case JSON: d, err := json.MarshalIndent(augment(res.Data()), "", " ") if err != nil { - Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), ErrGeneric) + Fatal(tr("Error during JSON encoding of the output: %v", err), ErrGeneric) } data = string(d) case MinifiedJSON: d, err := json.Marshal(augment(res.Data())) if err != nil { - Fatal(fmt.Sprintf("Error during JSON encoding of the output: %v", err), ErrGeneric) + Fatal(tr("Error during JSON encoding of the output: %v", err), ErrGeneric) } data = string(d) case YAML: d, err := yaml.Marshal(augment(res.Data())) if err != nil { - Fatal(fmt.Sprintf("Error during YAML encoding of the output: %v", err), ErrGeneric) + Fatal(tr("Error during YAML encoding of the output: %v", err), ErrGeneric) } data = string(d) case Text: From 08fb7e6591c575501ea04e85489390c30b8c6a06 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 3 Jan 2023 17:00:33 +0100 Subject: [PATCH 34/45] Spellcheck internal/cli/feedback/stdio.go Co-authored-by: per1234 --- internal/cli/feedback/stdio.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/feedback/stdio.go b/internal/cli/feedback/stdio.go index 900bad2896f..3650c585908 100644 --- a/internal/cli/feedback/stdio.go +++ b/internal/cli/feedback/stdio.go @@ -50,7 +50,7 @@ type OutputStreamsResult struct { // Data returns the result object itself, it is used to implement the Result interface. func (r *OutputStreamsResult) Data() interface{} { - // In case of non-Text output format, the output is accumulared so retrun the buffer as a Result object + // In case of non-Text output format, the output is accumulated so return the buffer as a Result object return r } From 8586cde5d554844a0e8075e7fc2fe3f01e222780 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 3 Jan 2023 17:01:43 +0100 Subject: [PATCH 35/45] Spellcheck internal/cli/feedback/feedback_cmd.go Co-authored-by: per1234 --- internal/cli/feedback/feedback_cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/feedback/feedback_cmd.go b/internal/cli/feedback/feedback_cmd.go index ce66d18f1ac..117a488f4ee 100644 --- a/internal/cli/feedback/feedback_cmd.go +++ b/internal/cli/feedback/feedback_cmd.go @@ -25,7 +25,7 @@ import ( func NewCommand() *cobra.Command { cmd := &cobra.Command{ Use: "feedback", - Short: "Test the feedback functions of the arduino CLI.", + Short: "Test the feedback functions of Arduino CLI.", Long: "This command is for testing purposes only, it is not intended for use by end users.", Args: cobra.NoArgs, Hidden: true, From 6a4a1dca19aba3d521d8b81fa420ddf7543a419c Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 4 Jan 2023 11:27:13 +0100 Subject: [PATCH 36/45] feedback: remove stray '\r' on Windows on interactive input --- internal/cli/feedback/terminal.go | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/internal/cli/feedback/terminal.go b/internal/cli/feedback/terminal.go index 2783571d077..5b645cbaf67 100644 --- a/internal/cli/feedback/terminal.go +++ b/internal/cli/feedback/terminal.go @@ -55,22 +55,18 @@ func InputUserField(prompt string, secret bool) (string, error) { } fmt.Fprintf(stdOut, "%s: ", prompt) - var value []byte - var err error + if secret { - value, err = term.ReadPassword(int(os.Stdin.Fd())) + // Read and return a password (no characted echoed on terminal) + value, err := term.ReadPassword(int(os.Stdin.Fd())) fmt.Fprintln(stdOut) - } else { - value, err = bufio.NewReader(os.Stdin).ReadBytes('\n') - if l := len(value); l > 0 { - value = value[:l-1] - } - } - if err != nil { - panic(err) + return string(value), err } - return string(value), nil + // Read and return an input line + sc := bufio.NewScanner(os.Stdin) + sc.Scan() + return sc.Text(), sc.Err() } // ExitWhenParentProcessEnds waits until the controlling parent process ends and then exits From 722138dac305f7b7470fee8e9ba9b08f1b05936a Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 4 Jan 2023 11:59:02 +0100 Subject: [PATCH 37/45] Ban use of os.Exit from cli package --- internal/cli/board/list.go | 2 +- internal/cli/cli_test.go | 13 +++++++------ internal/cli/compile/compile.go | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/internal/cli/board/list.go b/internal/cli/board/list.go index 2ae365e145b..4bf73b11fc4 100644 --- a/internal/cli/board/list.go +++ b/internal/cli/board/list.go @@ -60,7 +60,7 @@ func runListCommand(cmd *cobra.Command, args []string) { if watch { watchList(cmd, inst) - os.Exit(0) + return } ports, discvoeryErrors, err := board.List(&rpc.BoardListRequest{ diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go index 9986c292ee6..1c3980c2d9f 100644 --- a/internal/cli/cli_test.go +++ b/internal/cli/cli_test.go @@ -70,14 +70,15 @@ func inspect(t *testing.T, fset *token.FileSet, node ast.Node) bool { t.Fail() } case *ast.SelectorExpr: - wanted := map[string]bool{ - "os.Stdout": true, - "os.Stderr": true, - "os.Stdin": true, + wanted := map[string]string{ + "os.Stdout": "%s: object `%s` should not be used in this package (use `feedback.*` instead)\n", + "os.Stderr": "%s: object `%s` should not be used in this package (use `feedback.*` instead)\n", + "os.Stdin": "%s: object `%s` should not be used in this package (use `feedback.*` instead)\n", + "os.Exit": "%s: function `%s` should not be used in this package (use `return` or `feedback.FatalError` instead)\n", } name := expr(n) - if wanted[name] { - fmt.Printf("%s: object `%s` should not be used in this package (use `feedback.*` instead)\n", fset.Position(n.Pos()), name) + if msg, banned := wanted[name]; banned { + fmt.Printf(msg, fset.Position(n.Pos()), name) t.Fail() } } diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index 55cd345a255..d18c06b458a 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -309,7 +309,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { feedback.FatalError(err, feedback.ErrGeneric) } feedback.PrintResult(stdIORes()) - os.Exit(0) + return } stdIO := stdIORes() From ca2451be7082eb146ccfcf18f91db23faa25b6d0 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 4 Jan 2023 13:06:23 +0100 Subject: [PATCH 38/45] Removed unused parameter in compile.Compile --- commands/compile/compile.go | 2 +- commands/daemon/daemon.go | 3 +-- docs/UPGRADING.md | 14 ++++++++++++++ internal/cli/compile/compile.go | 3 +-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/commands/compile/compile.go b/commands/compile/compile.go index be605746b93..4a4c78acb9d 100644 --- a/commands/compile/compile.go +++ b/commands/compile/compile.go @@ -39,7 +39,7 @@ import ( var tr = i18n.Tr // Compile FIXMEDOC -func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream io.Writer, progressCB rpc.TaskProgressCB, debug bool) (r *rpc.CompileResponse, e error) { +func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream io.Writer, progressCB rpc.TaskProgressCB) (r *rpc.CompileResponse, e error) { // There is a binding between the export binaries setting and the CLI flag to explicitly set it, // since we want this binding to work also for the gRPC interface we must read it here in this diff --git a/commands/daemon/daemon.go b/commands/daemon/daemon.go index fc468c8f072..a0369f97ad4 100644 --- a/commands/daemon/daemon.go +++ b/commands/daemon/daemon.go @@ -209,8 +209,7 @@ func (s *ArduinoCoreServerImpl) Compile(req *rpc.CompileRequest, stream rpc.Ardu errStream := feedStreamTo(func(data []byte) { stream.Send(&rpc.CompileResponse{ErrStream: data}) }) compileResp, compileErr := compile.Compile( stream.Context(), req, outStream, errStream, - func(p *rpc.TaskProgress) { stream.Send(&rpc.CompileResponse{Progress: p}) }, - false) // Set debug to false + func(p *rpc.TaskProgress) { stream.Send(&rpc.CompileResponse{Progress: p}) }) outStream.Close() errStream.Close() var compileRespSendErr error diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md index edda26504db..eb3f2766c98 100644 --- a/docs/UPGRADING.md +++ b/docs/UPGRADING.md @@ -32,6 +32,20 @@ func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, er func UsingProgrammer(ctx context.Context, req *rpc.UploadUsingProgrammerRequest, outStream io.Writer, errStream io.Writer) error { ... } ``` +### golang API: methods in `github.com/arduino/arduino-cli/commands/compile` changed signature + +The following method in `github.com/arduino/arduino-cli/commands/compile`: + +```go +func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream io.Writer, progressCB rpc.TaskProgressCB, debug bool) (r *rpc.CompileResponse, e error) { ... } +``` + +do not require the `debug` parameter anymore: + +```go +func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream io.Writer, progressCB rpc.TaskProgressCB) (r *rpc.CompileResponse, e error) { ... } +``` + ### golang API: package `github.com/arduino/arduino-cli/cli` is no more public The package `cli` has been made internal. The code in this package is no more public API and can not be directly diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index d18c06b458a..e128155eeb8 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -216,8 +216,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { SkipLibrariesDiscovery: skipLibrariesDiscovery, } stdOut, stdErr, stdIORes := feedback.OutputStreams() - verboseCompile := configuration.Settings.GetString("logging.level") == "debug" - compileRes, compileError := compile.Compile(context.Background(), compileRequest, stdOut, stdErr, nil, verboseCompile) + compileRes, compileError := compile.Compile(context.Background(), compileRequest, stdOut, stdErr, nil) if compileError == nil && uploadAfterCompile { userFieldRes, err := upload.SupportedUserFields(context.Background(), &rpc.SupportedUserFieldsRequest{ From d2db9356cb45b2adb45b3d09139d4909d285ee53 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 12 Jan 2023 12:38:32 +0100 Subject: [PATCH 39/45] Non-interactive stream are always buffered --- internal/cli/feedback/feedback.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cli/feedback/feedback.go b/internal/cli/feedback/feedback.go index d73fd7cfd9d..424bf63de09 100644 --- a/internal/cli/feedback/feedback.go +++ b/internal/cli/feedback/feedback.go @@ -129,8 +129,8 @@ func SetFormat(f OutputFormat) { formatSelected = true if format == Text { - feedbackOut = stdOut - feedbackErr = stdErr + feedbackOut = io.MultiWriter(bufferOut, stdOut) + feedbackErr = io.MultiWriter(bufferErr, stdErr) } else { feedbackOut = bufferOut feedbackErr = bufferErr From 3ef55a6742329d8ebeeec8f854b2587ddcd7351c Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 12 Jan 2023 12:37:54 +0100 Subject: [PATCH 40/45] Use direct streams where appropiate --- internal/cli/completion/completion.go | 6 +++-- internal/cli/daemon/daemon.go | 9 ++++--- internal/cli/feedback/stdio.go | 34 ++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/internal/cli/completion/completion.go b/internal/cli/completion/completion.go index d119d57f120..32b337eaf41 100644 --- a/internal/cli/completion/completion.go +++ b/internal/cli/completion/completion.go @@ -47,8 +47,11 @@ func NewCommand() *cobra.Command { } func runCompletionCommand(cmd *cobra.Command, args []string) { - stdOut, _, res := feedback.OutputStreams() logrus.Info("Executing `arduino-cli completion`") + stdOut, _, err := feedback.DirectStreams() + if err != nil { + feedback.Fatal(err.Error(), feedback.ErrGeneric) + } if completionNoDesc && (args[0] == "powershell") { feedback.Fatal(tr("Error: command description is not supported by %v", args[0]), feedback.ErrGeneric) } @@ -66,5 +69,4 @@ func runCompletionCommand(cmd *cobra.Command, args []string) { case "powershell": cmd.Root().GenPowerShellCompletion(stdOut) } - feedback.PrintResult(res()) } diff --git a/internal/cli/daemon/daemon.go b/internal/cli/daemon/daemon.go index 16c6d9af83a..9536510ff8e 100644 --- a/internal/cli/daemon/daemon.go +++ b/internal/cli/daemon/daemon.go @@ -89,12 +89,11 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { defer f.Close() debugStdOut = f } else { - // Attach to os.Stdout only if we are in Text mode - if feedback.GetFormat() != feedback.Text { - feedback.Fatal(tr("Debug log is only available in text format"), feedback.ErrBadArgument) + if out, _, err := feedback.DirectStreams(); err != nil { + feedback.Fatal(tr("Can't write debug log: %s", err), feedback.ErrBadArgument) + } else { + debugStdOut = out } - out, _, _ := feedback.OutputStreams() - debugStdOut = out } gRPCOptions = append(gRPCOptions, grpc.UnaryInterceptor(unaryLoggerInterceptor), diff --git a/internal/cli/feedback/stdio.go b/internal/cli/feedback/stdio.go index 3650c585908..787435462e1 100644 --- a/internal/cli/feedback/stdio.go +++ b/internal/cli/feedback/stdio.go @@ -16,17 +16,39 @@ package feedback import ( + "errors" "io" ) -// OutputStreams returns the underlying io.Writer to directly stream to +// DirectStreams returns the underlying io.Writer to directly stream to // stdout and stderr. -// If the selected output format is not Text, the returned writers will -// accumulate the output until command execution is completed. +// If the selected output format is not Text, the function will error. +// +// Using the streams returned by this function allows direct control of +// the output and the PrintResult function must not be used anymore +func DirectStreams() (io.Writer, io.Writer, error) { + if !formatSelected { + panic("output format not yet selected") + } + if format != Text { + return nil, nil, errors.New(tr("available only in text format")) + } + return stdOut, stdErr, nil +} + +// OutputStreams returns a pair of io.Writer to write the command output. +// The returned writers will accumulate the output until the command +// execution is completed, so they are not suitable for printing an unbounded +// stream like a debug logger or an event watcher (use DirectStreams for +// that purpose). +// +// If the output format is Text the output will be directly streamed to the +// underlying stdio streams in real time. +// // This function returns also a callback that must be called when the -// command execution is completed, it will return a *OutputStreamsResult -// object that can be used as a Result or to retrieve the output to embed -// it in another object. +// command execution is completed, it will return an *OutputStreamsResult +// object that can be used as a Result or to retrieve the accumulated output +// to embed it in another object. func OutputStreams() (io.Writer, io.Writer, func() *OutputStreamsResult) { if !formatSelected { panic("output format not yet selected") From 3b20b8d12152ec3127a6e563a36c8e15b8aed913 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 12 Jan 2023 16:06:00 +0100 Subject: [PATCH 41/45] Compile outputs profile dump as part of the result --- internal/cli/compile/compile.go | 42 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index e128155eeb8..1e5a9621603 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -144,9 +144,6 @@ func NewCommand() *cobra.Command { func runCompileCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino-cli compile`") - if dumpProfile && feedback.GetFormat() != feedback.Text { - feedback.Fatal(tr("You cannot use the %[1]s flag together with %[2]s.", "--dump-profile", "--format json"), feedback.ErrBadArgument) - } if profileArg.Get() != "" { if len(libraries) > 0 { feedback.Fatal(tr("You cannot use the %s flag while compiling with a profile.", "--libraries"), feedback.ErrBadArgument) @@ -255,7 +252,10 @@ func runCompileCommand(cmd *cobra.Command, args []string) { } } - if dumpProfile { + profileOut := "" + if dumpProfile && compileError == nil { + // Output profile + libs := "" hasVendoredLibs := false for _, lib := range compileRes.GetUsedLibraries() { @@ -279,36 +279,29 @@ func runCompileCommand(cmd *cobra.Command, args []string) { if split := strings.Split(compileRequest.GetFqbn(), ":"); len(split) > 2 { newProfileName = split[2] } - profile := fmt.Sprintln() - profile += fmt.Sprintln("profiles:") - profile += fmt.Sprintln(" " + newProfileName + ":") - profile += fmt.Sprintln(" fqbn: " + compileRequest.GetFqbn()) - profile += fmt.Sprintln(" platforms:") + profileOut = fmt.Sprintln("profiles:") + profileOut += fmt.Sprintln(" " + newProfileName + ":") + profileOut += fmt.Sprintln(" fqbn: " + compileRequest.GetFqbn()) + profileOut += fmt.Sprintln(" platforms:") boardPlatform := compileRes.GetBoardPlatform() - profile += fmt.Sprintln(" - platform: " + boardPlatform.GetId() + " (" + boardPlatform.GetVersion() + ")") + profileOut += fmt.Sprintln(" - platform: " + boardPlatform.GetId() + " (" + boardPlatform.GetVersion() + ")") if url := boardPlatform.GetPackageUrl(); url != "" { - profile += fmt.Sprintln(" platform_index_url: " + url) + profileOut += fmt.Sprintln(" platform_index_url: " + url) } if buildPlatform := compileRes.GetBuildPlatform(); buildPlatform != nil && buildPlatform.Id != boardPlatform.Id && buildPlatform.Version != boardPlatform.Version { - profile += fmt.Sprintln(" - platform: " + buildPlatform.GetId() + " (" + buildPlatform.GetVersion() + ")") + profileOut += fmt.Sprintln(" - platform: " + buildPlatform.GetId() + " (" + buildPlatform.GetVersion() + ")") if url := buildPlatform.GetPackageUrl(); url != "" { - profile += fmt.Sprintln(" platform_index_url: " + url) + profileOut += fmt.Sprintln(" platform_index_url: " + url) } } if len(libs) > 0 { - profile += fmt.Sprintln(" libraries:") - profile += fmt.Sprint(libs) + profileOut += fmt.Sprintln(" libraries:") + profileOut += fmt.Sprint(libs) } - - // Output profile as a result - if _, err := stdOut.Write([]byte(profile)); err != nil { - feedback.FatalError(err, feedback.ErrGeneric) - } - feedback.PrintResult(stdIORes()) - return + profileOut += fmt.Sprintln() } stdIO := stdIORes() @@ -316,6 +309,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { CompilerOut: stdIO.Stdout, CompilerErr: stdIO.Stderr, BuilderResult: compileRes, + ProfileOut: profileOut, Success: compileError == nil, }) if compileError != nil { @@ -357,6 +351,7 @@ type compileResult struct { CompilerErr string `json:"compiler_err"` BuilderResult *rpc.CompileResponse `json:"builder_result"` Success bool `json:"success"` + ProfileOut string `json:"profile_out,omitempty"` } func (r *compileResult) Data() interface{} { @@ -405,5 +400,8 @@ func (r *compileResult) String() string { } res += platforms.Render() } + if r.ProfileOut != "" { + res += "\n" + fmt.Sprintln(r.ProfileOut) + } return res } From ab8a75675f2c9a3a29e05d04bdcdfbc71ca25018 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 12 Jan 2023 16:07:54 +0100 Subject: [PATCH 42/45] Report saved warnings also when erroring out --- internal/cli/feedback/feedback.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/cli/feedback/feedback.go b/internal/cli/feedback/feedback.go index 424bf63de09..aca91b602fb 100644 --- a/internal/cli/feedback/feedback.go +++ b/internal/cli/feedback/feedback.go @@ -179,7 +179,7 @@ func Fatal(errorMsg string, exitCode ExitCode) { Error string `json:"error"` Output *OutputStreamsResult `json:"output,omitempty"` } - res := FatalError{ + res := &FatalError{ Error: errorMsg, } if output := getOutputStreamResult(); !output.Empty() { @@ -188,11 +188,11 @@ func Fatal(errorMsg string, exitCode ExitCode) { var d []byte switch format { case JSON: - d, _ = json.MarshalIndent(res, "", " ") + d, _ = json.MarshalIndent(augment(res), "", " ") case MinifiedJSON: - d, _ = json.Marshal(res) + d, _ = json.Marshal(augment(res)) case YAML: - d, _ = yaml.Marshal(res) + d, _ = yaml.Marshal(augment(res)) default: panic("unknown output format") } From 4e051422e091447037f1b5495bc3d86a9b3dfa9b Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 12 Jan 2023 16:26:59 +0100 Subject: [PATCH 43/45] Print compile error and suggestions as part of the result --- internal/cli/compile/compile.go | 27 +++++++++++++++------------ internal/cli/feedback/feedback.go | 6 ++++++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index 1e5a9621603..548dc0c6e06 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -305,15 +305,16 @@ func runCompileCommand(cmd *cobra.Command, args []string) { } stdIO := stdIORes() - feedback.PrintResult(&compileResult{ + res := &compileResult{ CompilerOut: stdIO.Stdout, CompilerErr: stdIO.Stderr, BuilderResult: compileRes, ProfileOut: profileOut, Success: compileError == nil, - }) + } + if compileError != nil { - msg := tr("Error during build: %v", compileError) + res.Error = tr("Error during build: %v", compileError) // Check the error type to give the user better feedback on how // to resolve it @@ -333,17 +334,18 @@ func runCompileCommand(cmd *cobra.Command, args []string) { release() if profileArg.String() == "" { - msg += "\n" + res.Error += fmt.Sprintln() if platform != nil { suggestion := fmt.Sprintf("`%s core install %s`", version.VersionInfo.Application, platformErr.Platform) - msg += tr("Try running %s", suggestion) + res.Error += tr("Try running %s", suggestion) } else { - msg += tr("Platform %s is not found in any known index\nMaybe you need to add a 3rd party URL?", platformErr.Platform) + res.Error += tr("Platform %s is not found in any known index\nMaybe you need to add a 3rd party URL?", platformErr.Platform) } } } - feedback.Fatal(msg, feedback.ErrGeneric) + feedback.FatalResult(res, feedback.ErrGeneric) } + feedback.PrintResult(res) } type compileResult struct { @@ -352,6 +354,7 @@ type compileResult struct { BuilderResult *rpc.CompileResponse `json:"builder_result"` Success bool `json:"success"` ProfileOut string `json:"profile_out,omitempty"` + Error string `json:"error,omitempty"` } func (r *compileResult) Data() interface{} { @@ -365,8 +368,8 @@ func (r *compileResult) String() string { build := r.BuilderResult res := "\n" - libraries := table.New() if len(build.GetUsedLibraries()) > 0 { + libraries := table.New() libraries.SetHeader( table.NewCell(tr("Used library"), titleColor), table.NewCell(tr("Version"), titleColor), @@ -377,8 +380,8 @@ func (r *compileResult) String() string { l.GetVersion(), table.NewCell(l.GetInstallDir(), pathColor)) } + res += fmt.Sprintln(libraries.Render()) } - res += libraries.Render() + "\n" if boardPlatform := build.GetBoardPlatform(); boardPlatform != nil { platforms := table.New() @@ -398,10 +401,10 @@ func (r *compileResult) String() string { buildPlatform.GetVersion(), table.NewCell(buildPlatform.GetInstallDir(), pathColor)) } - res += platforms.Render() + res += fmt.Sprintln(platforms.Render()) } if r.ProfileOut != "" { - res += "\n" + fmt.Sprintln(r.ProfileOut) + res += fmt.Sprintln(r.ProfileOut) } - return res + return strings.TrimRight(res, fmt.Sprintln()) } diff --git a/internal/cli/feedback/feedback.go b/internal/cli/feedback/feedback.go index aca91b602fb..d4258baec48 100644 --- a/internal/cli/feedback/feedback.go +++ b/internal/cli/feedback/feedback.go @@ -168,6 +168,12 @@ func FatalError(err error, exitCode ExitCode) { Fatal(err.Error(), exitCode) } +// FatalResult outputs the result and exits with status exitCode. +func FatalResult(res Result, exitCode ExitCode) { + PrintResult(res) + os.Exit(int(exitCode)) +} + // Fatal outputs the errorMsg and exits with status exitCode. func Fatal(errorMsg string, exitCode ExitCode) { if format == Text { From 5735f8ac1ba37ad960212bb41bf312101b786c3d Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 12 Jan 2023 16:27:28 +0100 Subject: [PATCH 44/45] Add trailing newline only if compiler has produced output --- internal/cli/compile/compile.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index 548dc0c6e06..b83da4f1bf4 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -367,7 +367,10 @@ func (r *compileResult) String() string { pathColor := color.New(color.FgHiBlack) build := r.BuilderResult - res := "\n" + res := "" + if r.CompilerOut != "" || r.CompilerErr != "" { + res += fmt.Sprintln() + } if len(build.GetUsedLibraries()) > 0 { libraries := table.New() libraries.SetHeader( From 3d5ea52c9e79cfd932f10189991e512cb4d3e16f Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 13 Jan 2023 11:29:09 +0100 Subject: [PATCH 45/45] FatalResult now outputs the error on stderr --- internal/cli/compile/compile.go | 4 ++++ internal/cli/feedback/feedback.go | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index b83da4f1bf4..c790d493222 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -411,3 +411,7 @@ func (r *compileResult) String() string { } return strings.TrimRight(res, fmt.Sprintln()) } + +func (r *compileResult) ErrorString() string { + return r.Error +} diff --git a/internal/cli/feedback/feedback.go b/internal/cli/feedback/feedback.go index d4258baec48..7a2ff5087a5 100644 --- a/internal/cli/feedback/feedback.go +++ b/internal/cli/feedback/feedback.go @@ -102,6 +102,13 @@ type Result interface { Data() interface{} } +// ErrorResult is a result embedding also an error. In case of textual output +// the error will be printed on stderr. +type ErrorResult interface { + Result + ErrorString() string +} + var tr = i18n.Tr // SetOut can be used to change the out writer at runtime @@ -169,7 +176,7 @@ func FatalError(err error, exitCode ExitCode) { } // FatalResult outputs the result and exits with status exitCode. -func FatalResult(res Result, exitCode ExitCode) { +func FatalResult(res ErrorResult, exitCode ExitCode) { PrintResult(res) os.Exit(int(exitCode)) } @@ -229,6 +236,7 @@ func augment(data interface{}) interface{} { // structure. func PrintResult(res Result) { var data string + var dataErr string switch format { case JSON: d, err := json.MarshalIndent(augment(res.Data()), "", " ") @@ -250,10 +258,16 @@ func PrintResult(res Result) { data = string(d) case Text: data = res.String() + if resErr, ok := res.(ErrorResult); ok { + dataErr = resErr.ErrorString() + } default: panic("unknown output format") } if data != "" { fmt.Fprintln(stdOut, data) } + if dataErr != "" { + fmt.Fprintln(stdErr, dataErr) + } }