Skip to content

Commit f2df284

Browse files
author
Massimiliano Pippi
authored
Introduce Viper to manage the configuration file (arduino#487)
* dump all settings * init config file using viper * remove configs package * use viper API * default url shouldnt be added to additional_urls * map log settings to config file * do not use logging before it's ready * look for project wide config file
1 parent 2049a7a commit f2df284

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+583
-1144
lines changed

Diff for: arduino/cores/packagemanager/loader.go

+5-10
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,20 @@ import (
2424
"strings"
2525

2626
"github.com/arduino/arduino-cli/arduino/cores"
27-
"github.com/arduino/arduino-cli/configs"
27+
"github.com/arduino/arduino-cli/configuration"
2828
"github.com/arduino/go-paths-helper"
2929
properties "github.com/arduino/go-properties-orderedmap"
3030
semver "go.bug.st/relaxed-semver"
3131
)
3232

3333
// LoadHardware read all plaforms from the configured paths
34-
func (pm *PackageManager) LoadHardware(config *configs.Configuration) error {
35-
dirs, err := config.HardwareDirectories()
36-
if err != nil {
37-
return fmt.Errorf("getting hardware directory: %s", err)
38-
}
34+
func (pm *PackageManager) LoadHardware() error {
35+
dirs := configuration.HardwareDirectories()
3936
if err := pm.LoadHardwareFromDirectories(dirs); err != nil {
4037
return err
4138
}
42-
dirs, err = config.BundleToolsDirectories()
43-
if err != nil {
44-
return fmt.Errorf("getting hardware directory: %s", err)
45-
}
39+
40+
dirs = configuration.BundleToolsDirectories()
4641
return pm.LoadToolsFromBundleDirectories(dirs)
4742
}
4843

Diff for: arduino/cores/packagemanager/package_manager_test.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ package packagemanager_test
2020
import (
2121
"fmt"
2222
"net/url"
23+
"os"
2324
"testing"
2425

2526
"github.com/arduino/arduino-cli/arduino/cores"
2627
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
27-
"github.com/arduino/arduino-cli/configs"
28+
"github.com/arduino/arduino-cli/configuration"
2829
"github.com/arduino/go-paths-helper"
2930
"github.com/arduino/go-properties-orderedmap"
31+
"github.com/spf13/viper"
3032
"github.com/stretchr/testify/require"
3133
semver "go.bug.st/relaxed-semver"
3234
)
@@ -212,14 +214,16 @@ func TestBoardOptionsFunctions(t *testing.T) {
212214
}
213215

214216
func TestFindToolsRequiredForBoard(t *testing.T) {
217+
os.Setenv("ARDUINO_DATA_DIR", dataDir1.String())
218+
configuration.Init("")
219+
fmt.Println(viper.AllSettings())
215220
pm := packagemanager.NewPackageManager(
216221
dataDir1,
217-
dataDir1.Join("packages"),
218-
dataDir1.Join("staging"),
219-
dataDir1)
220-
conf := &configs.Configuration{
221-
DataDir: dataDir1,
222-
}
222+
paths.New(viper.GetString("directories.Packages")),
223+
paths.New(viper.GetString("directories.Downloads")),
224+
dataDir1,
225+
)
226+
223227
loadIndex := func(addr string) {
224228
res, err := url.Parse(addr)
225229
require.NoError(t, err)
@@ -228,7 +232,7 @@ func TestFindToolsRequiredForBoard(t *testing.T) {
228232
loadIndex("https://dl.espressif.com/dl/package_esp32_index.json")
229233
loadIndex("http://arduino.esp8266.com/stable/package_esp8266com_index.json")
230234
loadIndex("https://adafruit.github.io/arduino-board-index/package_adafruit_index.json")
231-
require.NoError(t, pm.LoadHardware(conf))
235+
require.NoError(t, pm.LoadHardware())
232236
esp32, err := pm.FindBoardWithFQBN("esp32:esp32:esp32")
233237
require.NoError(t, err)
234238
esptool231 := pm.FindToolDependency(&cores.ToolDependency{

Diff for: cli/cli.go

+97-37
Original file line numberDiff line numberDiff line change
@@ -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

4650
var (
@@ -54,13 +58,8 @@ var (
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+
118140
func 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

Comments
 (0)