From dfb97960fd202be1a8805d3adfa535b7dd02d4bc Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Wed, 10 Jul 2019 11:39:33 +0200 Subject: [PATCH 1/8] rearrange cli commands --- cli/board/attach.go | 16 +- cli/board/board.go | 17 +- cli/board/details.go | 30 ++-- cli/board/list.go | 17 +- cli/board/listall.go | 37 +++-- cli/cli.go | 215 ++++++++++--------------- cli/cli_test.go | 7 +- cli/compile/compile.go | 135 ++++++++-------- cli/config/config.go | 13 +- cli/config/dump.go | 23 ++- cli/config/init.go | 19 +-- cli/core/args.go | 4 +- cli/core/core.go | 11 +- cli/core/download.go | 17 +- cli/core/install.go | 17 +- cli/core/list.go | 13 +- cli/core/search.go | 13 +- cli/core/uninstall.go | 13 +- cli/core/update_index.go | 12 +- cli/core/upgrade.go | 19 ++- cli/daemon/daemon.go | 31 ++-- cli/errorcodes/errorcodes.go | 31 ++++ cli/generatedocs/generatedocs.go | 22 +-- cli/globals/globals.go | 105 ++++++++++++ cli/instance/instance.go | 78 +++++++++ cli/lib/download.go | 19 ++- cli/lib/install.go | 19 ++- cli/lib/lib.go | 13 +- cli/lib/list.go | 12 +- cli/lib/search.go | 12 +- cli/lib/uninstall.go | 14 +- cli/lib/update_index.go | 12 +- cli/lib/upgrade.go | 13 +- cli/{ => output}/output.go | 21 ++- {output => cli/output}/rpc_progress.go | 0 {output => cli/output}/table.go | 0 {output => cli/output}/text.go | 0 cli/root/root.go | 3 - cli/sketch/new.go | 11 +- cli/sketch/sketch.go | 14 +- cli/upload/upload.go | 84 +++++----- cli/version/version.go | 30 ++-- commands/compile/compile.go | 14 +- commands/daemon/daemon.go | 9 +- main.go | 7 +- output/output.go | 25 --- 46 files changed, 711 insertions(+), 536 deletions(-) create mode 100644 cli/errorcodes/errorcodes.go create mode 100644 cli/globals/globals.go create mode 100644 cli/instance/instance.go rename cli/{ => output}/output.go (82%) rename {output => cli/output}/rpc_progress.go (100%) rename {output => cli/output}/table.go (100%) rename {output => cli/output}/text.go (100%) delete mode 100644 output/output.go diff --git a/cli/board/attach.go b/cli/board/attach.go index 1f21734ad66..f2a5b7de6b4 100644 --- a/cli/board/attach.go +++ b/cli/board/attach.go @@ -21,7 +21,9 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/instance" + "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/board" "github.com/arduino/arduino-cli/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -33,9 +35,9 @@ func initAttachCommand() *cobra.Command { Use: "attach | [sketchPath]", Short: "Attaches a sketch to a board.", Long: "Attaches a sketch to a board.", - Example: " " + cli.VersionInfo.Application + " board attach serial:///dev/tty/ACM0\n" + - " " + cli.VersionInfo.Application + " board attach serial:///dev/tty/ACM0 HelloWorld\n" + - " " + cli.VersionInfo.Application + " board attach arduino:samd:mkr1000", + Example: " " + os.Args[0] + " board attach serial:///dev/tty/ACM0\n" + + " " + os.Args[0] + " board attach serial:///dev/tty/ACM0 HelloWorld\n" + + " " + os.Args[0] + " board attach arduino:samd:mkr1000", Args: cobra.RangeArgs(1, 2), Run: runAttachCommand, } @@ -49,7 +51,7 @@ var attachFlags struct { } func runAttachCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() var path string if len(args) > 0 { path = args[1] @@ -59,9 +61,9 @@ func runAttachCommand(cmd *cobra.Command, args []string) { BoardUri: args[0], SketchPath: path, SearchTimeout: attachFlags.searchTimeout, - }, cli.OutputTaskProgress()) + }, output.OutputTaskProgress()) if err != nil { formatter.PrintError(err, "attach board error") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } diff --git a/cli/board/board.go b/cli/board/board.go index 5a29328ac32..47dcecab14b 100644 --- a/cli/board/board.go +++ b/cli/board/board.go @@ -18,24 +18,27 @@ package board import ( - "github.com/arduino/arduino-cli/cli" + "os" + "github.com/spf13/cobra" ) -// InitCommand prepares the command. -func InitCommand() *cobra.Command { +// NewCommand created a new `board` command +func NewCommand() *cobra.Command { boardCommand := &cobra.Command{ Use: "board", Short: "Arduino board commands.", Long: "Arduino board commands.", Example: " # Lists all connected boards.\n" + - " " + cli.VersionInfo.Application + " board list\n\n" + + " " + os.Args[0] + " board list\n\n" + " # Attaches a sketch to a board.\n" + - " " + cli.VersionInfo.Application + " board attach serial:///dev/tty/ACM0 mySketch", + " " + os.Args[0] + " board attach serial:///dev/tty/ACM0 mySketch", } + boardCommand.AddCommand(initAttachCommand()) - boardCommand.AddCommand(initDetailsCommand()) + boardCommand.AddCommand(detailsCommand) boardCommand.AddCommand(initListCommand()) - boardCommand.AddCommand(initListAllCommand()) + boardCommand.AddCommand(listAllCommand) + return boardCommand } diff --git a/cli/board/details.go b/cli/board/details.go index bc1a2a6a740..49be6eac03b 100644 --- a/cli/board/details.go +++ b/cli/board/details.go @@ -22,39 +22,35 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/instance" + "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/board" "github.com/arduino/arduino-cli/common/formatter" - "github.com/arduino/arduino-cli/output" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/spf13/cobra" ) -func initDetailsCommand() *cobra.Command { - detailsCommand := &cobra.Command{ - Use: "details ", - Short: "Print details about a board.", - Long: "Show information about a board, in particular if the board has options to be specified in the FQBN.", - Example: " " + cli.VersionInfo.Application + " board details arduino:avr:nano", - Args: cobra.ExactArgs(1), - Run: runDetailsCommand, - } - return detailsCommand +var detailsCommand = &cobra.Command{ + Use: "details ", + Short: "Print details about a board.", + Long: "Show information about a board, in particular if the board has options to be specified in the FQBN.", + Example: " " + os.Args[0] + " board details arduino:avr:nano", + Args: cobra.ExactArgs(1), + Run: runDetailsCommand, } func runDetailsCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() - res, err := board.Details(context.Background(), &rpc.BoardDetailsReq{ - Instance: instance, + Instance: instance.CreateInstance(), Fqbn: args[0], }) if err != nil { formatter.PrintError(err, "Error getting board details") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } - if cli.OutputJSONOrElse(res) { + if output.OutputJSONOrElse(res) { outputDetailsResp(res) } } diff --git a/cli/board/list.go b/cli/board/list.go index 6c72a5433de..9ed019f68a3 100644 --- a/cli/board/list.go +++ b/cli/board/list.go @@ -24,10 +24,11 @@ import ( "sort" "time" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/instance" + "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/board" "github.com/arduino/arduino-cli/common/formatter" - "github.com/arduino/arduino-cli/output" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/spf13/cobra" ) @@ -37,7 +38,7 @@ func initListCommand() *cobra.Command { Use: "list", Short: "List connected boards.", Long: "Detects and displays a list of connected boards to the current computer.", - Example: " " + cli.VersionInfo.Application + " board list --timeout 10s", + Example: " " + os.Args[0] + " board list --timeout 10s", Args: cobra.NoArgs, Run: runListCommand, } @@ -53,22 +54,20 @@ var listFlags struct { // runListCommand detects and lists the connected arduino boards func runListCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() - if timeout, err := time.ParseDuration(listFlags.timeout); err != nil { formatter.PrintError(err, "Invalid timeout.") - os.Exit(cli.ErrBadArgument) + os.Exit(errorcodes.ErrBadArgument) } else { time.Sleep(timeout) } - resp, err := board.List(context.Background(), &rpc.BoardListReq{Instance: instance}) + resp, err := board.List(context.Background(), &rpc.BoardListReq{Instance: instance.CreateInstance()}) if err != nil { formatter.PrintError(err, "Error detecting boards") - os.Exit(cli.ErrNetwork) + os.Exit(errorcodes.ErrNetwork) } - if cli.OutputJSONOrElse(resp) { + if output.OutputJSONOrElse(resp) { outputListResp(resp) } } diff --git a/cli/board/listall.go b/cli/board/listall.go index 1da6c73bf06..4d81986dd0c 100644 --- a/cli/board/listall.go +++ b/cli/board/listall.go @@ -23,33 +23,31 @@ import ( "os" "sort" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/instance" + "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/board" "github.com/arduino/arduino-cli/common/formatter" - "github.com/arduino/arduino-cli/output" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/spf13/cobra" ) -func initListAllCommand() *cobra.Command { - listAllCommand := &cobra.Command{ - Use: "listall [boardname]", - Short: "List all known boards and their corresponding FQBN.", - Long: "" + - "List all boards that have the support platform installed. You can search\n" + - "for a specific board if you specify the board name", - Example: "" + - " " + cli.VersionInfo.Application + " board listall\n" + - " " + cli.VersionInfo.Application + " board listall zero", - Args: cobra.ArbitraryArgs, - Run: runListAllCommand, - } - return listAllCommand +var listAllCommand = &cobra.Command{ + Use: "listall [boardname]", + Short: "List all known boards and their corresponding FQBN.", + Long: "" + + "List all boards that have the support platform installed. You can search\n" + + "for a specific board if you specify the board name", + Example: "" + + " " + os.Args[0] + " board listall\n" + + " " + os.Args[0] + " board listall zero", + Args: cobra.ArbitraryArgs, + Run: runListAllCommand, } // runListAllCommand list all installed boards func runListAllCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() list, err := board.ListAll(context.Background(), &rpc.BoardListAllReq{ Instance: instance, @@ -57,9 +55,10 @@ func runListAllCommand(cmd *cobra.Command, args []string) { }) if err != nil { formatter.PrintError(err, "Error listing boards") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } - if cli.OutputJSONOrElse(list) { + + if output.OutputJSONOrElse(list) { outputBoardListAll(list) } } diff --git a/cli/cli.go b/cli/cli.go index 5d2dd0666db..d8af61e7b25 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -1,10 +1,10 @@ /* - * This file is part of arduino-cli. + * This file is part of arduino- * * Copyright 2018 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. + * which covers the main part of arduino- * The terms of this license can be found at: * https://www.gnu.org/licenses/gpl-3.0.en.html * @@ -18,152 +18,101 @@ package cli import ( - "context" - "errors" - "fmt" - "net/http" + "io/ioutil" "os" - "path/filepath" - "runtime" - "github.com/arduino/arduino-cli/arduino/cores/packagemanager" - "github.com/arduino/arduino-cli/arduino/libraries/librariesmanager" - "github.com/arduino/arduino-cli/commands" + "github.com/arduino/arduino-cli/cli/board" + "github.com/arduino/arduino-cli/cli/compile" + "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/errorcodes" + "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/sketch" + "github.com/arduino/arduino-cli/cli/upload" + "github.com/arduino/arduino-cli/cli/version" "github.com/arduino/arduino-cli/common/formatter" - "github.com/arduino/arduino-cli/configs" - rpc "github.com/arduino/arduino-cli/rpc/commands" - "github.com/arduino/arduino-cli/version" - "github.com/arduino/go-paths-helper" + "github.com/mattn/go-colorable" "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "golang.org/x/crypto/ssh/terminal" ) -// 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 - ErrNoConfigFile - ErrBadCall - 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. - ErrCoreConfig - ErrBadArgument -) - -// appName is the command line name of the Arduino CLI executable on the user system (users may change it) -var appName = filepath.Base(os.Args[0]) - -// VersionInfo contains all info injected during build -var VersionInfo = version.NewInfo(appName) - -// HTTPClientHeader is the object that will be propagated to configure the clients inside the downloaders -var HTTPClientHeader = getHTTPClientHeader() - -// ErrLogrus represents the logrus instance, which has the role to -// log all non info messages. -var ErrLogrus = logrus.New() - -// GlobalFlags represents flags available in all the program. -var GlobalFlags struct { - Debug bool // If true, dump debug output to stderr. - OutputJSON bool // true output in JSON, false output as Text -} - -// Config FIXMEDOC -var Config *configs.Configuration - -func packageManagerInitReq() *rpc.InitReq { - urls := []string{} - for _, URL := range Config.BoardManagerAdditionalUrls { - urls = append(urls, URL.String()) - } - - conf := &rpc.Configuration{} - conf.DataDir = Config.DataDir.String() - conf.DownloadsDir = Config.DownloadsDir().String() - conf.BoardManagerAdditionalUrls = urls - if Config.SketchbookDir != nil { - conf.SketchbookDir = Config.SketchbookDir.String() +var ( + // ArduinoCli is the root command + ArduinoCli = &cobra.Command{ + Use: "arduino-cli", + Short: "Arduino CLI.", + Long: "Arduino Command Line Interface (arduino-cli).", + Example: " " + os.Args[0] + " [flags...]", + PersistentPreRun: preRun, } - return &rpc.InitReq{Configuration: conf} -} + // ErrLogrus represents the logrus instance, which has the role to + // log all non info messages. + ErrLogrus = logrus.New() -func getHTTPClientHeader() http.Header { - userAgentValue := fmt.Sprintf("%s/%s (%s; %s; %s) Commit:%s/Build:%s", VersionInfo.Application, - VersionInfo.VersionString, runtime.GOARCH, runtime.GOOS, runtime.Version(), VersionInfo.Commit, VersionInfo.BuildDate) - downloaderHeaders := http.Header{"User-Agent": []string{userAgentValue}} - return downloaderHeaders -} - -// InitInstance FIXMEDOC -func InitInstance() *rpc.InitResp { - logrus.Info("Initializing package manager") - req := packageManagerInitReq() + outputFormat string +) - resp, err := commands.Init(context.Background(), req, OutputProgressBar(), OutputTaskProgress(), HTTPClientHeader) - if err != nil { - formatter.PrintError(err, "Error initializing package manager") - os.Exit(ErrGeneric) - } - if resp.GetLibrariesIndexError() != "" { - commands.UpdateLibrariesIndex(context.Background(), - &rpc.UpdateLibrariesIndexReq{Instance: resp.GetInstance()}, OutputProgressBar()) - rescResp, err := commands.Rescan(context.Background(), &rpc.RescanReq{Instance: resp.GetInstance()}) - if rescResp.GetLibrariesIndexError() != "" { - formatter.PrintErrorMessage("Error loading library index: " + rescResp.GetLibrariesIndexError()) - os.Exit(ErrGeneric) - } - if err != nil { - formatter.PrintError(err, "Error loading library index") - os.Exit(ErrGeneric) - } - resp.LibrariesIndexError = rescResp.LibrariesIndexError - resp.PlatformsIndexErrors = rescResp.PlatformsIndexErrors - } - return resp +// Init the cobra root command +func init() { + ArduinoCli.AddCommand(board.NewCommand()) + ArduinoCli.AddCommand(compile.NewCommand()) + ArduinoCli.AddCommand(config.NewCommand()) + ArduinoCli.AddCommand(core.NewCommand()) + ArduinoCli.AddCommand(daemon.NewCommand()) + ArduinoCli.AddCommand(generatedocs.NewCommand()) + ArduinoCli.AddCommand(lib.NewCommand()) + ArduinoCli.AddCommand(sketch.NewCommand()) + ArduinoCli.AddCommand(upload.NewCommand()) + ArduinoCli.AddCommand(version.NewCommand()) + + ArduinoCli.PersistentFlags().BoolVar(&globals.Debug, "debug", false, "Enables debug output (super verbose, used to debug the CLI).") + ArduinoCli.PersistentFlags().StringVar(&outputFormat, "format", "text", "The output format, can be [text|json].") + ArduinoCli.PersistentFlags().StringVar(&globals.YAMLConfigFile, "config-file", "", "The custom config file (if not specified the default will be used).") } -// CreateInstance creates and return an instance of the Arduino Core engine -func CreateInstance() *rpc.Instance { - resp := InitInstance() - if resp.GetPlatformsIndexErrors() != nil { - for _, err := range resp.GetPlatformsIndexErrors() { - formatter.PrintError(errors.New(err), "Error loading index") +func preRun(cmd *cobra.Command, args []string) { + // Reset logrus if debug flag changed. + if !globals.Debug { + // Discard logrus output if no debug. + logrus.SetOutput(ioutil.Discard) + } else { + // Else print on stderr. + + // Workaround to get colored output on windows + if terminal.IsTerminal(int(os.Stdout.Fd())) { + logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) } - formatter.PrintErrorMessage("Launch '" + VersionInfo.Application + " core update-index' to fix or download indexes.") - os.Exit(ErrGeneric) + logrus.SetOutput(colorable.NewColorableStdout()) + ErrLogrus.Out = colorable.NewColorableStderr() + formatter.SetLogger(ErrLogrus) } - return resp.GetInstance() -} - -// CreateInstaceIgnorePlatformIndexErrors creates and return an instance of the -// Arduino Core Engine, but won't stop on platforms index loading errors. -func CreateInstaceIgnorePlatformIndexErrors() *rpc.Instance { - return InitInstance().GetInstance() -} - -// InitPackageAndLibraryManager initializes the PackageManager and the -// LibaryManager with the default configuration. (DEPRECATED) -func InitPackageAndLibraryManager() (*packagemanager.PackageManager, *librariesmanager.LibrariesManager) { - resp := InitInstance() - return commands.GetPackageManager(resp), commands.GetLibraryManager(resp) -} - -// InitSketchPath returns sketchPath if specified or the current working -// directory if sketchPath is nil. -func InitSketchPath(sketchPath *paths.Path) *paths.Path { - if sketchPath != nil { - return sketchPath + globals.InitConfigs() + + logrus.Info(globals.VersionInfo.Application + "-" + globals.VersionInfo.VersionString) + logrus.Info("Starting root command preparation (`arduino`)") + switch outputFormat { + case "text": + formatter.SetFormatter("text") + globals.OutputJSON = false + case "json": + formatter.SetFormatter("json") + globals.OutputJSON = true + default: + formatter.PrintErrorMessage("Invalid output format: " + outputFormat) + os.Exit(errorcodes.ErrBadCall) } - wd, err := paths.Getwd() - if err != nil { - formatter.PrintError(err, "Couldn't get current working directory") - os.Exit(ErrGeneric) + logrus.Info("Formatter set") + if !formatter.IsCurrentFormat("text") { + cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { + logrus.Warn("Calling help on JSON format") + formatter.PrintErrorMessage("Invalid Call : should show Help, but it is available only in TEXT mode.") + os.Exit(errorcodes.ErrBadCall) + }) } - logrus.Infof("Reading sketch from dir: %s", wd) - return wd } diff --git a/cli/cli_test.go b/cli/cli_test.go index edbfca5df21..1a5538bc345 100644 --- a/cli/cli_test.go +++ b/cli/cli_test.go @@ -26,7 +26,7 @@ import ( "testing" "bou.ke/monkey" - "github.com/arduino/arduino-cli/cli/root" + "github.com/arduino/arduino-cli/cli" paths "github.com/arduino/go-paths-helper" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -111,9 +111,8 @@ func executeWithArgs(t *testing.T, args ...string) (int, []byte) { }() // Execute the CLI command, in this process - cmd := root.Init() - cmd.SetArgs(args) - cmd.Execute() + cli.ArduinoCli.SetArgs(args) + cli.ArduinoCli.Execute() }() return exitCode, output diff --git a/cli/compile/compile.go b/cli/compile/compile.go index 98e9eeeaf13..885edaecbd6 100644 --- a/cli/compile/compile.go +++ b/cli/compile/compile.go @@ -21,61 +21,19 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/globals" + + "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/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/arduino/go-paths-helper" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -// InitCommand prepares the command. -func InitCommand() *cobra.Command { - command := &cobra.Command{ - Use: "compile", - Short: "Compiles Arduino sketches.", - Long: "Compiles Arduino sketches.", - Example: " " + cli.VersionInfo.Application + " compile -b arduino:avr:uno /home/user/Arduino/MySketch", - Args: cobra.MaximumNArgs(1), - Run: run, - } - command.Flags().StringVarP( - &flags.fqbn, "fqbn", "b", "", - "Fully Qualified Board Name, e.g.: arduino:avr:uno") - command.Flags().BoolVar( - &flags.showProperties, "show-properties", false, - "Show all build properties used instead of compiling.") - command.Flags().BoolVar( - &flags.preprocess, "preprocess", false, - "Print preprocessed code to stdout instead of compiling.") - command.Flags().StringVar( - &flags.buildCachePath, "build-cache-path", "", - "Builds of 'core.a' are saved into this path to be cached and reused.") - command.Flags().StringVarP( - &flags.exportFile, "output", "o", "", - "Filename of the compile output.") - command.Flags().StringVar( - &flags.buildPath, "build-path", "", - "Path where to save compiled files. If omitted, a directory will be created in the default temporary path of your OS.") - command.Flags().StringSliceVar( - &flags.buildProperties, "build-properties", []string{}, - "List of custom build properties separated by commas. Or can be used multiple times for multiple properties.") - command.Flags().StringVar( - &flags.warnings, "warnings", "none", - `Optional, can be "none", "default", "more" and "all". Defaults to "none". Used to tell gcc which warning level to use (-W flag).`) - command.Flags().BoolVarP( - &flags.verbose, "verbose", "v", false, - "Optional, turns on verbose mode.") - command.Flags().BoolVar( - &flags.quiet, "quiet", false, - "Optional, supresses almost every output.") - command.Flags().StringVar( - &flags.vidPid, "vid-pid", "", - "When specified, VID/PID specific build properties are used, if boards supports them.") - return command -} - -var flags struct { +var ( fqbn string // Fully Qualified Board Name, e.g.: arduino:avr:uno. showProperties bool // Show all build preferences used instead of compiling. preprocess bool // Print preprocessed code to stdout. @@ -87,39 +45,80 @@ var flags struct { quiet bool // Suppresses almost every output. vidPid string // VID/PID specific build properties. exportFile string // The compiled binary is written to this file +) + +// NewCommand created a new `compile` command +func NewCommand() *cobra.Command { + command := &cobra.Command{ + Use: "compile", + Short: "Compiles Arduino sketches.", + Long: "Compiles Arduino sketches.", + Example: " " + os.Args[0] + " compile -b arduino:avr:uno /home/user/Arduino/MySketch", + Args: cobra.MaximumNArgs(1), + Run: run, + } + + command.Flags().StringVarP(&fqbn, "fqbn", "b", "", "Fully Qualified Board Name, e.g.: arduino:avr:uno") + command.Flags().BoolVar(&showProperties, "show-properties", false, "Show all build properties used instead of compiling.") + command.Flags().BoolVar(&preprocess, "preprocess", false, "Print preprocessed code to stdout instead of compiling.") + command.Flags().StringVar(&buildCachePath, "build-cache-path", "", "Builds of 'core.a' are saved into this path to be cached and reused.") + command.Flags().StringVarP(&exportFile, "output", "o", "", "Filename of the compile output.") + command.Flags().StringVar(&buildPath, "build-path", "", + "Path where to save compiled files. If omitted, a directory will be created in the default temporary path of your OS.") + command.Flags().StringSliceVar(&buildProperties, "build-properties", []string{}, + "List of custom build properties separated by commas. Or can be used multiple times for multiple properties.") + command.Flags().StringVar(&warnings, "warnings", "none", + `Optional, can be "none", "default", "more" and "all". Defaults to "none". Used to tell gcc which warning level to use (-W flag).`) + command.Flags().BoolVarP(&verbose, "verbose", "v", false, "Optional, turns on verbose mode.") + command.Flags().BoolVar(&quiet, "quiet", false, "Optional, supresses almost every output.") + command.Flags().StringVar(&vidPid, "vid-pid", "", "When specified, VID/PID specific build properties are used, if boards supports them.") + + return command } func run(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() var path *paths.Path if len(args) > 0 { path = paths.New(args[0]) } - sketchPath := cli.InitSketchPath(path) - compRes, err := compile.Compile(context.Background(), &rpc.CompileReq{ + + sketchPath := initSketchPath(path) + + _, err := compile.Compile(context.Background(), &rpc.CompileReq{ Instance: instance, - Fqbn: flags.fqbn, + Fqbn: fqbn, SketchPath: sketchPath.String(), - ShowProperties: flags.showProperties, - Preprocess: flags.preprocess, - BuildCachePath: flags.buildCachePath, - BuildPath: flags.buildPath, - BuildProperties: flags.buildProperties, - Warnings: flags.warnings, - Verbose: flags.verbose, - Quiet: flags.quiet, - VidPid: flags.vidPid, - ExportFile: flags.exportFile, - }, os.Stdout, os.Stderr) - if err == nil { - outputCompileResp(compRes) - } else { + ShowProperties: showProperties, + Preprocess: preprocess, + BuildCachePath: buildCachePath, + BuildPath: buildPath, + BuildProperties: buildProperties, + Warnings: warnings, + Verbose: verbose, + Quiet: quiet, + VidPid: vidPid, + ExportFile: exportFile, + }, os.Stdout, os.Stderr, globals.Config, globals.Debug) + + if err != nil { formatter.PrintError(err, "Error during build") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } -func outputCompileResp(details *rpc.CompileResp) { +// initSketchPath returns the current working directory +func initSketchPath(sketchPath *paths.Path) *paths.Path { + if sketchPath != nil { + return sketchPath + } + wd, err := paths.Getwd() + if err != nil { + formatter.PrintError(err, "Couldn't get current working directory") + os.Exit(errorcodes.ErrGeneric) + } + logrus.Infof("Reading sketch from dir: %s", wd) + return wd } diff --git a/cli/config/config.go b/cli/config/config.go index a03e0a0b083..c7fea67adeb 100644 --- a/cli/config/config.go +++ b/cli/config/config.go @@ -18,18 +18,21 @@ package config import ( - "github.com/arduino/arduino-cli/cli" + "os" + "github.com/spf13/cobra" ) -// InitCommand prepares the command. -func InitCommand() *cobra.Command { +// NewCommand created a new `config` command +func NewCommand() *cobra.Command { configCommand := &cobra.Command{ Use: "config", Short: "Arduino Configuration Commands.", - Example: " " + cli.VersionInfo.Application + " config init", + Example: " " + os.Args[0] + " config init", } - configCommand.AddCommand(initDumpCommand()) + + configCommand.AddCommand(dumpCmd) configCommand.AddCommand(initInitCommand()) + return configCommand } diff --git a/cli/config/dump.go b/cli/config/dump.go index c90daf246d6..2339662ce23 100644 --- a/cli/config/dump.go +++ b/cli/config/dump.go @@ -21,30 +21,29 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/common/formatter" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -func initDumpCommand() *cobra.Command { - return &cobra.Command{ - Use: "dump", - Short: "Prints the current configuration", - Long: "Prints the current configuration.", - Example: " " + cli.VersionInfo.Application + " config dump", - Args: cobra.NoArgs, - Run: runDumpCommand, - } +var dumpCmd = &cobra.Command{ + Use: "dump", + Short: "Prints the current configuration", + Long: "Prints the current configuration.", + Example: " " + os.Args[0] + " config dump", + Args: cobra.NoArgs, + Run: runDumpCommand, } func runDumpCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino config dump`") - data, err := cli.Config.SerializeToYAML() + data, err := globals.Config.SerializeToYAML() if err != nil { formatter.PrintError(err, "Error creating configuration") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } fmt.Println(string(data)) diff --git a/cli/config/init.go b/cli/config/init.go index c2068c9e3c8..2cbc05a6d89 100644 --- a/cli/config/init.go +++ b/cli/config/init.go @@ -20,7 +20,8 @@ package config import ( "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/common/formatter" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -33,9 +34,9 @@ func initInitCommand() *cobra.Command { Long: "Initializes a new config file into the default location ($EXE_DIR/cli-config.yml).", Example: "" + " # Creates a config file by asking questions to the user into the default location.\n" + - " " + cli.VersionInfo.Application + " config init\n\n" + + " " + os.Args[0] + " config init\n\n" + " # Creates a config file with default configuration into default location.\n" + - " " + cli.VersionInfo.Application + " config init --default\n", + " " + os.Args[0] + " config init --default\n", Args: cobra.NoArgs, Run: runInitCommand, } @@ -57,23 +58,23 @@ func runInitCommand(cmd *cobra.Command, args []string) { if !initFlags._default { if !formatter.IsCurrentFormat("text") { formatter.PrintErrorMessage("The interactive mode is supported only in text mode.") - os.Exit(cli.ErrBadCall) + os.Exit(errorcodes.ErrBadCall) } } filepath := initFlags.location if filepath == "" { - filepath = cli.Config.ConfigFile.String() + filepath = globals.Config.ConfigFile.String() } - if err := cli.Config.ConfigFile.Parent().MkdirAll(); err != nil { + if err := globals.Config.ConfigFile.Parent().MkdirAll(); err != nil { formatter.PrintError(err, "Cannot create config file.") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } - if err := cli.Config.SaveToYAML(filepath); err != nil { + if err := globals.Config.SaveToYAML(filepath); err != nil { formatter.PrintError(err, "Cannot create config file.") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } formatter.PrintResult("Config file PATH: " + filepath) logrus.Info("Done") diff --git a/cli/core/args.go b/cli/core/args.go index 1d669db812c..2f00602a945 100644 --- a/cli/core/args.go +++ b/cli/core/args.go @@ -22,7 +22,7 @@ import ( "os" "strings" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/common/formatter" ) @@ -47,7 +47,7 @@ func parsePlatformReferenceArgs(args []string) []*platformReferenceArg { reference, err := parsePlatformReferenceArg(arg) if err != nil { formatter.PrintError(err, "Invalid item "+arg) - os.Exit(cli.ErrBadArgument) + os.Exit(errorcodes.ErrBadArgument) } ret = append(ret, reference) } diff --git a/cli/core/core.go b/cli/core/core.go index b8aa1f297c7..709109fce56 100644 --- a/cli/core/core.go +++ b/cli/core/core.go @@ -18,18 +18,20 @@ package core import ( - "github.com/arduino/arduino-cli/cli" + "os" + "github.com/spf13/cobra" ) -// InitCommand prepares the command. -func InitCommand() *cobra.Command { +// NewCommand created a new `core` command +func NewCommand() *cobra.Command { coreCommand := &cobra.Command{ Use: "core", Short: "Arduino Core operations.", Long: "Arduino Core operations.", - Example: " " + cli.VersionInfo.Application + " core update-index", + Example: " " + os.Args[0] + " core update-index", } + coreCommand.AddCommand(initDownloadCommand()) coreCommand.AddCommand(initInstallCommand()) coreCommand.AddCommand(initListCommand()) @@ -37,5 +39,6 @@ func InitCommand() *cobra.Command { coreCommand.AddCommand(initUpgradeCommand()) coreCommand.AddCommand(initUninstallCommand()) coreCommand.AddCommand(initSearchCommand()) + return coreCommand } diff --git a/cli/core/download.go b/cli/core/download.go index e5cbbbb6962..b5dedc6e570 100644 --- a/cli/core/download.go +++ b/cli/core/download.go @@ -21,7 +21,10 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/core" "github.com/arduino/arduino-cli/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -35,8 +38,8 @@ func initDownloadCommand() *cobra.Command { Short: "Downloads one or more cores and corresponding tool dependencies.", Long: "Downloads one or more cores and corresponding tool dependencies.", Example: "" + - " " + cli.VersionInfo.Application + " core download arduino:samd # to download the latest version of arduino SAMD core.\n" + - " " + cli.VersionInfo.Application + " core download arduino:samd=1.6.9 # for a specific version (in this case 1.6.9).", + " " + os.Args[0] + " core download arduino:samd # to download the latest version of arduino SAMD core.\n" + + " " + os.Args[0] + " core download arduino:samd=1.6.9 # for a specific version (in this case 1.6.9).", Args: cobra.MinimumNArgs(1), Run: runDownloadCommand, } @@ -44,7 +47,7 @@ func initDownloadCommand() *cobra.Command { } func runDownloadCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() logrus.Info("Executing `arduino core download`") platformsRefs := parsePlatformReferenceArgs(args) @@ -55,11 +58,11 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { Architecture: platformRef.Architecture, Version: platformRef.Version, } - _, err := core.PlatformDownload(context.Background(), platformDownloadreq, cli.OutputProgressBar(), - cli.HTTPClientHeader) + _, err := core.PlatformDownload(context.Background(), platformDownloadreq, output.OutputProgressBar(), + globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error downloading "+args[i]) - os.Exit(cli.ErrNetwork) + os.Exit(errorcodes.ErrNetwork) } } } diff --git a/cli/core/install.go b/cli/core/install.go index 46d294bccb3..7f65a8eac5c 100644 --- a/cli/core/install.go +++ b/cli/core/install.go @@ -21,7 +21,10 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/core" "github.com/arduino/arduino-cli/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -35,9 +38,9 @@ func initInstallCommand() *cobra.Command { Short: "Installs one or more cores and corresponding tool dependencies.", Long: "Installs one or more cores and corresponding tool dependencies.", Example: " # download the latest version of arduino SAMD core.\n" + - " " + cli.VersionInfo.Application + " core install arduino:samd\n\n" + + " " + os.Args[0] + " core install arduino:samd\n\n" + " # download a specific version (in this case 1.6.9).\n" + - " " + cli.VersionInfo.Application + " core install arduino:samd@1.6.9", + " " + os.Args[0] + " core install arduino:samd@1.6.9", Args: cobra.MinimumNArgs(1), Run: runInstallCommand, } @@ -45,7 +48,7 @@ func initInstallCommand() *cobra.Command { } func runInstallCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() logrus.Info("Executing `arduino core install`") platformsRefs := parsePlatformReferenceArgs(args) @@ -57,11 +60,11 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Architecture: platformRef.Architecture, Version: platformRef.Version, } - _, err := core.PlatformInstall(context.Background(), plattformInstallReq, cli.OutputProgressBar(), - cli.OutputTaskProgress(), cli.HTTPClientHeader) + _, err := core.PlatformInstall(context.Background(), plattformInstallReq, output.OutputProgressBar(), + output.OutputTaskProgress(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error during install") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } } diff --git a/cli/core/list.go b/cli/core/list.go index 13d92b14440..4ac1c377b9c 100644 --- a/cli/core/list.go +++ b/cli/core/list.go @@ -23,10 +23,11 @@ import ( "os" "sort" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/instance" + "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/core" "github.com/arduino/arduino-cli/common/formatter" - "github.com/arduino/arduino-cli/output" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -37,7 +38,7 @@ func initListCommand() *cobra.Command { Use: "list", Short: "Shows the list of installed platforms.", Long: "Shows the list of installed platforms.", - Example: " " + cli.VersionInfo.Application + " core list", + Example: " " + os.Args[0] + " core list", Args: cobra.NoArgs, Run: runListCommand, } @@ -50,7 +51,7 @@ var listFlags struct { } func runListCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() logrus.Info("Executing `arduino core list`") resp, err := core.PlatformList(context.Background(), &rpc.PlatformListReq{ @@ -59,11 +60,11 @@ func runListCommand(cmd *cobra.Command, args []string) { }) if err != nil { formatter.PrintError(err, "Error listing platforms") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } installed := resp.GetInstalledPlatform() if installed != nil && len(installed) > 0 { - if cli.OutputJSONOrElse(installed) { + if output.OutputJSONOrElse(installed) { outputInstalledCores(installed) } } diff --git a/cli/core/search.go b/cli/core/search.go index 069705926e3..057c6d95c52 100644 --- a/cli/core/search.go +++ b/cli/core/search.go @@ -24,10 +24,11 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/instance" + "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/core" "github.com/arduino/arduino-cli/common/formatter" - "github.com/arduino/arduino-cli/output" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -38,7 +39,7 @@ func initSearchCommand() *cobra.Command { Use: "search ", Short: "Search for a core in the package index.", Long: "Search for a core in the package index using the specified keywords.", - Example: " " + cli.VersionInfo.Application + " core search MKRZero -v", + Example: " " + os.Args[0] + " core search MKRZero -v", Args: cobra.MinimumNArgs(1), Run: runSearchCommand, } @@ -46,7 +47,7 @@ func initSearchCommand() *cobra.Command { } func runSearchCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() logrus.Info("Executing `arduino core search`") arguments := strings.ToLower(strings.Join(args, " ")) @@ -58,11 +59,11 @@ func runSearchCommand(cmd *cobra.Command, args []string) { }) if err != nil { formatter.PrintError(err, "Error saerching for platforms") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } coreslist := resp.GetSearchOutput() - if cli.OutputJSONOrElse(coreslist) { + if output.OutputJSONOrElse(coreslist) { if len(coreslist) > 0 { outputSearchCores(coreslist) } else { diff --git a/cli/core/uninstall.go b/cli/core/uninstall.go index c5b15eb9c93..f15fa801e08 100644 --- a/cli/core/uninstall.go +++ b/cli/core/uninstall.go @@ -21,10 +21,11 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/instance" + "github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/commands/core" "github.com/arduino/arduino-cli/common/formatter" - "github.com/arduino/arduino-cli/output" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -35,14 +36,14 @@ func initUninstallCommand() *cobra.Command { Use: "uninstall PACKAGER:ARCH ...", Short: "Uninstalls one or more cores and corresponding tool dependencies if no more used.", Long: "Uninstalls one or more cores and corresponding tool dependencies if no more used.", - Example: " " + cli.VersionInfo.Application + " core uninstall arduino:samd\n", + Example: " " + os.Args[0] + " core uninstall arduino:samd\n", Args: cobra.MinimumNArgs(1), Run: runUninstallCommand, } } func runUninstallCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() logrus.Info("Executing `arduino core uninstall`") platformsRefs := parsePlatformReferenceArgs(args) @@ -50,7 +51,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { for _, platformRef := range platformsRefs { if platformRef.Version != "" { formatter.PrintErrorMessage("Invalid parameter " + platformRef.String() + ": version not allowed") - os.Exit(cli.ErrBadArgument) + os.Exit(errorcodes.ErrBadArgument) } } for _, platformRef := range platformsRefs { @@ -61,7 +62,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { }, output.NewTaskProgressCB()) if err != nil { formatter.PrintError(err, "Error during uninstall") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } } diff --git a/cli/core/update_index.go b/cli/core/update_index.go index f42ad3867f6..75e1ed70461 100644 --- a/cli/core/update_index.go +++ b/cli/core/update_index.go @@ -21,7 +21,9 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -34,7 +36,7 @@ func initUpdateIndexCommand() *cobra.Command { Use: "update-index", Short: "Updates the index of cores.", Long: "Updates the index of cores to the latest version.", - Example: " " + cli.VersionInfo.Application + " core update-index", + Example: " " + os.Args[0] + " core update-index", Args: cobra.NoArgs, Run: runUpdateIndexCommand, } @@ -42,14 +44,14 @@ func initUpdateIndexCommand() *cobra.Command { } func runUpdateIndexCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstaceIgnorePlatformIndexErrors() + instance := instance.CreateInstaceIgnorePlatformIndexErrors() logrus.Info("Executing `arduino core update-index`") _, err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexReq{ Instance: instance, - }, cli.OutputProgressBar()) + }, output.OutputProgressBar()) if err != nil { formatter.PrintError(err, "Error updating index") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } diff --git a/cli/core/upgrade.go b/cli/core/upgrade.go index f6ed8e28591..4159df94b01 100644 --- a/cli/core/upgrade.go +++ b/cli/core/upgrade.go @@ -21,7 +21,10 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/core" "github.com/arduino/arduino-cli/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -36,23 +39,23 @@ func initUpgradeCommand() *cobra.Command { Long: "Upgrades one or all installed platforms to the latest version.", Example: "" + " # upgrade everything to the latest version\n" + - " " + cli.VersionInfo.Application + " core upgrade\n\n" + + " " + os.Args[0] + " core upgrade\n\n" + " # upgrade arduino:samd to the latest version\n" + - " " + cli.VersionInfo.Application + " core upgrade arduino:samd", + " " + os.Args[0] + " core upgrade arduino:samd", Run: runUpgradeCommand, } return upgradeCommand } func runUpgradeCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() logrus.Info("Executing `arduino core upgrade`") platformsRefs := parsePlatformReferenceArgs(args) for i, platformRef := range platformsRefs { if platformRef.Version != "" { formatter.PrintErrorMessage(("Invalid item " + args[i])) - os.Exit(cli.ErrBadArgument) + os.Exit(errorcodes.ErrBadArgument) } } for _, platformRef := range platformsRefs { @@ -60,11 +63,11 @@ func runUpgradeCommand(cmd *cobra.Command, args []string) { Instance: instance, PlatformPackage: platformRef.Package, Architecture: platformRef.Architecture, - }, cli.OutputProgressBar(), cli.OutputTaskProgress(), - cli.HTTPClientHeader) + }, output.OutputProgressBar(), output.OutputTaskProgress(), + globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error during upgrade") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } } diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index 3b14b0ead65..10c04830b8d 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -22,33 +22,32 @@ import ( "log" "net" "net/http" + "os" "runtime" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/commands/daemon" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/spf13/cobra" "google.golang.org/grpc" ) -// InitCommand initialize the command -func InitCommand() *cobra.Command { - cmd := &cobra.Command{ +const ( + port = ":50051" +) + +// NewCommand created a new `daemon` command +func NewCommand() *cobra.Command { + return &cobra.Command{ Use: "daemon", Short: "Run as a daemon", Long: "Running as a daemon the initialization of cores and libraries is done only once.", - Example: " " + cli.VersionInfo.Application + " daemon", + Example: " " + os.Args[0] + " daemon", Args: cobra.NoArgs, Run: runDaemonCommand, - Hidden: true, } - return cmd } -const ( - port = ":50051" -) - func runDaemonCommand(cmd *cobra.Command, args []string) { lis, err := net.Listen("tcp", port) if err != nil { @@ -56,11 +55,15 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { } s := grpc.NewServer() - userAgentValue := fmt.Sprintf("%s/%s daemon (%s; %s; %s) Commit:%s/Build:%s", cli.VersionInfo.Application, - cli.VersionInfo.VersionString, runtime.GOARCH, runtime.GOOS, runtime.Version(), cli.VersionInfo.Commit, cli.VersionInfo.BuildDate) + userAgentValue := fmt.Sprintf("%s/%s daemon (%s; %s; %s) Commit:%s/Build:%s", globals.VersionInfo.Application, + globals.VersionInfo.VersionString, runtime.GOARCH, runtime.GOOS, runtime.Version(), globals.VersionInfo.Commit, globals.VersionInfo.BuildDate) headers := http.Header{"User-Agent": []string{userAgentValue}} - coreServer := daemon.ArduinoCoreServerImpl{DownloaderHeaders: headers} + coreServer := daemon.ArduinoCoreServerImpl{ + DownloaderHeaders: headers, + VersionString: globals.VersionInfo.VersionString, + Config: globals.Config, + } rpc.RegisterArduinoCoreServer(s, &coreServer) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) diff --git a/cli/errorcodes/errorcodes.go b/cli/errorcodes/errorcodes.go new file mode 100644 index 00000000000..a63bcf2ba3d --- /dev/null +++ b/cli/errorcodes/errorcodes.go @@ -0,0 +1,31 @@ +// This file is part of arduino-cli. +// +// Copyright 2019 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 errorcodes + +// 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 + ErrNoConfigFile + ErrBadCall + 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. + ErrCoreConfig + ErrBadArgument +) diff --git a/cli/generatedocs/generatedocs.go b/cli/generatedocs/generatedocs.go index 000537b811f..4c983948e89 100644 --- a/cli/generatedocs/generatedocs.go +++ b/cli/generatedocs/generatedocs.go @@ -21,20 +21,24 @@ import ( "os" "path/filepath" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" ) -// InitCommand prepares the command. -func InitCommand() *cobra.Command { - var command = &cobra.Command{ +var outputDir = "" + +// NewCommand created a new `generatedocs` command +func NewCommand() *cobra.Command { + command := &cobra.Command{ Use: "generate-docs", Short: "Generates bash completion and command manpages.", Long: "Generates bash completion and command manpages.", - Example: " " + cli.VersionInfo.Application + " generate-docs bash-completions", + Example: " " + os.Args[0] + " generate-docs bash-completions", + Hidden: true, } + command.PersistentFlags().StringVarP(&outputDir, "output-dir", "o", "", "Directory where to save generated files. Default is './docs', the directory must exist.") command.AddCommand(&cobra.Command{ @@ -47,12 +51,10 @@ func InitCommand() *cobra.Command { Args: cobra.NoArgs, Run: generateBashCompletions, }) - command.Hidden = true + return command } -var outputDir = "" - func generateBashCompletions(cmd *cobra.Command, args []string) { if outputDir == "" { outputDir = "docs/bash_completions" @@ -61,7 +63,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(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } @@ -78,6 +80,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(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } diff --git a/cli/globals/globals.go b/cli/globals/globals.go new file mode 100644 index 00000000000..cf1965b2da0 --- /dev/null +++ b/cli/globals/globals.go @@ -0,0 +1,105 @@ +package globals + +import ( + "fmt" + "net/http" + "os" + "path/filepath" + "runtime" + + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/common/formatter" + "github.com/arduino/arduino-cli/configs" + "github.com/arduino/arduino-cli/version" + "github.com/arduino/go-paths-helper" + "github.com/sirupsen/logrus" +) + +var ( + // Debug determines whether to dump debug output to stderr or not + Debug bool + // OutputJSON is true output in JSON, false output as Text + OutputJSON bool + // HTTPClientHeader is the object that will be propagated to configure the clients inside the downloaders + HTTPClientHeader = getHTTPClientHeader() + // VersionInfo contains all info injected during build + VersionInfo = version.NewInfo(filepath.Base(os.Args[0])) + // Config FIXMEDOC + Config *configs.Configuration + + YAMLConfigFile string +) + +func getHTTPClientHeader() http.Header { + userAgentValue := fmt.Sprintf("%s/%s (%s; %s; %s) Commit:%s/Build:%s", VersionInfo.Application, + VersionInfo.VersionString, runtime.GOARCH, runtime.GOOS, runtime.Version(), VersionInfo.Commit, VersionInfo.BuildDate) + downloaderHeaders := http.Header{"User-Agent": []string{userAgentValue}} + return downloaderHeaders +} + +// InitConfigs initializes the configuration from the specified file. +func InitConfigs() { + // Start with default configuration + if conf, err := configs.NewConfiguration(); err != nil { + logrus.WithError(err).Error("Error creating default configuration") + formatter.PrintError(err, "Error creating default configuration") + os.Exit(errorcodes.ErrGeneric) + } else { + Config = conf + } + + // Read configuration from global config file + logrus.Info("Checking for config file in: " + Config.ConfigFile.String()) + if Config.ConfigFile.Exist() { + readConfigFrom(Config.ConfigFile) + } + + if Config.IsBundledInDesktopIDE() { + logrus.Info("CLI is bundled into the IDE") + err := Config.LoadFromDesktopIDEPreferences() + if err != nil { + logrus.WithError(err).Warn("Did not manage to get config file of IDE, using default configuration") + } + } else { + logrus.Info("CLI is not bundled into the IDE") + } + + // Read configuration from parent folders (project config) + if pwd, err := paths.Getwd(); err != nil { + logrus.WithError(err).Warn("Did not manage to find current path") + if path := paths.New("arduino-yaml"); path.Exist() { + readConfigFrom(path) + } + } else { + Config.Navigate(pwd) + } + + // Read configuration from old configuration file if found, but output a warning. + if old := paths.New(".cli-config.yml"); old.Exist() { + logrus.Errorf("Old configuration file detected: %s.", old) + logrus.Info("The name of this file has been changed to `arduino-yaml`, please rename the file fix it.") + formatter.PrintError( + fmt.Errorf("WARNING: Old configuration file detected: %s", old), + "The name of this file has been changed to `arduino-yaml`, in a future release we will not support"+ + "the old name `.cli-config.yml` anymore. Please rename the file to `arduino-yaml` to silence this warning.") + readConfigFrom(old) + } + + // Read configuration from environment vars + Config.LoadFromEnv() + + // Read configuration from user specified file + if YAMLConfigFile != "" { + Config.ConfigFile = paths.New(YAMLConfigFile) + readConfigFrom(Config.ConfigFile) + } + + logrus.Info("Configuration set") +} + +func readConfigFrom(path *paths.Path) { + logrus.Infof("Reading configuration from %s", path) + if err := Config.LoadFromYAML(path); err != nil { + logrus.WithError(err).Warnf("Could not read configuration from %s", path) + } +} diff --git a/cli/instance/instance.go b/cli/instance/instance.go new file mode 100644 index 00000000000..1b04ac5d282 --- /dev/null +++ b/cli/instance/instance.go @@ -0,0 +1,78 @@ +package instance + +import ( + "context" + "errors" + "os" + + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/common/formatter" + rpc "github.com/arduino/arduino-cli/rpc/commands" + "github.com/sirupsen/logrus" +) + +// CreateInstaceIgnorePlatformIndexErrors creates and return an instance of the +// Arduino Core Engine, but won't stop on platforms index loading errors. +func CreateInstaceIgnorePlatformIndexErrors() *rpc.Instance { + return initInstance().GetInstance() +} + +// CreateInstance creates and return an instance of the Arduino Core engine +func CreateInstance() *rpc.Instance { + resp := initInstance() + if resp.GetPlatformsIndexErrors() != nil { + for _, err := range resp.GetPlatformsIndexErrors() { + formatter.PrintError(errors.New(err), "Error loading index") + } + formatter.PrintErrorMessage("Launch '" + os.Args[0] + " core update-index' to fix or download indexes.") + os.Exit(errorcodes.ErrGeneric) + } + return resp.GetInstance() +} + +func initInstance() *rpc.InitResp { + logrus.Info("Initializing package manager") + req := packageManagerInitReq() + + resp, err := commands.Init(context.Background(), req, output.OutputProgressBar(), output.OutputTaskProgress(), globals.HTTPClientHeader) + if err != nil { + formatter.PrintError(err, "Error initializing package manager") + os.Exit(errorcodes.ErrGeneric) + } + if resp.GetLibrariesIndexError() != "" { + commands.UpdateLibrariesIndex(context.Background(), + &rpc.UpdateLibrariesIndexReq{Instance: resp.GetInstance()}, output.OutputProgressBar()) + rescResp, err := commands.Rescan(context.Background(), &rpc.RescanReq{Instance: resp.GetInstance()}) + if rescResp.GetLibrariesIndexError() != "" { + formatter.PrintErrorMessage("Error loading library index: " + rescResp.GetLibrariesIndexError()) + os.Exit(errorcodes.ErrGeneric) + } + if err != nil { + formatter.PrintError(err, "Error loading library index") + os.Exit(errorcodes.ErrGeneric) + } + resp.LibrariesIndexError = rescResp.LibrariesIndexError + resp.PlatformsIndexErrors = rescResp.PlatformsIndexErrors + } + return resp +} + +func packageManagerInitReq() *rpc.InitReq { + urls := []string{} + for _, URL := range globals.Config.BoardManagerAdditionalUrls { + urls = append(urls, URL.String()) + } + + conf := &rpc.Configuration{} + conf.DataDir = globals.Config.DataDir.String() + conf.DownloadsDir = globals.Config.DownloadsDir().String() + conf.BoardManagerAdditionalUrls = urls + if globals.Config.SketchbookDir != nil { + conf.SketchbookDir = globals.Config.SketchbookDir.String() + } + + return &rpc.InitReq{Configuration: conf} +} diff --git a/cli/lib/download.go b/cli/lib/download.go index acd384eb9df..5049480c514 100644 --- a/cli/lib/download.go +++ b/cli/lib/download.go @@ -22,7 +22,10 @@ import ( "os" "github.com/arduino/arduino-cli/arduino/libraries/librariesindex" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -35,8 +38,8 @@ func initDownloadCommand() *cobra.Command { Short: "Downloads one or more libraries without installing them.", Long: "Downloads one or more libraries without installing them.", Example: "" + - " " + cli.VersionInfo.Application + " lib download AudioZero # for the latest version.\n" + - " " + cli.VersionInfo.Application + " lib download AudioZero@1.0.0 # for a specific version.", + " " + os.Args[0] + " lib download AudioZero # for the latest version.\n" + + " " + os.Args[0] + " lib download AudioZero@1.0.0 # for a specific version.", Args: cobra.MinimumNArgs(1), Run: runDownloadCommand, } @@ -44,11 +47,11 @@ func initDownloadCommand() *cobra.Command { } func runDownloadCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstaceIgnorePlatformIndexErrors() + instance := instance.CreateInstaceIgnorePlatformIndexErrors() pairs, err := librariesindex.ParseArgs(args) if err != nil { formatter.PrintError(err, "Arguments error") - os.Exit(cli.ErrBadArgument) + os.Exit(errorcodes.ErrBadArgument) } for _, library := range pairs { libraryDownloadReq := &rpc.LibraryDownloadReq{ @@ -56,11 +59,11 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { Name: library.Name, Version: library.Version.String(), } - _, err := lib.LibraryDownload(context.Background(), libraryDownloadReq, cli.OutputProgressBar(), - cli.HTTPClientHeader) + _, err := lib.LibraryDownload(context.Background(), libraryDownloadReq, output.OutputProgressBar(), + globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error downloading "+library.String()) - os.Exit(cli.ErrNetwork) + os.Exit(errorcodes.ErrNetwork) } } } diff --git a/cli/lib/install.go b/cli/lib/install.go index 94c863d034b..1ecfa126227 100644 --- a/cli/lib/install.go +++ b/cli/lib/install.go @@ -22,7 +22,10 @@ import ( "os" "github.com/arduino/arduino-cli/arduino/libraries/librariesindex" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -35,8 +38,8 @@ func initInstallCommand() *cobra.Command { Short: "Installs one of more specified libraries into the system.", Long: "Installs one or more specified libraries into the system.", Example: "" + - " " + cli.VersionInfo.Application + " lib install AudioZero # for the latest version.\n" + - " " + cli.VersionInfo.Application + " lib install AudioZero@1.0.0 # for the specific version.", + " " + os.Args[0] + " lib install AudioZero # for the latest version.\n" + + " " + os.Args[0] + " lib install AudioZero@1.0.0 # for the specific version.", Args: cobra.MinimumNArgs(1), Run: runInstallCommand, } @@ -44,11 +47,11 @@ func initInstallCommand() *cobra.Command { } func runInstallCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstaceIgnorePlatformIndexErrors() + instance := instance.CreateInstaceIgnorePlatformIndexErrors() refs, err := librariesindex.ParseArgs(args) if err != nil { formatter.PrintError(err, "Arguments error") - os.Exit(cli.ErrBadArgument) + os.Exit(errorcodes.ErrBadArgument) } for _, library := range refs { libraryInstallReq := &rpc.LibraryInstallReq{ @@ -56,11 +59,11 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Name: library.Name, Version: library.Version.String(), } - err := lib.LibraryInstall(context.Background(), libraryInstallReq, cli.OutputProgressBar(), - cli.OutputTaskProgress(), cli.HTTPClientHeader) + err := lib.LibraryInstall(context.Background(), libraryInstallReq, output.OutputProgressBar(), + output.OutputTaskProgress(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error installing "+library.String()) - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } } diff --git a/cli/lib/lib.go b/cli/lib/lib.go index 148ddd1da30..08ad40c22cf 100644 --- a/cli/lib/lib.go +++ b/cli/lib/lib.go @@ -18,20 +18,22 @@ package lib import ( - "github.com/arduino/arduino-cli/cli" + "os" + "github.com/spf13/cobra" ) -// InitCommand prepares the command. -func InitCommand() *cobra.Command { +// NewCommand created a new `lib` command +func NewCommand() *cobra.Command { libCommand := &cobra.Command{ Use: "lib", Short: "Arduino commands about libraries.", Long: "Arduino commands about libraries.", Example: "" + - " " + cli.VersionInfo.Application + " lib install AudioZero\n" + - " " + cli.VersionInfo.Application + " lib update-index", + " " + os.Args[0] + " lib install AudioZero\n" + + " " + os.Args[0] + " lib update-index", } + libCommand.AddCommand(initDownloadCommand()) libCommand.AddCommand(initInstallCommand()) libCommand.AddCommand(initListCommand()) @@ -39,5 +41,6 @@ func InitCommand() *cobra.Command { libCommand.AddCommand(initUninstallCommand()) libCommand.AddCommand(initUpgradeCommand()) libCommand.AddCommand(initUpdateIndexCommand()) + return libCommand } diff --git a/cli/lib/list.go b/cli/lib/list.go index b75705c3fb5..2c18af59a00 100644 --- a/cli/lib/list.go +++ b/cli/lib/list.go @@ -21,7 +21,9 @@ import ( "fmt" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -36,7 +38,7 @@ func initListCommand() *cobra.Command { Use: "list", Short: "Shows a list of all installed libraries.", Long: "Shows a list of all installed libraries.", - Example: " " + cli.VersionInfo.Application + " lib list", + Example: " " + os.Args[0] + " lib list", Args: cobra.NoArgs, Run: runListCommand, } @@ -51,7 +53,7 @@ var listFlags struct { } func runListCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstaceIgnorePlatformIndexErrors() + instance := instance.CreateInstaceIgnorePlatformIndexErrors() logrus.Info("Listing") res, err := lib.LibraryList(context.Background(), &rpc.LibraryListReq{ @@ -61,11 +63,11 @@ func runListCommand(cmd *cobra.Command, args []string) { }) if err != nil { formatter.PrintError(err, "Error listing Libraries") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } if len(res.GetInstalledLibrary()) > 0 { results := res.GetInstalledLibrary() - if cli.OutputJSONOrElse(results) { + if output.OutputJSONOrElse(results) { if len(results) > 0 { fmt.Println(outputListLibrary(results)) } else { diff --git a/cli/lib/search.go b/cli/lib/search.go index 552dfbe25f4..0c5fec08983 100644 --- a/cli/lib/search.go +++ b/cli/lib/search.go @@ -24,7 +24,9 @@ import ( "sort" "strings" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -38,7 +40,7 @@ func initSearchCommand() *cobra.Command { Use: "search [LIBRARY_NAME]", Short: "Searchs for one or more libraries data.", Long: "Search for one or more libraries data (case insensitive search).", - Example: " " + cli.VersionInfo.Application + " lib search audio", + Example: " " + os.Args[0] + " lib search audio", Args: cobra.ArbitraryArgs, Run: runSearchCommand, } @@ -51,7 +53,7 @@ var searchFlags struct { } func runSearchCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstaceIgnorePlatformIndexErrors() + instance := instance.CreateInstaceIgnorePlatformIndexErrors() logrus.Info("Executing `arduino lib search`") searchResp, err := lib.LibrarySearch(context.Background(), &rpc.LibrarySearchReq{ Instance: instance, @@ -59,10 +61,10 @@ func runSearchCommand(cmd *cobra.Command, args []string) { }) if err != nil { formatter.PrintError(err, "Error saerching for Library") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } - if cli.OutputJSONOrElse(searchResp) { + if output.OutputJSONOrElse(searchResp) { results := searchResp.GetLibraries() sort.Slice(results, func(i, j int) bool { return results[i].Name < results[j].Name diff --git a/cli/lib/uninstall.go b/cli/lib/uninstall.go index 0a5f1b79291..66830a47f17 100644 --- a/cli/lib/uninstall.go +++ b/cli/lib/uninstall.go @@ -22,7 +22,9 @@ import ( "os" "github.com/arduino/arduino-cli/arduino/libraries/librariesindex" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -35,7 +37,7 @@ func initUninstallCommand() *cobra.Command { Use: "uninstall LIBRARY_NAME(S)", Short: "Uninstalls one or more libraries.", Long: "Uninstalls one or more libraries.", - Example: " " + cli.VersionInfo.Application + " lib uninstall AudioZero", + Example: " " + os.Args[0] + " lib uninstall AudioZero", Args: cobra.MinimumNArgs(1), Run: runUninstallCommand, } @@ -45,11 +47,11 @@ func initUninstallCommand() *cobra.Command { func runUninstallCommand(cmd *cobra.Command, args []string) { logrus.Info("Executing `arduino lib uninstall`") - instance := cli.CreateInstaceIgnorePlatformIndexErrors() + instance := instance.CreateInstaceIgnorePlatformIndexErrors() libRefs, err := librariesindex.ParseArgs(args) if err != nil { formatter.PrintError(err, "Arguments error") - os.Exit(cli.ErrBadArgument) + os.Exit(errorcodes.ErrBadArgument) } for _, library := range libRefs { @@ -57,10 +59,10 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { Instance: instance, Name: library.Name, Version: library.Version.String(), - }, cli.OutputTaskProgress()) + }, output.OutputTaskProgress()) if err != nil { formatter.PrintError(err, "Error uninstalling "+library.String()) - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } diff --git a/cli/lib/update_index.go b/cli/lib/update_index.go index e07ebe16f29..29f045f5a54 100644 --- a/cli/lib/update_index.go +++ b/cli/lib/update_index.go @@ -21,7 +21,9 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -33,16 +35,16 @@ func initUpdateIndexCommand() *cobra.Command { Use: "update-index", Short: "Updates the libraries index.", Long: "Updates the libraries index to the latest version.", - Example: " " + cli.VersionInfo.Application + " lib update-index", + Example: " " + os.Args[0] + " lib update-index", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - instance := cli.CreateInstaceIgnorePlatformIndexErrors() + instance := instance.CreateInstaceIgnorePlatformIndexErrors() err := commands.UpdateLibrariesIndex(context.Background(), &rpc.UpdateLibrariesIndexReq{ Instance: instance, - }, cli.OutputProgressBar()) + }, output.OutputProgressBar()) if err != nil { formatter.PrintError(err, "Error updating library index") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } }, } diff --git a/cli/lib/upgrade.go b/cli/lib/upgrade.go index 1bd0fc83b9a..fd5889e8fdf 100644 --- a/cli/lib/upgrade.go +++ b/cli/lib/upgrade.go @@ -20,7 +20,10 @@ package lib import ( "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "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/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" @@ -35,7 +38,7 @@ func initUpgradeCommand() *cobra.Command { Short: "Upgrades installed libraries.", Long: "This command ungrades all installed libraries to the latest available version." + "To upgrade a single library use the 'install' command.", - Example: " " + cli.VersionInfo.Application + " lib upgrade", + Example: " " + os.Args[0] + " lib upgrade", Args: cobra.NoArgs, Run: runUpgradeCommand, } @@ -43,14 +46,14 @@ func initUpgradeCommand() *cobra.Command { } func runUpgradeCommand(cmd *cobra.Command, args []string) { - instance := cli.CreateInstaceIgnorePlatformIndexErrors() + instance := instance.CreateInstaceIgnorePlatformIndexErrors() err := lib.LibraryUpgradeAll(context.Background(), &rpc.LibraryUpgradeAllReq{ Instance: instance, - }, cli.OutputProgressBar(), cli.OutputTaskProgress(), cli.HTTPClientHeader) + }, output.OutputProgressBar(), output.OutputTaskProgress(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error upgrading libraries") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } logrus.Info("Done") diff --git a/cli/output.go b/cli/output/output.go similarity index 82% rename from cli/output.go rename to cli/output/output.go index 20a23819286..5de1f3dd11e 100644 --- a/cli/output.go +++ b/cli/output/output.go @@ -15,30 +15,35 @@ // a commercial license, send an email to license@arduino.cc. // -package cli +package output import ( "encoding/json" "fmt" "os" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/common/formatter" - "github.com/arduino/arduino-cli/output" rpc "github.com/arduino/arduino-cli/rpc/commands" + colorable "github.com/mattn/go-colorable" ) +// TODO: Feed text output into colorable stdOut +var _ = colorable.NewColorableStdout() + // OutputJSONOrElse outputs the JSON encoding of v if the JSON output format has been // selected by the user and returns false. Otherwise no output is produced and the // function returns true. func OutputJSONOrElse(v interface{}) bool { - if !GlobalFlags.OutputJSON { + if !globals.OutputJSON { return true } d, err := json.MarshalIndent(v, "", " ") if err != nil { formatter.PrintError(err, "Error during JSON encoding of the output") - os.Exit(ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } fmt.Print(string(d)) return false @@ -47,8 +52,8 @@ func OutputJSONOrElse(v interface{}) bool { // OutputProgressBar returns a DownloadProgressCB that prints a progress bar. // If JSON output format has been selected, the callback outputs nothing. func OutputProgressBar() commands.DownloadProgressCB { - if !GlobalFlags.OutputJSON { - return output.NewDownloadProgressBarCB() + if !globals.OutputJSON { + return NewDownloadProgressBarCB() } return func(curr *rpc.DownloadProgress) { // XXX: Output progress in JSON? @@ -58,8 +63,8 @@ func OutputProgressBar() commands.DownloadProgressCB { // OutputTaskProgress returns a TaskProgressCB that prints the task progress. // If JSON output format has been selected, the callback outputs nothing. func OutputTaskProgress() commands.TaskProgressCB { - if !GlobalFlags.OutputJSON { - return output.NewTaskProgressCB() + if !globals.OutputJSON { + return NewTaskProgressCB() } return func(curr *rpc.TaskProgress) { // XXX: Output progress in JSON? diff --git a/output/rpc_progress.go b/cli/output/rpc_progress.go similarity index 100% rename from output/rpc_progress.go rename to cli/output/rpc_progress.go diff --git a/output/table.go b/cli/output/table.go similarity index 100% rename from output/table.go rename to cli/output/table.go diff --git a/output/text.go b/cli/output/text.go similarity index 100% rename from output/text.go rename to cli/output/text.go diff --git a/cli/root/root.go b/cli/root/root.go index 894011b57db..764012befcb 100644 --- a/cli/root/root.go +++ b/cli/root/root.go @@ -61,11 +61,8 @@ func Init() *cobra.Command { command.AddCommand(daemon.InitCommand()) command.AddCommand(generatedocs.InitCommand()) command.AddCommand(lib.InitCommand()) - // command.AddCommand(login.InitCommand()) - // command.AddCommand(logout.InitCommand()) command.AddCommand(sketch.InitCommand()) command.AddCommand(upload.InitCommand()) - // command.AddCommand(validate.InitCommand()) command.AddCommand(version.InitCommand()) return command } diff --git a/cli/sketch/new.go b/cli/sketch/new.go index 7ed9f20e739..39a640e354e 100644 --- a/cli/sketch/new.go +++ b/cli/sketch/new.go @@ -20,7 +20,8 @@ package sketch import ( "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/globals" "github.com/arduino/arduino-cli/common/formatter" "github.com/spf13/cobra" ) @@ -30,7 +31,7 @@ func initNewCommand() *cobra.Command { Use: "new", Short: "Create a new Sketch", Long: "Create a new Sketch", - Example: " " + cli.VersionInfo.Application + " sketch new MultiBlinker", + Example: " " + os.Args[0] + " sketch new MultiBlinker", Args: cobra.ExactArgs(1), Run: runNewCommand, } @@ -46,16 +47,16 @@ void loop() { `) func runNewCommand(cmd *cobra.Command, args []string) { - sketchDir := cli.Config.SketchbookDir.Join(args[0]) + sketchDir := globals.Config.SketchbookDir.Join(args[0]) if err := sketchDir.MkdirAll(); err != nil { formatter.PrintError(err, "Could not create sketch directory.") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } sketchFile := sketchDir.Join(args[0] + ".ino") if err := sketchFile.WriteFile(emptySketch); err != nil { formatter.PrintError(err, "Error creating sketch.") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } formatter.Print("Sketch created in: " + sketchDir.String()) diff --git a/cli/sketch/sketch.go b/cli/sketch/sketch.go index 2c735778c52..4851b877ebc 100644 --- a/cli/sketch/sketch.go +++ b/cli/sketch/sketch.go @@ -18,19 +18,17 @@ package sketch import ( - "github.com/arduino/arduino-cli/cli" + "os" + "github.com/spf13/cobra" ) -// InitCommand prepares the command. -func InitCommand() *cobra.Command { - sketchCommand := &cobra.Command{ +// NewCommand created a new `sketch` command +func NewCommand() *cobra.Command { + return &cobra.Command{ Use: "sketch", Short: "Arduino CLI Sketch Commands.", Long: "Arduino CLI Sketch Commands.", - Example: " " + cli.VersionInfo.Application + " sketch new MySketch", + Example: " " + os.Args[0] + " sketch new MySketch", } - sketchCommand.AddCommand(initNewCommand()) - //sketchCommand.AddCommand(initSyncCommand()) - return sketchCommand } diff --git a/cli/upload/upload.go b/cli/upload/upload.go index f69a451cc7d..35c4649d222 100644 --- a/cli/upload/upload.go +++ b/cli/upload/upload.go @@ -21,76 +21,80 @@ import ( "context" "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/commands/upload" "github.com/arduino/arduino-cli/common/formatter" rpc "github.com/arduino/arduino-cli/rpc/commands" "github.com/arduino/go-paths-helper" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -// InitCommand prepares the command. -func InitCommand() *cobra.Command { +var ( + fqbn string + port string + verbose bool + verify bool + importFile string +) + +// NewCommand created a new `upload` command +func NewCommand() *cobra.Command { uploadCommand := &cobra.Command{ Use: "upload", Short: "Upload Arduino sketches.", Long: "Upload Arduino sketches.", - Example: " " + cli.VersionInfo.Application + " upload /home/user/Arduino/MySketch", + Example: " " + os.Args[0] + " upload /home/user/Arduino/MySketch", Args: cobra.MaximumNArgs(1), Run: run, } - uploadCommand.Flags().StringVarP( - &flags.fqbn, "fqbn", "b", "", - "Fully Qualified Board Name, e.g.: arduino:avr:uno") - uploadCommand.Flags().StringVarP( - &flags.port, "port", "p", "", - "Upload port, e.g.: COM10 or /dev/ttyACM0") - uploadCommand.Flags().StringVarP( - &flags.importFile, "input", "i", "", - "Input file to be uploaded.") - uploadCommand.Flags().BoolVarP( - &flags.verify, "verify", "t", false, - "Verify uploaded binary after the upload.") - uploadCommand.Flags().BoolVarP( - &flags.verbose, "verbose", "v", false, - "Optional, turns on verbose mode.") - return uploadCommand -} -var flags struct { - fqbn string - port string - verbose bool - verify bool - importFile string + uploadCommand.Flags().StringVarP(&fqbn, "fqbn", "b", "", "Fully Qualified Board Name, e.g.: arduino:avr:uno") + uploadCommand.Flags().StringVarP(&port, "port", "p", "", "Upload port, e.g.: COM10 or /dev/ttyACM0") + uploadCommand.Flags().StringVarP(&importFile, "input", "i", "", "Input file to be uploaded.") + uploadCommand.Flags().BoolVarP(&verify, "verify", "t", false, "Verify uploaded binary after the upload.") + uploadCommand.Flags().BoolVarP(&verbose, "verbose", "v", false, "Optional, turns on verbose mode.") + + return uploadCommand } func run(command *cobra.Command, args []string) { - instance := cli.CreateInstance() + instance := instance.CreateInstance() var path *paths.Path if len(args) > 0 { path = paths.New(args[0]) } - sketchPath := cli.InitSketchPath(path) + sketchPath := initSketchPath(path) - uploadRes, err := upload.Upload(context.Background(), &rpc.UploadReq{ + _, err := upload.Upload(context.Background(), &rpc.UploadReq{ Instance: instance, - Fqbn: flags.fqbn, + Fqbn: fqbn, SketchPath: sketchPath.String(), - Port: flags.port, - Verbose: flags.verbose, - Verify: flags.verify, - ImportFile: flags.importFile, + Port: port, + Verbose: verbose, + Verify: verify, + ImportFile: importFile, }, os.Stdout, os.Stderr) - if err == nil { - outputUploadResp(uploadRes) - } else { + + if err != nil { formatter.PrintError(err, "Error during Upload") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } -func outputUploadResp(details *rpc.UploadResp) { +// initSketchPath returns the current working directory +func initSketchPath(sketchPath *paths.Path) *paths.Path { + if sketchPath != nil { + return sketchPath + } + wd, err := paths.Getwd() + if err != nil { + formatter.PrintError(err, "Couldn't get current working directory") + os.Exit(errorcodes.ErrGeneric) + } + logrus.Infof("Reading sketch from dir: %s", wd) + return wd } diff --git a/cli/version/version.go b/cli/version/version.go index 824460d38cc..35cd688c1d5 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,39 +19,27 @@ package version import ( "fmt" + "os" - "github.com/arduino/arduino-cli/cli" + "github.com/arduino/arduino-cli/cli/globals" + "github.com/arduino/arduino-cli/cli/output" "github.com/spf13/cobra" ) -// InitCommand prepares the command. -func InitCommand() *cobra.Command { - versionCommand := &cobra.Command{ +// NewCommand created a new `version` command +func NewCommand() *cobra.Command { + return &cobra.Command{ Use: "version", Short: "Shows version number of arduino CLI.", Long: "Shows version number of arduino CLI which is installed on your system.", - Example: " " + cli.VersionInfo.Application + " version", + Example: " " + os.Args[0] + " version", Args: cobra.NoArgs, Run: run, } - return versionCommand -} - -type versionOutput struct { - Command string `json:"command"` - Version string `json:"version"` - Commit string `json:"commit"` - BuildDate string `json:"build_date"` } func run(cmd *cobra.Command, args []string) { - res := &versionOutput{ - Command: cmd.Parent().Name(), - Version: cli.VersionInfo.VersionString, - Commit: cli.VersionInfo.Commit, - BuildDate: cli.VersionInfo.BuildDate.String(), - } - if cli.OutputJSONOrElse(res) { - fmt.Printf("%s\n", cli.VersionInfo) + if output.OutputJSONOrElse(globals.VersionInfo) { + fmt.Printf("%s\n", globals.VersionInfo) } } diff --git a/commands/compile/compile.go b/commands/compile/compile.go index 4d2a80f699d..5f7d819d8ce 100644 --- a/commands/compile/compile.go +++ b/commands/compile/compile.go @@ -29,8 +29,8 @@ import ( "github.com/arduino/arduino-cli/arduino/cores" "github.com/arduino/arduino-cli/arduino/cores/packagemanager" "github.com/arduino/arduino-cli/arduino/sketches" - "github.com/arduino/arduino-cli/cli" "github.com/arduino/arduino-cli/commands" + "github.com/arduino/arduino-cli/configs" "github.com/arduino/arduino-cli/legacy/builder" "github.com/arduino/arduino-cli/legacy/builder/i18n" "github.com/arduino/arduino-cli/legacy/builder/types" @@ -41,7 +41,7 @@ import ( ) // Compile FIXMEDOC -func Compile(ctx context.Context, req *rpc.CompileReq, outStream io.Writer, errStream io.Writer) (*rpc.CompileResp, error) { +func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.Writer, config *configs.Configuration, debug bool) (*rpc.CompileResp, error) { pm := commands.GetPackageManager(req) if pm == nil { return nil, errors.New("invalid instance") @@ -88,20 +88,20 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream io.Writer, errS builderCtx.SketchLocation = sketch.FullPath // FIXME: This will be redundant when arduino-builder will be part of the cli - if packagesDir, err := cli.Config.HardwareDirectories(); err == nil { + if packagesDir, err := config.HardwareDirectories(); err == nil { builderCtx.HardwareDirs = packagesDir } else { return nil, fmt.Errorf("cannot get hardware directories: %s", err) } - if toolsDir, err := cli.Config.BundleToolsDirectories(); err == nil { + if toolsDir, err := config.BundleToolsDirectories(); err == nil { builderCtx.ToolsDirs = toolsDir } else { return nil, fmt.Errorf("cannot get bundled tools directories: %s", err) } builderCtx.OtherLibrariesDirs = paths.NewPathList() - builderCtx.OtherLibrariesDirs.Add(cli.Config.LibrariesDir()) + builderCtx.OtherLibrariesDirs.Add(config.LibrariesDir()) if req.GetBuildPath() != "" { builderCtx.BuildPath = paths.New(req.GetBuildPath()) @@ -118,7 +118,7 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream io.Writer, errS builderCtx.USBVidPid = req.GetVidPid() builderCtx.WarningsLevel = req.GetWarnings() - if cli.GlobalFlags.Debug { + if debug { builderCtx.DebugLevel = 100 } else { builderCtx.DebugLevel = 5 @@ -138,7 +138,7 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream io.Writer, errS builderCtx.ArduinoAPIVersion = "10607" // Check if Arduino IDE is installed and get it's libraries location. - preferencesTxt := cli.Config.DataDir.Join("preferences.txt") + preferencesTxt := config.DataDir.Join("preferences.txt") ideProperties, err := properties.LoadFromPath(preferencesTxt) if err == nil { lastIdeSubProperties := ideProperties.SubTree("last").SubTree("ide") diff --git a/commands/daemon/daemon.go b/commands/daemon/daemon.go index 6ebd8929005..2413372ab4e 100644 --- a/commands/daemon/daemon.go +++ b/commands/daemon/daemon.go @@ -25,19 +25,21 @@ import ( "io" "net/http" - "github.com/arduino/arduino-cli/cli" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands/board" "github.com/arduino/arduino-cli/commands/compile" "github.com/arduino/arduino-cli/commands/core" "github.com/arduino/arduino-cli/commands/lib" "github.com/arduino/arduino-cli/commands/upload" + "github.com/arduino/arduino-cli/configs" rpc "github.com/arduino/arduino-cli/rpc/commands" ) // ArduinoCoreServerImpl FIXMEDOC type ArduinoCoreServerImpl struct { DownloaderHeaders http.Header + VersionString string + Config *configs.Configuration } // BoardDetails FIXMEDOC @@ -115,7 +117,7 @@ func (s *ArduinoCoreServerImpl) Init(req *rpc.InitReq, stream rpc.ArduinoCore_In // Version FIXMEDOC func (s *ArduinoCoreServerImpl) Version(ctx context.Context, req *rpc.VersionReq) (*rpc.VersionResp, error) { - return &rpc.VersionResp{Version: cli.VersionInfo.VersionString}, nil + return &rpc.VersionResp{Version: s.VersionString}, nil } // Compile FIXMEDOC @@ -124,7 +126,8 @@ func (s *ArduinoCoreServerImpl) Compile(req *rpc.CompileReq, stream rpc.ArduinoC stream.Context(), req, feedStream(func(data []byte) { stream.Send(&rpc.CompileResp{OutStream: data}) }), feedStream(func(data []byte) { stream.Send(&rpc.CompileResp{ErrStream: data}) }), - ) + s.Config, + false) // set debug to false if err != nil { return err } diff --git a/main.go b/main.go index 11d973d9fec..9b4fc380e23 100644 --- a/main.go +++ b/main.go @@ -21,14 +21,13 @@ import ( "os" "github.com/arduino/arduino-cli/cli" - "github.com/arduino/arduino-cli/cli/root" + "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/common/formatter" ) func main() { - cmd := root.Init() - if err := cmd.Execute(); err != nil { + if err := cli.ArduinoCli.Execute(); err != nil { formatter.PrintError(err, "Bad exit.") - os.Exit(cli.ErrGeneric) + os.Exit(errorcodes.ErrGeneric) } } diff --git a/output/output.go b/output/output.go deleted file mode 100644 index 8d5f3da0fbd..00000000000 --- a/output/output.go +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is part of arduino-cli. - * - * Copyright 2018 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 output - -import ( - colorable "github.com/mattn/go-colorable" -) - -// TODO: Feed text output into colorable stdOut -var _ = colorable.NewColorableStdout() From 683e53efe492f2d68719720c6eeb9cfa086689fb Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Thu, 11 Jul 2019 10:30:54 +0200 Subject: [PATCH 2/8] remove unused package --- cli/root/root.go | 180 ----------------------------------------------- 1 file changed, 180 deletions(-) delete mode 100644 cli/root/root.go diff --git a/cli/root/root.go b/cli/root/root.go deleted file mode 100644 index 764012befcb..00000000000 --- a/cli/root/root.go +++ /dev/null @@ -1,180 +0,0 @@ -/* - * This file is part of arduino-cli. - * - * Copyright 2018 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 root - -import ( - "fmt" - "io/ioutil" - "os" - - "github.com/arduino/arduino-cli/cli" - "github.com/arduino/arduino-cli/cli/board" - "github.com/arduino/arduino-cli/cli/compile" - "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/generatedocs" - "github.com/arduino/arduino-cli/cli/lib" - "github.com/arduino/arduino-cli/cli/sketch" - "github.com/arduino/arduino-cli/cli/upload" - "github.com/arduino/arduino-cli/cli/version" - "github.com/arduino/arduino-cli/common/formatter" - "github.com/arduino/arduino-cli/configs" - "github.com/arduino/go-paths-helper" - "github.com/mattn/go-colorable" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "golang.org/x/crypto/ssh/terminal" -) - -// Init prepares the cobra root command. -func Init() *cobra.Command { - command := &cobra.Command{ - Use: "arduino-cli", - Short: "Arduino CLI.", - Long: "Arduino Command Line Interface (arduino-cli).", - Example: " " + cli.VersionInfo.Application + " [flags...]", - PersistentPreRun: preRun, - } - command.PersistentFlags().BoolVar(&cli.GlobalFlags.Debug, "debug", false, "Enables debug output (super verbose, used to debug the CLI).") - command.PersistentFlags().StringVar(&outputFormat, "format", "text", "The output format, can be [text|json].") - command.PersistentFlags().StringVar(&yamlConfigFile, "config-file", "", "The custom config file (if not specified the default will be used).") - command.AddCommand(board.InitCommand()) - command.AddCommand(compile.InitCommand()) - command.AddCommand(config.InitCommand()) - command.AddCommand(core.InitCommand()) - command.AddCommand(daemon.InitCommand()) - command.AddCommand(generatedocs.InitCommand()) - command.AddCommand(lib.InitCommand()) - command.AddCommand(sketch.InitCommand()) - command.AddCommand(upload.InitCommand()) - command.AddCommand(version.InitCommand()) - return command -} - -var outputFormat string -var yamlConfigFile string - -func preRun(cmd *cobra.Command, args []string) { - // Reset logrus if debug flag changed. - if !cli.GlobalFlags.Debug { - // Discard logrus output if no debug. - logrus.SetOutput(ioutil.Discard) - } else { - // Else print on stderr. - - // Workaround to get colored output on windows - if terminal.IsTerminal(int(os.Stdout.Fd())) { - logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) - } - logrus.SetOutput(colorable.NewColorableStdout()) - cli.ErrLogrus.Out = colorable.NewColorableStderr() - formatter.SetLogger(cli.ErrLogrus) - } - initConfigs() - - logrus.Info(cli.VersionInfo.Application + "-" + cli.VersionInfo.VersionString) - logrus.Info("Starting root command preparation (`arduino`)") - switch outputFormat { - case "text": - formatter.SetFormatter("text") - cli.GlobalFlags.OutputJSON = false - case "json": - formatter.SetFormatter("json") - cli.GlobalFlags.OutputJSON = true - default: - formatter.PrintErrorMessage("Invalid output format: " + outputFormat) - os.Exit(cli.ErrBadCall) - } - - logrus.Info("Formatter set") - if !formatter.IsCurrentFormat("text") { - cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { - logrus.Warn("Calling help on JSON format") - formatter.PrintErrorMessage("Invalid Call : should show Help, but it is available only in TEXT mode.") - os.Exit(cli.ErrBadCall) - }) - } -} - -// initConfigs initializes the configuration from the specified file. -func initConfigs() { - // Start with default configuration - if conf, err := configs.NewConfiguration(); err != nil { - logrus.WithError(err).Error("Error creating default configuration") - formatter.PrintError(err, "Error creating default configuration") - os.Exit(cli.ErrGeneric) - } else { - cli.Config = conf - } - - // Read configuration from global config file - logrus.Info("Checking for config file in: " + cli.Config.ConfigFile.String()) - if cli.Config.ConfigFile.Exist() { - readConfigFrom(cli.Config.ConfigFile) - } - - if cli.Config.IsBundledInDesktopIDE() { - logrus.Info("CLI is bundled into the IDE") - err := cli.Config.LoadFromDesktopIDEPreferences() - if err != nil { - logrus.WithError(err).Warn("Did not manage to get config file of IDE, using default configuration") - } - } else { - logrus.Info("CLI is not bundled into the IDE") - } - - // Read configuration from parent folders (project config) - if pwd, err := paths.Getwd(); err != nil { - logrus.WithError(err).Warn("Did not manage to find current path") - if path := paths.New("arduino-cli.yaml"); path.Exist() { - readConfigFrom(path) - } - } else { - cli.Config.Navigate(pwd) - } - - // Read configuration from old configuration file if found, but output a warning. - if old := paths.New(".cli-config.yml"); old.Exist() { - logrus.Errorf("Old configuration file detected: %s.", old) - logrus.Info("The name of this file has been changed to `arduino-cli.yaml`, please rename the file fix it.") - formatter.PrintError( - fmt.Errorf("WARNING: Old configuration file detected: %s", old), - "The name of this file has been changed to `arduino-cli.yaml`, in a future release we will not support"+ - "the old name `.cli-config.yml` anymore. Please rename the file to `arduino-cli.yaml` to silence this warning.") - readConfigFrom(old) - } - - // Read configuration from environment vars - cli.Config.LoadFromEnv() - - // Read configuration from user specified file - if yamlConfigFile != "" { - cli.Config.ConfigFile = paths.New(yamlConfigFile) - readConfigFrom(cli.Config.ConfigFile) - } - - logrus.Info("Configuration set") -} - -func readConfigFrom(path *paths.Path) { - logrus.Infof("Reading configuration from %s", path) - if err := cli.Config.LoadFromYAML(path); err != nil { - logrus.WithError(err).Warnf("Could not read configuration from %s", path) - } -} From c8edd7651c8689e905e9a1c60b4dd2b4b0ee72cd Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Thu, 11 Jul 2019 10:32:31 +0200 Subject: [PATCH 3/8] use a better naming for output functions --- cli/board/attach.go | 2 +- cli/board/details.go | 2 +- cli/board/list.go | 2 +- cli/board/listall.go | 2 +- cli/core/download.go | 2 +- cli/core/install.go | 4 ++-- cli/core/list.go | 2 +- cli/core/search.go | 2 +- cli/core/update_index.go | 2 +- cli/core/upgrade.go | 2 +- cli/globals/globals.go | 2 +- cli/instance/instance.go | 4 ++-- cli/lib/download.go | 2 +- cli/lib/install.go | 4 ++-- cli/lib/list.go | 2 +- cli/lib/search.go | 2 +- cli/lib/uninstall.go | 2 +- cli/lib/update_index.go | 2 +- cli/lib/upgrade.go | 2 +- cli/output/output.go | 12 ++++++------ cli/version/version.go | 2 +- go.mod | 10 ++++++++++ go.sum | 17 +++++++++++++++++ 23 files changed, 56 insertions(+), 29 deletions(-) diff --git a/cli/board/attach.go b/cli/board/attach.go index f2a5b7de6b4..0b8f8bcd016 100644 --- a/cli/board/attach.go +++ b/cli/board/attach.go @@ -61,7 +61,7 @@ func runAttachCommand(cmd *cobra.Command, args []string) { BoardUri: args[0], SketchPath: path, SearchTimeout: attachFlags.searchTimeout, - }, output.OutputTaskProgress()) + }, output.TaskProgress()) if err != nil { formatter.PrintError(err, "attach board error") os.Exit(errorcodes.ErrGeneric) diff --git a/cli/board/details.go b/cli/board/details.go index 49be6eac03b..e39f5e56842 100644 --- a/cli/board/details.go +++ b/cli/board/details.go @@ -50,7 +50,7 @@ func runDetailsCommand(cmd *cobra.Command, args []string) { formatter.PrintError(err, "Error getting board details") os.Exit(errorcodes.ErrGeneric) } - if output.OutputJSONOrElse(res) { + if output.JSONOrElse(res) { outputDetailsResp(res) } } diff --git a/cli/board/list.go b/cli/board/list.go index 9ed019f68a3..79da263ac62 100644 --- a/cli/board/list.go +++ b/cli/board/list.go @@ -67,7 +67,7 @@ func runListCommand(cmd *cobra.Command, args []string) { os.Exit(errorcodes.ErrNetwork) } - if output.OutputJSONOrElse(resp) { + if output.JSONOrElse(resp) { outputListResp(resp) } } diff --git a/cli/board/listall.go b/cli/board/listall.go index 4d81986dd0c..2c2d2a85122 100644 --- a/cli/board/listall.go +++ b/cli/board/listall.go @@ -58,7 +58,7 @@ func runListAllCommand(cmd *cobra.Command, args []string) { os.Exit(errorcodes.ErrGeneric) } - if output.OutputJSONOrElse(list) { + if output.JSONOrElse(list) { outputBoardListAll(list) } } diff --git a/cli/core/download.go b/cli/core/download.go index b5dedc6e570..1dba6a738fc 100644 --- a/cli/core/download.go +++ b/cli/core/download.go @@ -58,7 +58,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { Architecture: platformRef.Architecture, Version: platformRef.Version, } - _, err := core.PlatformDownload(context.Background(), platformDownloadreq, output.OutputProgressBar(), + _, err := core.PlatformDownload(context.Background(), platformDownloadreq, output.ProgressBar(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error downloading "+args[i]) diff --git a/cli/core/install.go b/cli/core/install.go index 7f65a8eac5c..d4e5b8152da 100644 --- a/cli/core/install.go +++ b/cli/core/install.go @@ -60,8 +60,8 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Architecture: platformRef.Architecture, Version: platformRef.Version, } - _, err := core.PlatformInstall(context.Background(), plattformInstallReq, output.OutputProgressBar(), - output.OutputTaskProgress(), globals.HTTPClientHeader) + _, err := core.PlatformInstall(context.Background(), plattformInstallReq, output.ProgressBar(), + output.TaskProgress(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error during install") os.Exit(errorcodes.ErrGeneric) diff --git a/cli/core/list.go b/cli/core/list.go index 4ac1c377b9c..3f38657ae9c 100644 --- a/cli/core/list.go +++ b/cli/core/list.go @@ -64,7 +64,7 @@ func runListCommand(cmd *cobra.Command, args []string) { } installed := resp.GetInstalledPlatform() if installed != nil && len(installed) > 0 { - if output.OutputJSONOrElse(installed) { + if output.JSONOrElse(installed) { outputInstalledCores(installed) } } diff --git a/cli/core/search.go b/cli/core/search.go index 057c6d95c52..5c08f3d300c 100644 --- a/cli/core/search.go +++ b/cli/core/search.go @@ -63,7 +63,7 @@ func runSearchCommand(cmd *cobra.Command, args []string) { } coreslist := resp.GetSearchOutput() - if output.OutputJSONOrElse(coreslist) { + if output.JSONOrElse(coreslist) { if len(coreslist) > 0 { outputSearchCores(coreslist) } else { diff --git a/cli/core/update_index.go b/cli/core/update_index.go index 75e1ed70461..a146927a248 100644 --- a/cli/core/update_index.go +++ b/cli/core/update_index.go @@ -49,7 +49,7 @@ func runUpdateIndexCommand(cmd *cobra.Command, args []string) { _, err := commands.UpdateIndex(context.Background(), &rpc.UpdateIndexReq{ Instance: instance, - }, output.OutputProgressBar()) + }, output.ProgressBar()) if err != nil { formatter.PrintError(err, "Error updating index") os.Exit(errorcodes.ErrGeneric) diff --git a/cli/core/upgrade.go b/cli/core/upgrade.go index 4159df94b01..ec951e7915a 100644 --- a/cli/core/upgrade.go +++ b/cli/core/upgrade.go @@ -63,7 +63,7 @@ func runUpgradeCommand(cmd *cobra.Command, args []string) { Instance: instance, PlatformPackage: platformRef.Package, Architecture: platformRef.Architecture, - }, output.OutputProgressBar(), output.OutputTaskProgress(), + }, output.ProgressBar(), output.TaskProgress(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error during upgrade") diff --git a/cli/globals/globals.go b/cli/globals/globals.go index cf1965b2da0..058fc290e5b 100644 --- a/cli/globals/globals.go +++ b/cli/globals/globals.go @@ -26,7 +26,7 @@ var ( VersionInfo = version.NewInfo(filepath.Base(os.Args[0])) // Config FIXMEDOC Config *configs.Configuration - + // YAMLConfigFile contains the path to the config file YAMLConfigFile string ) diff --git a/cli/instance/instance.go b/cli/instance/instance.go index 1b04ac5d282..b29d2b9bbf8 100644 --- a/cli/instance/instance.go +++ b/cli/instance/instance.go @@ -37,14 +37,14 @@ func initInstance() *rpc.InitResp { logrus.Info("Initializing package manager") req := packageManagerInitReq() - resp, err := commands.Init(context.Background(), req, output.OutputProgressBar(), output.OutputTaskProgress(), globals.HTTPClientHeader) + resp, err := commands.Init(context.Background(), req, output.ProgressBar(), output.TaskProgress(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error initializing package manager") os.Exit(errorcodes.ErrGeneric) } if resp.GetLibrariesIndexError() != "" { commands.UpdateLibrariesIndex(context.Background(), - &rpc.UpdateLibrariesIndexReq{Instance: resp.GetInstance()}, output.OutputProgressBar()) + &rpc.UpdateLibrariesIndexReq{Instance: resp.GetInstance()}, output.ProgressBar()) rescResp, err := commands.Rescan(context.Background(), &rpc.RescanReq{Instance: resp.GetInstance()}) if rescResp.GetLibrariesIndexError() != "" { formatter.PrintErrorMessage("Error loading library index: " + rescResp.GetLibrariesIndexError()) diff --git a/cli/lib/download.go b/cli/lib/download.go index 5049480c514..8787338c7ef 100644 --- a/cli/lib/download.go +++ b/cli/lib/download.go @@ -59,7 +59,7 @@ func runDownloadCommand(cmd *cobra.Command, args []string) { Name: library.Name, Version: library.Version.String(), } - _, err := lib.LibraryDownload(context.Background(), libraryDownloadReq, output.OutputProgressBar(), + _, err := lib.LibraryDownload(context.Background(), libraryDownloadReq, output.ProgressBar(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error downloading "+library.String()) diff --git a/cli/lib/install.go b/cli/lib/install.go index 1ecfa126227..70bbf50bd59 100644 --- a/cli/lib/install.go +++ b/cli/lib/install.go @@ -59,8 +59,8 @@ func runInstallCommand(cmd *cobra.Command, args []string) { Name: library.Name, Version: library.Version.String(), } - err := lib.LibraryInstall(context.Background(), libraryInstallReq, output.OutputProgressBar(), - output.OutputTaskProgress(), globals.HTTPClientHeader) + err := lib.LibraryInstall(context.Background(), libraryInstallReq, output.ProgressBar(), + output.TaskProgress(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error installing "+library.String()) os.Exit(errorcodes.ErrGeneric) diff --git a/cli/lib/list.go b/cli/lib/list.go index 2c18af59a00..dab2b334092 100644 --- a/cli/lib/list.go +++ b/cli/lib/list.go @@ -67,7 +67,7 @@ func runListCommand(cmd *cobra.Command, args []string) { } if len(res.GetInstalledLibrary()) > 0 { results := res.GetInstalledLibrary() - if output.OutputJSONOrElse(results) { + if output.JSONOrElse(results) { if len(results) > 0 { fmt.Println(outputListLibrary(results)) } else { diff --git a/cli/lib/search.go b/cli/lib/search.go index 0c5fec08983..b44263e7f23 100644 --- a/cli/lib/search.go +++ b/cli/lib/search.go @@ -64,7 +64,7 @@ func runSearchCommand(cmd *cobra.Command, args []string) { os.Exit(errorcodes.ErrGeneric) } - if output.OutputJSONOrElse(searchResp) { + if output.JSONOrElse(searchResp) { results := searchResp.GetLibraries() sort.Slice(results, func(i, j int) bool { return results[i].Name < results[j].Name diff --git a/cli/lib/uninstall.go b/cli/lib/uninstall.go index 66830a47f17..f398addc7f8 100644 --- a/cli/lib/uninstall.go +++ b/cli/lib/uninstall.go @@ -59,7 +59,7 @@ func runUninstallCommand(cmd *cobra.Command, args []string) { Instance: instance, Name: library.Name, Version: library.Version.String(), - }, output.OutputTaskProgress()) + }, output.TaskProgress()) if err != nil { formatter.PrintError(err, "Error uninstalling "+library.String()) os.Exit(errorcodes.ErrGeneric) diff --git a/cli/lib/update_index.go b/cli/lib/update_index.go index 29f045f5a54..5769aac8aa0 100644 --- a/cli/lib/update_index.go +++ b/cli/lib/update_index.go @@ -41,7 +41,7 @@ func initUpdateIndexCommand() *cobra.Command { instance := instance.CreateInstaceIgnorePlatformIndexErrors() err := commands.UpdateLibrariesIndex(context.Background(), &rpc.UpdateLibrariesIndexReq{ Instance: instance, - }, output.OutputProgressBar()) + }, output.ProgressBar()) if err != nil { formatter.PrintError(err, "Error updating library index") os.Exit(errorcodes.ErrGeneric) diff --git a/cli/lib/upgrade.go b/cli/lib/upgrade.go index fd5889e8fdf..9737e6f4c91 100644 --- a/cli/lib/upgrade.go +++ b/cli/lib/upgrade.go @@ -50,7 +50,7 @@ func runUpgradeCommand(cmd *cobra.Command, args []string) { err := lib.LibraryUpgradeAll(context.Background(), &rpc.LibraryUpgradeAllReq{ Instance: instance, - }, output.OutputProgressBar(), output.OutputTaskProgress(), globals.HTTPClientHeader) + }, output.ProgressBar(), output.TaskProgress(), globals.HTTPClientHeader) if err != nil { formatter.PrintError(err, "Error upgrading libraries") os.Exit(errorcodes.ErrGeneric) diff --git a/cli/output/output.go b/cli/output/output.go index 5de1f3dd11e..f9c6d4bf536 100644 --- a/cli/output/output.go +++ b/cli/output/output.go @@ -33,10 +33,10 @@ import ( // TODO: Feed text output into colorable stdOut var _ = colorable.NewColorableStdout() -// OutputJSONOrElse outputs the JSON encoding of v if the JSON output format has been +// JSONOrElse outputs the JSON encoding of v if the JSON output format has been // selected by the user and returns false. Otherwise no output is produced and the // function returns true. -func OutputJSONOrElse(v interface{}) bool { +func JSONOrElse(v interface{}) bool { if !globals.OutputJSON { return true } @@ -49,9 +49,9 @@ func OutputJSONOrElse(v interface{}) bool { return false } -// OutputProgressBar returns a DownloadProgressCB that prints a progress bar. +// ProgressBar returns a DownloadProgressCB that prints a progress bar. // If JSON output format has been selected, the callback outputs nothing. -func OutputProgressBar() commands.DownloadProgressCB { +func ProgressBar() commands.DownloadProgressCB { if !globals.OutputJSON { return NewDownloadProgressBarCB() } @@ -60,9 +60,9 @@ func OutputProgressBar() commands.DownloadProgressCB { } } -// OutputTaskProgress returns a TaskProgressCB that prints the task progress. +// TaskProgress returns a TaskProgressCB that prints the task progress. // If JSON output format has been selected, the callback outputs nothing. -func OutputTaskProgress() commands.TaskProgressCB { +func TaskProgress() commands.TaskProgressCB { if !globals.OutputJSON { return NewTaskProgressCB() } diff --git a/cli/version/version.go b/cli/version/version.go index 35cd688c1d5..7c5e720e974 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -39,7 +39,7 @@ func NewCommand() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - if output.OutputJSONOrElse(globals.VersionInfo) { + if output.JSONOrElse(globals.VersionInfo) { fmt.Printf("%s\n", globals.VersionInfo) } } diff --git a/go.mod b/go.mod index 4fd220f90bc..621f01fae52 100644 --- a/go.mod +++ b/go.mod @@ -41,9 +41,19 @@ require ( go.bug.st/downloader v1.1.0 go.bug.st/relaxed-semver v0.0.0-20181022103824-0265409c5852 go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45 +<<<<<<< HEAD golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/net v0.0.0-20190311183353-d8887717615a golang.org/x/text v0.3.0 +======= + golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 + golang.org/x/lint v0.0.0-20190409202823-959b441ac422 // indirect + golang.org/x/net v0.0.0-20190628185345-da137c7871d7 + golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 // indirect + golang.org/x/text v0.3.2 + golang.org/x/tools v0.0.0-20190710184609-286818132824 // indirect + google.golang.org/appengine v1.4.0 // indirect +>>>>>>> use a better naming for output functions google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d // indirect google.golang.org/grpc v1.21.1 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect diff --git a/go.sum b/go.sum index b3df07b4de4..b3bd9275a40 100644 --- a/go.sum +++ b/go.sum @@ -125,31 +125,48 @@ go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45/go.mod h1:dRSl/CVCTf56CkX golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 h1:6ZQFf1D2YYDDI7eSwW8adlkkavTB9sw5I24FVtEvNUQ= +golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190710184609-286818132824 h1:dOGf5KG5e5tnConXcTAnHv2YgmYJtrYjN9b1cMC21TY= +golang.org/x/tools v0.0.0-20190710184609-286818132824/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= From f179a91bc6ff455554a13509ff06cf1e302dd143 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Thu, 11 Jul 2019 17:48:44 +0200 Subject: [PATCH 4/8] fix missing subcommands --- cli/sketch/sketch.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/sketch/sketch.go b/cli/sketch/sketch.go index 4851b877ebc..178a40fa7b7 100644 --- a/cli/sketch/sketch.go +++ b/cli/sketch/sketch.go @@ -25,10 +25,14 @@ import ( // NewCommand created a new `sketch` command func NewCommand() *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "sketch", Short: "Arduino CLI Sketch Commands.", Long: "Arduino CLI Sketch Commands.", Example: " " + os.Args[0] + " sketch new MySketch", } + + cmd.AddCommand(initNewCommand()) + + return cmd } From 17aa937b61e5f2e0d86ddacca8da9d54680c8d37 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Thu, 11 Jul 2019 17:49:26 +0200 Subject: [PATCH 5/8] split function for testing sake --- cli/cli.go | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/cli/cli.go b/cli/cli.go index d8af61e7b25..cbfab85eb77 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -59,20 +59,25 @@ var ( // Init the cobra root command func init() { - ArduinoCli.AddCommand(board.NewCommand()) - ArduinoCli.AddCommand(compile.NewCommand()) - ArduinoCli.AddCommand(config.NewCommand()) - ArduinoCli.AddCommand(core.NewCommand()) - ArduinoCli.AddCommand(daemon.NewCommand()) - ArduinoCli.AddCommand(generatedocs.NewCommand()) - ArduinoCli.AddCommand(lib.NewCommand()) - ArduinoCli.AddCommand(sketch.NewCommand()) - ArduinoCli.AddCommand(upload.NewCommand()) - ArduinoCli.AddCommand(version.NewCommand()) + createCliCommandTree(ArduinoCli) +} + +// this is here only for testing +func createCliCommandTree(cmd *cobra.Command) { + cmd.AddCommand(board.NewCommand()) + cmd.AddCommand(compile.NewCommand()) + cmd.AddCommand(config.NewCommand()) + cmd.AddCommand(core.NewCommand()) + cmd.AddCommand(daemon.NewCommand()) + cmd.AddCommand(generatedocs.NewCommand()) + cmd.AddCommand(lib.NewCommand()) + cmd.AddCommand(sketch.NewCommand()) + cmd.AddCommand(upload.NewCommand()) + cmd.AddCommand(version.NewCommand()) - ArduinoCli.PersistentFlags().BoolVar(&globals.Debug, "debug", false, "Enables debug output (super verbose, used to debug the CLI).") - ArduinoCli.PersistentFlags().StringVar(&outputFormat, "format", "text", "The output format, can be [text|json].") - ArduinoCli.PersistentFlags().StringVar(&globals.YAMLConfigFile, "config-file", "", "The custom config file (if not specified the default will be used).") + cmd.PersistentFlags().BoolVar(&globals.Debug, "debug", false, "Enables debug output (super verbose, used to debug the CLI).") + cmd.PersistentFlags().StringVar(&outputFormat, "format", "text", "The output format, can be [text|json].") + cmd.PersistentFlags().StringVar(&globals.YAMLConfigFile, "config-file", "", "The custom config file (if not specified the default will be used).") } func preRun(cmd *cobra.Command, args []string) { From 18d9529b3d4600883eff35c8a1480a73550b2bcc Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Thu, 11 Jul 2019 17:50:04 +0200 Subject: [PATCH 6/8] fixed tests to work with the new layout, marked as integration tests --- cli/cli_test.go | 680 +++++++++++++++++++++++------------------------- 1 file changed, 327 insertions(+), 353 deletions(-) diff --git a/cli/cli_test.go b/cli/cli_test.go index 1a5538bc345..fd638cb719c 100644 --- a/cli/cli_test.go +++ b/cli/cli_test.go @@ -15,76 +15,137 @@ * a commercial license, send an email to license@arduino.cc. */ -package cli_test +package cli import ( "encoding/json" + "flag" "fmt" "io/ioutil" "os" + "os/exec" + "path/filepath" "strings" "testing" "bou.ke/monkey" - "github.com/arduino/arduino-cli/cli" paths "github.com/arduino/go-paths-helper" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" semver "go.bug.st/relaxed-semver" ) -// Redirecting stdOut so we can analyze output line by -// line and check with what we want. -var stdOut = os.Stdout +var ( + // Redirecting stdOut so we can analyze output line by + // line and check with what we want. + stdOut = os.Stdout + + currDownloadDir string + currDataDir string + currSketchbookDir string +) type stdOutRedirect struct { tempFile *os.File - t *testing.T } -func (grabber *stdOutRedirect) Open(t *testing.T) { +func (grabber *stdOutRedirect) Open() { tempFile, err := ioutil.TempFile(os.TempDir(), "test") - require.NoError(t, err, "Opening temp output file") + if err != nil { + panic("Opening temp output file") + } os.Stdout = tempFile grabber.tempFile = tempFile - grabber.t = t } func (grabber *stdOutRedirect) GetOutput() []byte { _, err := grabber.tempFile.Seek(0, 0) - require.NoError(grabber.t, err, "Rewinding temp output file") + if err != nil { + panic("Rewinding temp output file") + } + output, err := ioutil.ReadAll(grabber.tempFile) - require.NoError(grabber.t, err, "Reading temp output file") + if err != nil { + panic("Reading temp output file") + } + return output } func (grabber *stdOutRedirect) Close() { grabber.tempFile.Close() err := os.Remove(grabber.tempFile.Name()) - assert.NoError(grabber.t, err, "Removing temp output file") + if err != nil { + panic("Removing temp output file") + } os.Stdout = stdOut } +func TestMain(m *testing.M) { + // all these tests perform actual operations, don't run in short mode + flag.Parse() + if testing.Short() { + fmt.Println("skip integration tests") + os.Exit(0) + } + + // SetUp + currDataDir = tmpDirOrDie() + os.Setenv("ARDUINO_DATA_DIR", currDataDir) + currDownloadDir = tmpDirOrDie() + os.Setenv("ARDUINO_DOWNLOADS_DIR", currDownloadDir) + currSketchbookDir = filepath.Join("testdata", "sketchbook_with_custom_hardware") + os.Setenv("ARDUINO_SKETCHBOOK_DIR", currSketchbookDir) + + // Run + res := m.Run() + + // TearDown + os.RemoveAll(currDataDir) + os.Unsetenv("ARDUINO_DATA_DIR") + currDataDir = "" + os.RemoveAll(currDownloadDir) + os.Unsetenv("ARDUINO_DOWNLOADS_DIR") + currDownloadDir = "" + os.Unsetenv("ARDUINO_SKETCHBOOK_DIR") + + os.Exit(res) +} + +func tmpDirOrDie() string { + dir, err := ioutil.TempDir(os.TempDir(), "cli_test") + if err != nil { + panic(fmt.Sprintf("error creating tmp dir: %v", err)) + } + return dir +} + // executeWithArgs executes the Cobra Command with the given arguments // and intercepts any errors (even `os.Exit()` ones), returning the exit code -func executeWithArgs(t *testing.T, args ...string) (int, []byte) { +func executeWithArgs(args ...string) (int, []byte) { var output []byte var exitCode int fmt.Printf("RUNNING: %s\n", args) // This closure is here because we won't that the defer are executed after the end of the "executeWithArgs" method func() { - // Create an empty config for the CLI test + // Create an empty config for the CLI test in the same dir of the test conf := paths.New("arduino-cli.yaml") - require.False(t, conf.Exist()) - err := conf.WriteFile([]byte("board_manager:\n additional_urls:\n")) - require.NoError(t, err) + if conf.Exist() { + panic("config file must not exist already") + } + + if err := conf.WriteFile([]byte("board_manager:\n additional_urls:\n")); err != nil { + panic(err) + } + defer func() { - require.NoError(t, conf.Remove()) + if err := conf.Remove(); err != nil { + panic(err) + } }() redirect := &stdOutRedirect{} - redirect.Open(t) + redirect.Open() defer func() { output = redirect.GetOutput() redirect.Close() @@ -110,165 +171,127 @@ func executeWithArgs(t *testing.T, args ...string) (int, []byte) { } }() - // Execute the CLI command, in this process - cli.ArduinoCli.SetArgs(args) - cli.ArduinoCli.Execute() + // Execute the CLI command, start fresh every time + ArduinoCli.ResetCommands() + ArduinoCli.ResetFlags() + createCliCommandTree(ArduinoCli) + ArduinoCli.SetArgs(args) + ArduinoCli.Execute() }() return exitCode, output } -var currDownloadDir *paths.Path - -func useSharedDownloadDir(t *testing.T) func() { - tmp := paths.TempDir().Join("arduino-cli-test-staging") - err := tmp.MkdirAll() - require.NoError(t, err, "making shared staging dir") - os.Setenv("ARDUINO_DOWNLOADS_DIR", tmp.String()) - currDownloadDir = tmp - fmt.Printf("ARDUINO_DOWNLOADS_DIR = %s\n", os.Getenv("ARDUINO_DOWNLOADS_DIR")) - - return func() { - os.Unsetenv("ARDUINO_DOWNLOADS_DIR") - currDownloadDir = nil - fmt.Printf("ARDUINO_DOWNLOADS_DIR = %s\n", os.Getenv("ARDUINO_DOWNLOADS_DIR")) - } -} - -var currDataDir *paths.Path - -func makeTempDataDir(t *testing.T) func() { - tmp, err := paths.MkTempDir("", "test") - require.NoError(t, err, "making temporary data dir") - os.Setenv("ARDUINO_DATA_DIR", tmp.String()) - currDataDir = tmp - fmt.Printf("ARDUINO_DATA_DIR = %s\n", os.Getenv("ARDUINO_DATA_DIR")) - - err = tmp.RemoveAll() // To test if the data dir is automatically created - require.NoError(t, err) - - return func() { - os.Unsetenv("ARDUINO_DATA_DIR") - currDataDir = nil - tmp.RemoveAll() - fmt.Printf("ARDUINO_DATA_DIR = %s\n", os.Getenv("ARDUINO_DATA_DIR")) - } -} - -var currSketchbookDir *paths.Path - -func makeTempSketchbookDir(t *testing.T) func() { - tmp, err := paths.MkTempDir("", "test") - require.NoError(t, err, "making temporary staging dir") - os.Setenv("ARDUINO_SKETCHBOOK_DIR", tmp.String()) - currSketchbookDir = tmp - err = tmp.RemoveAll() // To test if the sketchbook dir is automatically created - require.NoError(t, err) - - fmt.Printf("ARDUINO_SKETCHBOOK_DIR = %s\n", os.Getenv("ARDUINO_SKETCHBOOK_DIR")) - return func() { - os.Unsetenv("ARDUINO_SKETCHBOOK_DIR") - currSketchbookDir = nil - tmp.RemoveAll() - fmt.Printf("ARDUINO_SKETCHBOOK_DIR = %s\n", os.Getenv("ARDUINO_SKETCHBOOK_DIR")) +func detectLatestAVRCore(t *testing.T) string { + jsonFile := filepath.Join(currDataDir, "package_index.json") + type index struct { + Packages []struct { + Name string + Platforms []struct { + Architecture string + Version string + } + } } -} - -func setSketchbookDir(t *testing.T, tmp *paths.Path) func() { - os.Setenv("ARDUINO_SKETCHBOOK_DIR", tmp.String()) - currSketchbookDir = tmp - - fmt.Printf("ARDUINO_SKETCHBOOK_DIR = %s\n", os.Getenv("ARDUINO_SKETCHBOOK_DIR")) - return func() { - os.Unsetenv("ARDUINO_SKETCHBOOK_DIR") - currSketchbookDir = nil - fmt.Printf("ARDUINO_SKETCHBOOK_DIR = %s\n", os.Getenv("ARDUINO_SKETCHBOOK_DIR")) + var jsonIndex index + jsonData, err := ioutil.ReadFile(jsonFile) + require.NoError(t, err, "reading package_index.json") + err = json.Unmarshal(jsonData, &jsonIndex) + require.NoError(t, err, "parsing package_index.json") + latest := semver.MustParse("0.0.1") + for _, p := range jsonIndex.Packages { + if p.Name == "arduino" { + for _, pl := range p.Platforms { + ver, err := semver.Parse(pl.Version) + require.NoError(t, err, "version parsing") + if pl.Architecture == "avr" && ver.GreaterThan(latest) { + latest = ver + } + } + break + } } + require.NotEmpty(t, latest, "latest avr core version") + fmt.Println("Latest AVR core version:", latest) + return latest.String() } // END -- Utility functions -func TestUploadCommands(t *testing.T) { - defer makeTempDataDir(t)() - defer useSharedDownloadDir(t)() - defer setSketchbookDir(t, paths.New("testdata", "sketchbook_with_custom_hardware"))() - - updateCoreIndex(t) +func TestUploadIntegration(t *testing.T) { + exitCode, _ := executeWithArgs("core", "update-index") + require.Zero(t, exitCode) - exitCode, _ := executeWithArgs(t, "core", "install", "arduino:avr") - require.Zero(t, exitCode, "exit code") + exitCode, _ = executeWithArgs("core", "install", "arduino:avr") + require.Zero(t, exitCode) // -i flag - exitCode, d := executeWithArgs(t, "upload", "-i", currSketchbookDir.Join("test.hex").String(), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") - require.Zero(t, exitCode, "exit code") + exitCode, d := executeWithArgs("upload", "-i", filepath.Join(currSketchbookDir, "test.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") + require.Zero(t, exitCode) require.Contains(t, string(d), "QUIET") require.Contains(t, string(d), "NOVERIFY") require.Contains(t, string(d), "testdata/sketchbook_with_custom_hardware/test.hex") // -i flag with implicit extension - exitCode, d = executeWithArgs(t, "upload", "-i", currSketchbookDir.Join("test").String(), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("upload", "-i", filepath.Join(currSketchbookDir, "test"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") + require.Zero(t, exitCode) require.Contains(t, string(d), "QUIET") require.Contains(t, string(d), "NOVERIFY") require.Contains(t, string(d), "testdata/sketchbook_with_custom_hardware/test.hex") // -i with absolute path - fullPath, err := currSketchbookDir.Join("test.hex").Abs() - require.NoError(t, err, "absolute path of test.hex") - exitCode, d = executeWithArgs(t, "upload", "-i", fullPath.String(), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") - require.Zero(t, exitCode, "exit code") + fullPath, err := filepath.Abs(filepath.Join(currSketchbookDir, "test.hex")) + require.NoError(t, err) + exitCode, d = executeWithArgs("upload", "-i", fullPath, "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") + require.Zero(t, exitCode) require.Contains(t, string(d), "QUIET") require.Contains(t, string(d), "NOVERIFY") require.Contains(t, string(d), "testdata/sketchbook_with_custom_hardware/test.hex") // -v verbose - exitCode, d = executeWithArgs(t, "upload", "-v", "-i", currSketchbookDir.Join("test.hex").String(), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("upload", "-v", "-t", "-i", filepath.Join(currSketchbookDir, "test.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") + require.Zero(t, exitCode) require.Contains(t, string(d), "VERBOSE") - require.Contains(t, string(d), "NOVERIFY") + require.Contains(t, string(d), "VERIFY") require.Contains(t, string(d), "testdata/sketchbook_with_custom_hardware/test.hex") // -t verify - exitCode, d = executeWithArgs(t, "upload", "-t", "-i", currSketchbookDir.Join("test.hex").String(), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("upload", "-i", filepath.Join(currSketchbookDir, "test.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") + require.Zero(t, exitCode) require.Contains(t, string(d), "QUIET") - require.Contains(t, string(d), "VERIFY") + require.Contains(t, string(d), "NOVERIFY") require.Contains(t, string(d), "testdata/sketchbook_with_custom_hardware/test.hex") // -v -t verbose verify - exitCode, d = executeWithArgs(t, "upload", "-v", "-t", "-i", currSketchbookDir.Join("test.hex").String(), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("upload", "-v", "-t", "-i", filepath.Join(currSketchbookDir, "test.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") + require.Zero(t, exitCode) require.Contains(t, string(d), "VERBOSE") require.Contains(t, string(d), "VERIFY") require.Contains(t, string(d), "testdata/sketchbook_with_custom_hardware/test.hex") // non-existent file - exitCode, _ = executeWithArgs(t, "upload", "-i", currSketchbookDir.Join("test123.hex").String(), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") - require.NotZero(t, exitCode, "exit code") + exitCode, _ = executeWithArgs("upload", "-i", filepath.Join(currSketchbookDir, "test123.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") + require.NotZero(t, exitCode) // sketch - exitCode, d = executeWithArgs(t, "upload", currSketchbookDir.Join("TestSketch").String(), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("upload", filepath.Join(currSketchbookDir, "TestSketch"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") + require.Zero(t, exitCode) require.Contains(t, string(d), "QUIET") require.Contains(t, string(d), "NOVERIFY") require.Contains(t, string(d), "testdata/sketchbook_with_custom_hardware/TestSketch/TestSketch.test.avr.testboard.hex") // sketch without build - exitCode, _ = executeWithArgs(t, "upload", currSketchbookDir.Join("TestSketch2").String(), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") - require.NotZero(t, exitCode, "exit code") + exitCode, _ = executeWithArgs("upload", filepath.Join(currSketchbookDir, "TestSketch2"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0") + require.NotZero(t, exitCode) // platform without 'recipe.output.tmp_file' property - exitCode, _ = executeWithArgs(t, "upload", "-i", currSketchbookDir.Join("test.hex").String(), "-b", "test2:avr:testboard", "-p", "/dev/ttyACM0") - require.NotZero(t, exitCode, "exit code") + exitCode, _ = executeWithArgs("upload", "-i", filepath.Join(currSketchbookDir, "test.hex"), "-b", "test2:avr:testboard", "-p", "/dev/ttyACM0") + require.NotZero(t, exitCode) } -func TestLibSearch(t *testing.T) { - defer makeTempDataDir(t)() - defer makeTempSketchbookDir(t)() - defer useSharedDownloadDir(t)() - - exitCode, output := executeWithArgs(t, "lib", "search", "audiozer", "--format", "json") - require.Zero(t, exitCode, "process exit code") +func TestLibSearchIntegration(t *testing.T) { + exitCode, output := executeWithArgs("lib", "search", "audiozer", "--format", "json") + require.Zero(t, exitCode) var res struct { Libraries []struct { Name string @@ -280,426 +303,377 @@ func TestLibSearch(t *testing.T) { require.Len(t, res.Libraries, 1) require.Equal(t, res.Libraries[0].Name, "AudioZero") - exitCode, output = executeWithArgs(t, "lib", "search", "audiozero", "--names") + exitCode, output = executeWithArgs("lib", "search", "audiozero", "--names") require.Zero(t, exitCode, "process exit code") require.Equal(t, "AudioZero\n", string(output)) - exitCode, output = executeWithArgs(t, "lib", "search", "audiozer", "--names") + exitCode, output = executeWithArgs("lib", "search", "audiozer", "--names") require.Zero(t, exitCode, "process exit code") require.Equal(t, "AudioZero\n", string(output)) - exitCode, output = executeWithArgs(t, "lib", "search", "audiozerooooo", "--names") + exitCode, output = executeWithArgs("lib", "search", "audiozerooooo", "--names") require.Zero(t, exitCode, "process exit code") require.Equal(t, "", string(output)) } -func TestUserLibs(t *testing.T) { - defer makeTempDataDir(t)() - defer makeTempSketchbookDir(t)() - defer useSharedDownloadDir(t)() - libDir := currSketchbookDir.Join("libraries") - err := libDir.MkdirAll() - require.NoError(t, err, "creating 'sketchbook/libraries' dir") +func TestLibUserIntegration(t *testing.T) { + // source of test custom libs + libDir := filepath.Join("testdata", "libs") + // install destination + libInstallDir := filepath.Join(currSketchbookDir, "libraries") + require.NoError(t, os.MkdirAll(libInstallDir, os.FileMode(0755))) + defer os.RemoveAll(libInstallDir) installLib := func(lib string) { - libPath := paths.New("testdata", "libs", lib) - fmt.Printf("COPYING: %s in %s\n", libPath, libDir) - err = libPath.CopyDirTo(libDir.Join(lib)) - require.NoError(t, err, "copying "+lib+" in sketchbook") + cmd := exec.Command("cp", "-r", "-a", filepath.Join(libDir, lib), libInstallDir) + require.NoError(t, cmd.Run(), cmd.Args) } // List libraries (valid libs) installLib("MyLib") - exitCode, d := executeWithArgs(t, "lib", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d := executeWithArgs("lib", "list") + require.Zero(t, exitCode) require.Contains(t, string(d), "MyLib") require.Contains(t, string(d), "1.0.5") // List libraries (pre-1.5 format) installLib("MyLibPre15") - exitCode, d = executeWithArgs(t, "lib", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "list") + require.Zero(t, exitCode) require.Contains(t, string(d), "MyLibPre15") // List libraries (invalid version lib) installLib("MyLibWithWrongVersion") - exitCode, d = executeWithArgs(t, "lib", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "list") + require.Zero(t, exitCode) require.Contains(t, string(d), "MyLibWithWrongVersion") } -func TestSketchCommands(t *testing.T) { - defer makeTempDataDir(t)() - defer makeTempSketchbookDir(t)() - defer useSharedDownloadDir(t)() - - exitCode, _ := executeWithArgs(t, "sketch", "new", "Test") - require.Zero(t, exitCode, "exit code") -} - -func TestLibDownloadAndInstall(t *testing.T) { - defer makeTempDataDir(t)() - defer makeTempSketchbookDir(t)() - defer useSharedDownloadDir(t)() - - exitCode, _ := executeWithArgs(t, "core", "update-index") - require.Zero(t, exitCode, "exit code") +func TestLibDownloadAndInstallIntegration(t *testing.T) { + exitCode, _ := executeWithArgs("core", "update-index") + require.Zero(t, exitCode) // Download inexistent - exitCode, d := executeWithArgs(t, "lib", "download", "inexistentLibrary", "--format", "json") - require.NotZero(t, exitCode, "exit code") + exitCode, d := executeWithArgs("lib", "download", "inexistentLibrary", "--format", "json") + require.NotZero(t, exitCode) require.Contains(t, string(d), "library inexistentLibrary not found") - exitCode, d = executeWithArgs(t, "lib", "download", "inexistentLibrary") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "download", "inexistentLibrary") + require.NotZero(t, exitCode) require.Contains(t, string(d), "library inexistentLibrary not found") // Download latest - exitCode, d = executeWithArgs(t, "lib", "download", "Audio") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "download", "Audio") + require.Zero(t, exitCode) require.Contains(t, string(d), "Audio@") require.Contains(t, string(d), "downloaded") // Download non existent version - exitCode, d = executeWithArgs(t, "lib", "download", "Audio@1.2.3-nonexistent") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "download", "Audio@1.2.3-nonexistent") + require.NotZero(t, exitCode) require.Contains(t, string(d), "not found") // Install latest - exitCode, d = executeWithArgs(t, "lib", "install", "Audio") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "install", "Audio") + require.Zero(t, exitCode) require.Contains(t, string(d), "Audio@") require.Contains(t, string(d), "Installed") - exitCode, d = executeWithArgs(t, "lib", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "list") + require.Zero(t, exitCode) require.Contains(t, string(d), "Audio") // Already installed - exitCode, d = executeWithArgs(t, "lib", "install", "Audio") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "install", "Audio") + require.NotZero(t, exitCode) require.Contains(t, string(d), "Audio@") require.Contains(t, string(d), "already installed") // Install another version - exitCode, d = executeWithArgs(t, "lib", "install", "Audio@1.0.4") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "install", "Audio@1.0.4") + require.Zero(t, exitCode) require.Contains(t, string(d), "Audio@1.0.4") require.Contains(t, string(d), "Installed") - exitCode, d = executeWithArgs(t, "lib", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "list") + require.Zero(t, exitCode) require.Contains(t, string(d), "Audio") require.Contains(t, string(d), "1.0.4") // List updatable - exitCode, d = executeWithArgs(t, "lib", "list", "--updatable") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "list", "--updatable") + require.Zero(t, exitCode) require.Contains(t, string(d), "Audio") require.Contains(t, string(d), "1.0.4") require.Contains(t, string(d), "1.0.5") // Uninstall version not installed - exitCode, d = executeWithArgs(t, "lib", "uninstall", "Audio@1.0.3") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "uninstall", "Audio@1.0.3") + require.NotZero(t, exitCode) require.Contains(t, string(d), "Audio@1.0.3") require.Contains(t, string(d), "not installed") // Upgrade libraries - exitCode, d = executeWithArgs(t, "lib", "upgrade") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "upgrade") + require.Zero(t, exitCode) require.Contains(t, string(d), "Installed") require.Contains(t, string(d), "Audio") require.Contains(t, string(d), "1.0.5") // Uninstall (without version) - exitCode, d = executeWithArgs(t, "lib", "uninstall", "Audio") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "uninstall", "Audio") + require.Zero(t, exitCode) require.Contains(t, string(d), "Uninstalling") require.Contains(t, string(d), "Audio") require.Contains(t, string(d), "1.0.5") - exitCode, d = executeWithArgs(t, "lib", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "list") + require.Zero(t, exitCode) require.NotContains(t, string(d), "Audio") // Uninstall (with version) - exitCode, d = executeWithArgs(t, "lib", "install", "Audio@1.0.4") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "install", "Audio@1.0.4") + require.Zero(t, exitCode) require.Contains(t, string(d), "Audio@1.0.4") require.Contains(t, string(d), "Installed") - exitCode, d = executeWithArgs(t, "lib", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "list") + require.Zero(t, exitCode) require.Contains(t, string(d), "Audio") require.Contains(t, string(d), "1.0.4") - exitCode, d = executeWithArgs(t, "lib", "uninstall", "Audio@1.0.4") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "uninstall", "Audio@1.0.4") + require.Zero(t, exitCode) require.Contains(t, string(d), "Uninstalling") require.Contains(t, string(d), "Audio") require.Contains(t, string(d), "1.0.4") - exitCode, d = executeWithArgs(t, "lib", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("lib", "list") + require.Zero(t, exitCode) require.NotContains(t, string(d), "Audio") } -func updateCoreIndex(t *testing.T) { - // run a "core update-index" to download the package_index.json - exitCode, _ := executeWithArgs(t, "core", "update-index") - require.Equal(t, 0, exitCode, "exit code") -} - -func detectLatestAVRCore(t *testing.T) string { - jsonFile := currDataDir.Join("package_index.json") - type index struct { - Packages []struct { - Name string - Platforms []struct { - Architecture string - Version string - } - } - } - var jsonIndex index - jsonData, err := jsonFile.ReadFile() - require.NoError(t, err, "reading package_index.json") - err = json.Unmarshal(jsonData, &jsonIndex) - require.NoError(t, err, "parsing package_index.json") - latest := semver.MustParse("0.0.1") - for _, p := range jsonIndex.Packages { - if p.Name == "arduino" { - for _, pl := range p.Platforms { - ver, err := semver.Parse(pl.Version) - require.NoError(t, err, "version parsing") - if pl.Architecture == "avr" && ver.GreaterThan(latest) { - latest = ver - } - } - break - } - } - require.NotEmpty(t, latest, "latest avr core version") - fmt.Println("Latest AVR core version:", latest) - return latest.String() +func TestSketchCommandsIntegration(t *testing.T) { + exitCode, _ := executeWithArgs("sketch", "new", "Test") + require.Zero(t, exitCode) } -func TestCompileCommands(t *testing.T) { - defer makeTempDataDir(t)() - defer makeTempSketchbookDir(t)() - defer useSharedDownloadDir(t)() - +func TestCompileCommandsIntegration(t *testing.T) { // Set staging dir to a temporary dir - tmp, err := ioutil.TempDir(os.TempDir(), "test") - require.NoError(t, err, "making temporary staging dir") + tmp := tmpDirOrDie() defer os.RemoveAll(tmp) - updateCoreIndex(t) + // override SetUp dirs + os.Setenv("ARDUINO_SKETCHBOOK_DIR", tmp) + currSketchbookDir = tmp + + exitCode, _ := executeWithArgs("core", "update-index") + require.Zero(t, exitCode) // Download latest AVR - exitCode, _ := executeWithArgs(t, "core", "install", "arduino:avr") - require.Zero(t, exitCode, "exit code") + exitCode, _ = executeWithArgs("core", "install", "arduino:avr") + require.Zero(t, exitCode) // Create a test sketch - exitCode, d := executeWithArgs(t, "sketch", "new", "Test1") - require.Zero(t, exitCode, "exit code") + exitCode, d := executeWithArgs("sketch", "new", "Test1") + require.Zero(t, exitCode) require.Contains(t, string(d), "Sketch created") // Build sketch without FQBN - test1 := currSketchbookDir.Join("Test1").String() - exitCode, d = executeWithArgs(t, "compile", test1) - require.NotZero(t, exitCode, "exit code") + test1 := filepath.Join(currSketchbookDir, "Test1") + exitCode, d = executeWithArgs("compile", test1) + require.NotZero(t, exitCode) require.Contains(t, string(d), "no FQBN provided") // Build sketch for arduino:avr:uno - exitCode, d = executeWithArgs(t, "compile", "-b", "arduino:avr:uno", test1) - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("compile", "-b", "arduino:avr:uno", test1) + require.Zero(t, exitCode) require.Contains(t, string(d), "Sketch uses") require.True(t, paths.New(test1).Join("Test1.arduino.avr.uno.hex").Exist()) // Build sketch for arduino:avr:nano (without options) - exitCode, d = executeWithArgs(t, "compile", "-b", "arduino:avr:nano", test1) - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("compile", "-b", "arduino:avr:nano", test1) + require.Zero(t, exitCode) require.Contains(t, string(d), "Sketch uses") require.True(t, paths.New(test1).Join("Test1.arduino.avr.nano.hex").Exist()) // Build sketch with --output path - { - pwd, err := os.Getwd() - require.NoError(t, err) - defer func() { require.NoError(t, os.Chdir(pwd)) }() - require.NoError(t, os.Chdir(tmp)) - - exitCode, d = executeWithArgs(t, "compile", "-b", "arduino:avr:nano", "-o", "test", test1) - require.Zero(t, exitCode, "exit code") - require.Contains(t, string(d), "Sketch uses") - require.True(t, paths.New("test.hex").Exist()) - - exitCode, d = executeWithArgs(t, "compile", "-b", "arduino:avr:nano", "-o", "test2.hex", test1) - require.Zero(t, exitCode, "exit code") - require.Contains(t, string(d), "Sketch uses") - require.True(t, paths.New("test2.hex").Exist()) - require.NoError(t, paths.New(tmp, "anothertest").MkdirAll()) - - exitCode, d = executeWithArgs(t, "compile", "-b", "arduino:avr:nano", "-o", "anothertest/test", test1) - require.Zero(t, exitCode, "exit code") - require.Contains(t, string(d), "Sketch uses") - require.True(t, paths.New("anothertest", "test.hex").Exist()) - - exitCode, d = executeWithArgs(t, "compile", "-b", "arduino:avr:nano", "-o", tmp+"/anothertest/test2", test1) - require.Zero(t, exitCode, "exit code") - require.Contains(t, string(d), "Sketch uses") - require.True(t, paths.New("anothertest", "test2.hex").Exist()) - } -} + pwd, err := os.Getwd() + require.NoError(t, err) + defer func() { require.NoError(t, os.Chdir(pwd)) }() + require.NoError(t, os.Chdir(tmp)) + + exitCode, d = executeWithArgs("compile", "-b", "arduino:avr:nano", "-o", "test", test1) + require.Zero(t, exitCode) + require.Contains(t, string(d), "Sketch uses") + require.True(t, paths.New("test.hex").Exist()) + + exitCode, d = executeWithArgs("compile", "-b", "arduino:avr:nano", "-o", "test2.hex", test1) + require.Zero(t, exitCode) + require.Contains(t, string(d), "Sketch uses") + require.True(t, paths.New("test2.hex").Exist()) + require.NoError(t, paths.New(tmp, "anothertest").MkdirAll()) + + exitCode, d = executeWithArgs("compile", "-b", "arduino:avr:nano", "-o", "anothertest/test", test1) + require.Zero(t, exitCode) + require.Contains(t, string(d), "Sketch uses") + require.True(t, paths.New("anothertest", "test.hex").Exist()) -func TestInvalidCoreURL(t *testing.T) { - defer makeTempDataDir(t)() - defer makeTempSketchbookDir(t)() - defer useSharedDownloadDir(t)() + exitCode, d = executeWithArgs("compile", "-b", "arduino:avr:nano", "-o", tmp+"/anothertest/test2", test1) + require.Zero(t, exitCode) + require.Contains(t, string(d), "Sketch uses") + require.True(t, paths.New("anothertest", "test2.hex").Exist()) +} - tmp, err := paths.MkTempDir("", "") - require.NoError(t, err, "making temporary dir") - defer tmp.RemoveAll() +func TestInvalidCoreURLIntegration(t *testing.T) { + // override SetUp dirs + tmp := tmpDirOrDie() + defer os.RemoveAll(tmp) + os.Setenv("ARDUINO_SKETCHBOOK_DIR", tmp) + currSketchbookDir = tmp - configFile := tmp.Join("arduino-cli.yaml") - err = configFile.WriteFile([]byte(` + configFile := filepath.Join(currDataDir, "arduino-cli.yaml") + err := ioutil.WriteFile(configFile, []byte(` board_manager: additional_urls: - http://www.invalid-domain-asjkdakdhadjkh.com/package_example_index.json -`)) - require.NoError(t, err, "writing dummy config "+configFile.String()) +`), os.FileMode(0644)) + require.NoError(t, err, "writing dummy config "+configFile) - require.NoError(t, currDataDir.MkdirAll()) - err = currDataDir.Join("package_index.json").WriteFile([]byte(`{ "packages": [] }`)) + err = ioutil.WriteFile(filepath.Join(currDataDir, "package_index.json"), []byte(`{ "packages": [] }`), os.FileMode(0644)) require.NoError(t, err, "Writing empty json index file") - err = currDataDir.Join("package_example_index.json").WriteFile([]byte(`{ "packages": [] }`)) + + err = ioutil.WriteFile(filepath.Join(currDataDir, "package_example_index.json"), []byte(`{ "packages": [] }`), os.FileMode(0644)) require.NoError(t, err, "Writing empty json index file") - err = currDataDir.Join("library_index.json").WriteFile([]byte(`{ "libraries": [] }`)) + + err = ioutil.WriteFile(filepath.Join(currDataDir, "library_index.json"), []byte(`{ "libraries": [] }`), os.FileMode(0644)) require.NoError(t, err, "Writing empty json index file") // Empty cores list - exitCode, _ := executeWithArgs(t, "--config-file", configFile.String(), "core", "list") - require.Zero(t, exitCode, "exit code") + exitCode, _ := executeWithArgs("--config-file", configFile, "core", "list") + require.Zero(t, exitCode) // Dump config with cmd-line specific file - exitCode, d := executeWithArgs(t, "--config-file", configFile.String(), "config", "dump") - require.Zero(t, exitCode, "exit code") + exitCode, d := executeWithArgs("--config-file", configFile, "config", "dump") + require.Zero(t, exitCode) require.Contains(t, string(d), "- http://www.invalid-domain-asjkdakdhadjkh.com/package_example_index.json") // Update inexistent index - exitCode, _ = executeWithArgs(t, "--config-file", configFile.String(), "core", "update-index") - require.NotZero(t, exitCode, "exit code") + exitCode, _ = executeWithArgs("--config-file", configFile, "core", "update-index") + require.NotZero(t, exitCode) // Empty cores list - exitCode, d = executeWithArgs(t, "--config-file", configFile.String(), "core", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("--config-file", configFile, "core", "list") + require.Zero(t, exitCode) require.Empty(t, strings.TrimSpace(string(d))) } -func TestCoreCommands(t *testing.T) { - defer makeTempDataDir(t)() - defer makeTempSketchbookDir(t)() - defer useSharedDownloadDir(t)() +func TestCoreCommandsIntegration(t *testing.T) { + // override SetUp dirs + tmp := tmpDirOrDie() + defer os.RemoveAll(tmp) + os.Setenv("ARDUINO_SKETCHBOOK_DIR", tmp) + currSketchbookDir = tmp + + exitCode, _ := executeWithArgs("core", "update-index") + require.Zero(t, exitCode) - updateCoreIndex(t) AVR := "arduino:avr@" + detectLatestAVRCore(t) // Download a specific core version - exitCode, d := executeWithArgs(t, "core", "download", "arduino:avr@1.6.16") - require.Zero(t, exitCode, "exit code") + exitCode, d := executeWithArgs("core", "download", "arduino:avr@1.6.16") + require.Zero(t, exitCode) require.Regexp(t, "arduino:avr-gcc@4.9.2-atmel3.5.3-arduino2 (already )?downloaded", string(d)) require.Regexp(t, "arduino:avrdude@6.3.0-arduino8 (already )?downloaded", string(d)) require.Regexp(t, "arduino:arduinoOTA@1.0.0 (already )?downloaded", string(d)) require.Regexp(t, "arduino:avr@1.6.16 (already )?downloaded", string(d)) // Download latest - exitCode, d = executeWithArgs(t, "core", "download", "arduino:avr") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "download", "arduino:avr") + require.Zero(t, exitCode) require.Regexp(t, AVR+" (already )?downloaded", string(d)) // Wrong downloads - exitCode, d = executeWithArgs(t, "core", "download", "arduino:samd@1.2.3-notexisting") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "download", "arduino:samd@1.2.3-notexisting") + require.NotZero(t, exitCode) require.Contains(t, string(d), "required version 1.2.3-notexisting not found for platform arduino:samd") - exitCode, d = executeWithArgs(t, "core", "download", "arduino:notexistent") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "download", "arduino:notexistent") + require.NotZero(t, exitCode) require.Contains(t, string(d), "not found") - exitCode, d = executeWithArgs(t, "core", "download", "wrongparameter") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "download", "wrongparameter") + require.NotZero(t, exitCode) require.Contains(t, string(d), "invalid item") // Empty cores list - exitCode, d = executeWithArgs(t, "core", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "list") + require.Zero(t, exitCode) require.Empty(t, strings.TrimSpace(string(d))) // Install avr 1.6.16 - exitCode, d = executeWithArgs(t, "core", "install", "arduino:avr@1.6.16") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "install", "arduino:avr@1.6.16") + require.Zero(t, exitCode) require.Contains(t, string(d), "arduino:avr@1.6.16 installed") - exitCode, d = executeWithArgs(t, "core", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "list") + require.Zero(t, exitCode) require.Contains(t, string(d), "arduino:avr") require.Contains(t, string(d), "1.6.16") - exitCode, d = executeWithArgs(t, "core", "list", "--format", "json") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "list", "--format", "json") + require.Zero(t, exitCode) require.Contains(t, string(d), "arduino:avr") require.Contains(t, string(d), "1.6.16") // Replace avr with 1.6.17 - exitCode, d = executeWithArgs(t, "core", "install", "arduino:avr@1.6.17") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "install", "arduino:avr@1.6.17") + require.Zero(t, exitCode) require.Contains(t, string(d), "Updating arduino:avr@1.6.16 with arduino:avr@1.6.17") require.Contains(t, string(d), "arduino:avr@1.6.17 installed") - exitCode, d = executeWithArgs(t, "core", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "list") + require.Zero(t, exitCode) require.Contains(t, string(d), "arduino:avr") require.Contains(t, string(d), "1.6.17") // List updatable cores - exitCode, d = executeWithArgs(t, "core", "list", "--updatable") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "list", "--updatable") + require.Zero(t, exitCode) require.Contains(t, string(d), "arduino:avr") - exitCode, d = executeWithArgs(t, "core", "list", "--updatable", "--format", "json") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "list", "--updatable", "--format", "json") + require.Zero(t, exitCode) require.Contains(t, string(d), "arduino:avr") // Upgrade platform - exitCode, d = executeWithArgs(t, "core", "upgrade", "arduino:avr@1.6.18") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "upgrade", "arduino:avr@1.6.18") + require.NotZero(t, exitCode) require.Contains(t, string(d), "Invalid item arduino:avr@1.6.18") - exitCode, d = executeWithArgs(t, "core", "upgrade", "other:avr") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "upgrade", "other:avr") + require.NotZero(t, exitCode) require.Contains(t, string(d), "other:avr not found") - exitCode, d = executeWithArgs(t, "core", "upgrade", "arduino:samd") - require.NotZero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "upgrade", "arduino:samd") + require.NotZero(t, exitCode) require.Contains(t, string(d), "arduino:samd is not installed") - exitCode, d = executeWithArgs(t, "core", "upgrade", "arduino:avr") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "upgrade", "arduino:avr") + require.Zero(t, exitCode) require.Contains(t, string(d), "Updating arduino:avr@1.6.17 with "+AVR) // List updatable cores - exitCode, d = executeWithArgs(t, "core", "list", "--updatable") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "list", "--updatable") + require.Zero(t, exitCode) require.NotContains(t, string(d), "arduino:avr") - exitCode, d = executeWithArgs(t, "core", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "list") + require.Zero(t, exitCode) require.Contains(t, string(d), "arduino:avr") // Uninstall arduino:avr - exitCode, d = executeWithArgs(t, "core", "uninstall", "arduino:avr") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "uninstall", "arduino:avr") + require.Zero(t, exitCode) require.Contains(t, string(d), AVR+" uninstalled") // Empty cores list - exitCode, d = executeWithArgs(t, "core", "list") - require.Zero(t, exitCode, "exit code") + exitCode, d = executeWithArgs("core", "list") + require.Zero(t, exitCode) require.Empty(t, strings.TrimSpace(string(d))) } From ca12012312351aa2555a6634aef7076ad2cdcb49 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Thu, 11 Jul 2019 18:24:56 +0200 Subject: [PATCH 7/8] remove emptyness test, it depends on the state of the machine running the tests --- cli/cli_test.go | 20 -------------------- cli/serial/serial.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 cli/serial/serial.go diff --git a/cli/cli_test.go b/cli/cli_test.go index fd638cb719c..50efa732953 100644 --- a/cli/cli_test.go +++ b/cli/cli_test.go @@ -25,7 +25,6 @@ import ( "os" "os/exec" "path/filepath" - "strings" "testing" "bou.ke/monkey" @@ -544,10 +543,6 @@ board_manager: err = ioutil.WriteFile(filepath.Join(currDataDir, "library_index.json"), []byte(`{ "libraries": [] }`), os.FileMode(0644)) require.NoError(t, err, "Writing empty json index file") - // Empty cores list - exitCode, _ := executeWithArgs("--config-file", configFile, "core", "list") - require.Zero(t, exitCode) - // Dump config with cmd-line specific file exitCode, d := executeWithArgs("--config-file", configFile, "config", "dump") require.Zero(t, exitCode) @@ -556,11 +551,6 @@ board_manager: // Update inexistent index exitCode, _ = executeWithArgs("--config-file", configFile, "core", "update-index") require.NotZero(t, exitCode) - - // Empty cores list - exitCode, d = executeWithArgs("--config-file", configFile, "core", "list") - require.Zero(t, exitCode) - require.Empty(t, strings.TrimSpace(string(d))) } func TestCoreCommandsIntegration(t *testing.T) { @@ -601,11 +591,6 @@ func TestCoreCommandsIntegration(t *testing.T) { require.NotZero(t, exitCode) require.Contains(t, string(d), "invalid item") - // Empty cores list - exitCode, d = executeWithArgs("core", "list") - require.Zero(t, exitCode) - require.Empty(t, strings.TrimSpace(string(d))) - // Install avr 1.6.16 exitCode, d = executeWithArgs("core", "install", "arduino:avr@1.6.16") require.Zero(t, exitCode) @@ -671,9 +656,4 @@ func TestCoreCommandsIntegration(t *testing.T) { exitCode, d = executeWithArgs("core", "uninstall", "arduino:avr") require.Zero(t, exitCode) require.Contains(t, string(d), AVR+" uninstalled") - - // Empty cores list - exitCode, d = executeWithArgs("core", "list") - require.Zero(t, exitCode) - require.Empty(t, strings.TrimSpace(string(d))) } diff --git a/cli/serial/serial.go b/cli/serial/serial.go new file mode 100644 index 00000000000..1b491adb1c2 --- /dev/null +++ b/cli/serial/serial.go @@ -0,0 +1,34 @@ +// This file is part of arduino-cli. +// +// Copyright 2019 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 serial + +import ( + "os" + + "github.com/spf13/cobra" +) + +// InitCommand prepares the command. +func InitCommand() *cobra.Command { + serialCommand := &cobra.Command{ + Use: "serial", + Short: "Arduino CLI Serial Commands.", + Long: "Arduino CLI Serial Commands.", + Example: " " + os.Args[0] + " serial monitor /dev/tty0", + } + + return serialCommand +} From 08b6e95b5625771ef1ec826c06e892103a3faf03 Mon Sep 17 00:00:00 2001 From: Massimiliano Pippi Date: Mon, 15 Jul 2019 15:08:05 +0200 Subject: [PATCH 8/8] removed unwanted checked in module --- cli/serial/serial.go | 34 ---------------------------------- go.mod | 9 --------- 2 files changed, 43 deletions(-) delete mode 100644 cli/serial/serial.go diff --git a/cli/serial/serial.go b/cli/serial/serial.go deleted file mode 100644 index 1b491adb1c2..00000000000 --- a/cli/serial/serial.go +++ /dev/null @@ -1,34 +0,0 @@ -// This file is part of arduino-cli. -// -// Copyright 2019 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 serial - -import ( - "os" - - "github.com/spf13/cobra" -) - -// InitCommand prepares the command. -func InitCommand() *cobra.Command { - serialCommand := &cobra.Command{ - Use: "serial", - Short: "Arduino CLI Serial Commands.", - Long: "Arduino CLI Serial Commands.", - Example: " " + os.Args[0] + " serial monitor /dev/tty0", - } - - return serialCommand -} diff --git a/go.mod b/go.mod index 621f01fae52..cbbabed658a 100644 --- a/go.mod +++ b/go.mod @@ -41,19 +41,10 @@ require ( go.bug.st/downloader v1.1.0 go.bug.st/relaxed-semver v0.0.0-20181022103824-0265409c5852 go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45 -<<<<<<< HEAD golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/net v0.0.0-20190311183353-d8887717615a golang.org/x/text v0.3.0 -======= - golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 - golang.org/x/lint v0.0.0-20190409202823-959b441ac422 // indirect - golang.org/x/net v0.0.0-20190628185345-da137c7871d7 - golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 // indirect - golang.org/x/text v0.3.2 - golang.org/x/tools v0.0.0-20190710184609-286818132824 // indirect google.golang.org/appengine v1.4.0 // indirect ->>>>>>> use a better naming for output functions google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d // indirect google.golang.org/grpc v1.21.1 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect