@@ -21,6 +21,8 @@ import (
2121 "fmt"
2222 "io/ioutil"
2323 "os"
24+ "path"
25+ "path/filepath"
2426 "strings"
2527
2628 "github.com/arduino/arduino-cli/cli/board"
@@ -37,10 +39,12 @@ import (
3739 "github.com/arduino/arduino-cli/cli/sketch"
3840 "github.com/arduino/arduino-cli/cli/upload"
3941 "github.com/arduino/arduino-cli/cli/version"
42+ "github.com/arduino/arduino-cli/configuration"
4043 "github.com/mattn/go-colorable"
4144 "github.com/rifflock/lfshook"
4245 "github.com/sirupsen/logrus"
4346 "github.com/spf13/cobra"
47+ "github.com/spf13/viper"
4448)
4549
4650var (
5458 }
5559
5660 verbose bool
57- logFile string
58- logFormat string
5961 outputFormat string
60- )
61-
62- const (
63- defaultLogLevel = "info"
62+ configFile string
6463)
6564
6665// Init the cobra root command
@@ -82,12 +81,16 @@ func createCliCommandTree(cmd *cobra.Command) {
8281 cmd .AddCommand (version .NewCommand ())
8382
8483 cmd .PersistentFlags ().BoolVarP (& verbose , "verbose" , "v" , false , "Print the logs on the standard output." )
85- cmd .PersistentFlags ().StringVar (& globals .LogLevel , "log-level" , defaultLogLevel , "Messages with this level and above will be logged." )
86- cmd .PersistentFlags ().StringVar (& logFile , "log-file" , "" , "Path to the file where logs will be written." )
87- cmd .PersistentFlags ().StringVar (& logFormat , "log-format" , "text" , "The output format for the logs, can be [text|json]." )
84+ cmd .PersistentFlags ().String ("log-level" , "" , "Messages with this level and above will be logged." )
85+ viper .BindPFlag ("logging.level" , cmd .PersistentFlags ().Lookup ("log-level" ))
86+ cmd .PersistentFlags ().String ("log-file" , "" , "Path to the file where logs will be written." )
87+ viper .BindPFlag ("logging.file" , cmd .PersistentFlags ().Lookup ("log-file" ))
88+ cmd .PersistentFlags ().String ("log-format" , "" , "The output format for the logs, can be [text|json]." )
89+ viper .BindPFlag ("logging.format" , cmd .PersistentFlags ().Lookup ("log-format" ))
8890 cmd .PersistentFlags ().StringVar (& outputFormat , "format" , "text" , "The output format, can be [text|json]." )
89- cmd .PersistentFlags ().StringVar (& globals .YAMLConfigFile , "config-file" , "" , "The custom config file (if not specified the default will be used)." )
90- cmd .PersistentFlags ().StringSliceVar (& globals .AdditionalUrls , "additional-urls" , []string {}, "Additional URLs for the board manager." )
91+ cmd .PersistentFlags ().StringVar (& configFile , "config-file" , "" , "The custom config file (if not specified the default will be used)." )
92+ cmd .PersistentFlags ().StringSlice ("additional-urls" , []string {}, "Additional URLs for the board manager." )
93+ viper .BindPFlag ("board_manager.additional_urls" , cmd .PersistentFlags ().Lookup ("additional-urls" ))
9194}
9295
9396// convert the string passed to the `--log-level` option to the corresponding
@@ -115,14 +118,73 @@ func parseFormatString(arg string) (feedback.OutputFormat, bool) {
115118 return f , found
116119}
117120
121+ // This function is here to replicate the old logic looking for a config
122+ // file in the parent tree of the CWD, aka "project config".
123+ // Please
124+ func searchConfigTree (cwd string ) string {
125+ // go back up to root and search for the config file
126+ for {
127+ if _ , err := os .Stat (path .Join (cwd , "arduino-cli.yaml" )); os .IsNotExist (err ) {
128+ // no config file found
129+ next := path .Join (cwd , ".." )
130+ if filepath .Clean (next ) == filepath .Clean (cwd ) {
131+ return ""
132+ }
133+ cwd = next
134+ } else {
135+ return cwd
136+ }
137+ }
138+ }
139+
118140func preRun (cmd * cobra.Command , args []string ) {
119- // normalize the format strings
120- outputFormat = strings .ToLower (outputFormat )
121- // configure the output package
122- output .OutputFormat = outputFormat
123- logFormat = strings .ToLower (logFormat )
141+ //
142+ // Prepare the configuration system
143+ //
144+ configPath := ""
145+
146+ // get cwd, if something is wrong don't do anything and let
147+ // configuration init proceed
148+ if cwd , err := os .Getwd (); err == nil {
149+ configPath = searchConfigTree (cwd )
150+ }
151+
152+ // override the config path if --config-file was passed
153+ if fi , err := os .Stat (configFile ); err == nil {
154+ if fi .IsDir () {
155+ configPath = configFile
156+ } else {
157+ configPath = filepath .Dir (configFile )
158+ }
159+ }
160+
161+ // initialize the config system
162+ configuration .Init (configPath )
163+ configFile := viper .ConfigFileUsed ()
164+
165+ //
166+ // Prepare logging
167+ //
168+
169+ // decide whether we should log to stdout
170+ if verbose {
171+ // if we print on stdout, do it in full colors
172+ logrus .SetOutput (colorable .NewColorableStdout ())
173+ logrus .SetFormatter (& logrus.TextFormatter {
174+ ForceColors : true ,
175+ })
176+ } else {
177+ logrus .SetOutput (ioutil .Discard )
178+ }
179+
180+ // set the Logger format
181+ logFormat := strings .ToLower (viper .GetString ("logging.format" ))
182+ if logFormat == "json" {
183+ logrus .SetFormatter (& logrus.JSONFormatter {})
184+ }
124185
125186 // should we log to file?
187+ logFile := viper .GetString ("logging.file" )
126188 if logFile != "" {
127189 file , err := os .OpenFile (logFile , os .O_CREATE | os .O_WRONLY | os .O_APPEND , 0666 )
128190 if err != nil {
@@ -138,30 +200,22 @@ func preRun(cmd *cobra.Command, args []string) {
138200 }
139201 }
140202
141- // should we log to stdout?
142- if verbose {
143- logrus .SetOutput (colorable .NewColorableStdout ())
144- logrus .SetFormatter (& logrus.TextFormatter {
145- ForceColors : true ,
146- })
147- } else {
148- // Discard logrus output if no writer was set
149- logrus .SetOutput (ioutil .Discard )
150- }
151-
152203 // configure logging filter
153- if lvl , found := toLogLevel (globals . LogLevel ); ! found {
154- fmt . Printf ("Invalid option for --log-level: %s" , globals . LogLevel )
204+ if lvl , found := toLogLevel (viper . GetString ( "logging.level" ) ); ! found {
205+ feedback . Errorf ("Invalid option for --log-level: %s" , viper . GetString ( "logging.level" ) )
155206 os .Exit (errorcodes .ErrBadArgument )
156207 } else {
157208 logrus .SetLevel (lvl )
158209 }
159210
160- // set the Logger format
161- if logFormat == "json" {
162- logrus .SetFormatter (& logrus.JSONFormatter {})
163- }
211+ //
212+ // Prepare the Feedback system
213+ //
164214
215+ // normalize the format strings
216+ outputFormat = strings .ToLower (outputFormat )
217+ // configure the output package
218+ output .OutputFormat = outputFormat
165219 // check the right output format was passed
166220 format , found := parseFormatString (outputFormat )
167221 if ! found {
@@ -172,12 +226,18 @@ func preRun(cmd *cobra.Command, args []string) {
172226 // use the output format to configure the Feedback
173227 feedback .SetFormat (format )
174228
175- globals .InitConfigs ()
229+ //
230+ // Print some status info and check command is consistent
231+ //
232+
233+ if configFile != "" {
234+ logrus .Infof ("Using config file: %s" , configFile )
235+ } else {
236+ logrus .Info ("Config file not found, using default values" )
237+ }
176238
177- logrus .Info (globals .VersionInfo .Application + "-" + globals .VersionInfo .VersionString )
178- logrus .Info ("Starting root command preparation (`arduino`)" )
239+ logrus .Info (globals .VersionInfo .Application + " version " + globals .VersionInfo .VersionString )
179240
180- logrus .Info ("Formatter set" )
181241 if outputFormat != "text" {
182242 cmd .SetHelpFunc (func (cmd * cobra.Command , args []string ) {
183243 logrus .Warn ("Calling help on JSON format" )
0 commit comments