Skip to content

Commit 900654f

Browse files
authored
Add --dest-file flag to config init command (#957)
1 parent a8985da commit 900654f

File tree

6 files changed

+230
-41
lines changed

6 files changed

+230
-41
lines changed

Diff for: cli/config/init.go

+43-12
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,20 @@ package config
1717

1818
import (
1919
"os"
20-
"path/filepath"
2120

2221
"github.com/arduino/arduino-cli/cli/errorcodes"
2322
"github.com/arduino/arduino-cli/cli/feedback"
23+
paths "github.com/arduino/go-paths-helper"
2424
"github.com/sirupsen/logrus"
2525
"github.com/spf13/cobra"
2626
"github.com/spf13/viper"
2727
)
2828

29-
var destDir string
29+
var (
30+
destDir string
31+
destFile string
32+
overwrite bool
33+
)
3034

3135
const defaultFileName = "arduino-cli.yaml"
3236

@@ -37,39 +41,66 @@ func initInitCommand() *cobra.Command {
3741
Long: "Creates or updates the configuration file in the data directory or custom directory with the current configuration settings.",
3842
Example: "" +
3943
" # Writes current configuration to the configuration file in the data directory.\n" +
40-
" " + os.Args[0] + " config init",
44+
" " + os.Args[0] + " config init" +
45+
" " + os.Args[0] + " config init --dest-dir /home/user/MyDirectory" +
46+
" " + os.Args[0] + " config init --dest-file /home/user/MyDirectory/my_settings.yaml",
4147
Args: cobra.NoArgs,
4248
Run: runInitCommand,
4349
}
4450
initCommand.Flags().StringVar(&destDir, "dest-dir", "", "Sets where to save the configuration file.")
51+
initCommand.Flags().StringVar(&destFile, "dest-file", "", "Sets where to save the configuration file.")
52+
initCommand.Flags().BoolVar(&overwrite, "overwrite", false, "Overwrite existing config file.")
4553
return initCommand
4654
}
4755

4856
func runInitCommand(cmd *cobra.Command, args []string) {
49-
if destDir == "" {
57+
if destFile != "" && destDir != "" {
58+
feedback.Errorf("Can't use both --dest-file and --dest-dir flags at the same time.")
59+
os.Exit(errorcodes.ErrGeneric)
60+
}
61+
62+
var configFileAbsPath *paths.Path
63+
var absPath *paths.Path
64+
var err error
65+
66+
switch {
67+
case destFile != "":
68+
configFileAbsPath, err = paths.New(destFile).Abs()
69+
if err != nil {
70+
feedback.Errorf("Cannot find absolute path: %v", err)
71+
os.Exit(errorcodes.ErrGeneric)
72+
}
73+
74+
absPath = configFileAbsPath.Parent()
75+
case destDir == "":
5076
destDir = viper.GetString("directories.Data")
77+
fallthrough
78+
default:
79+
absPath, err = paths.New(destDir).Abs()
80+
if err != nil {
81+
feedback.Errorf("Cannot find absolute path: %v", err)
82+
os.Exit(errorcodes.ErrGeneric)
83+
}
84+
configFileAbsPath = absPath.Join(defaultFileName)
5185
}
5286

53-
absPath, err := filepath.Abs(destDir)
54-
if err != nil {
55-
feedback.Errorf("Cannot find absolute path: %v", err)
87+
if !overwrite && configFileAbsPath.Exist() {
88+
feedback.Error("Config file already exists, use --overwrite to discard the existing one.")
5689
os.Exit(errorcodes.ErrGeneric)
5790
}
58-
configFileAbsPath := filepath.Join(absPath, defaultFileName)
5991

6092
logrus.Infof("Writing config file to: %s", absPath)
61-
62-
if err := os.MkdirAll(absPath, os.FileMode(0755)); err != nil {
93+
if err := absPath.MkdirAll(); err != nil {
6394
feedback.Errorf("Cannot create config file directory: %v", err)
6495
os.Exit(errorcodes.ErrGeneric)
6596
}
6697

67-
if err := viper.WriteConfigAs(configFileAbsPath); err != nil {
98+
if err := viper.WriteConfigAs(configFileAbsPath.String()); err != nil {
6899
feedback.Errorf("Cannot create config file: %v", err)
69100
os.Exit(errorcodes.ErrGeneric)
70101
}
71102

72-
msg := "Config file written to: " + configFileAbsPath
103+
msg := "Config file written to: " + configFileAbsPath.String()
73104
logrus.Info(msg)
74105
feedback.Print(msg)
75106
}

Diff for: commands/daemon/settings_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package daemon
1818
import (
1919
"context"
2020
"encoding/json"
21+
"path/filepath"
2122
"testing"
2223

2324
"github.com/spf13/viper"
@@ -30,12 +31,12 @@ import (
3031
var svc = SettingsService{}
3132

3233
func init() {
33-
configuration.Init("testdata")
34+
configuration.Init(filepath.Join("testdata", "arduino-cli.yaml"))
3435
}
3536

3637
func reset() {
3738
viper.Reset()
38-
configuration.Init("testdata")
39+
configuration.Init(filepath.Join("testdata", "arduino-cli.yaml"))
3940
}
4041

4142
func TestGetAll(t *testing.T) {

Diff for: configuration/configuration.go

+28-23
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,21 @@ import (
3535
func Init(configPath string) {
3636
// Config file metadata
3737
jww.SetStdoutThreshold(jww.LevelFatal)
38-
viper.SetConfigName("arduino-cli")
38+
39+
configDir := paths.New(configPath)
40+
if configDir != nil && !configDir.IsDir() {
41+
viper.SetConfigName(strings.TrimSuffix(configDir.Base(), configDir.Ext()))
42+
} else {
43+
viper.SetConfigName("arduino-cli")
44+
}
3945

4046
// Get default data path if none was provided
4147
if configPath == "" {
4248
configPath = getDefaultArduinoDataDir()
4349
}
4450

4551
// Add paths where to search for a config file
46-
viper.AddConfigPath(configPath)
52+
viper.AddConfigPath(filepath.Dir(configPath))
4753

4854
// Bind env vars
4955
viper.SetEnvPrefix("ARDUINO")
@@ -185,30 +191,39 @@ func IsBundledInDesktopIDE() bool {
185191
}
186192

187193
// FindConfigFile returns the config file path using the argument '--config-file' if specified or via the current working dir
188-
func FindConfigFile() string {
189-
194+
func FindConfigFile(args []string) string {
190195
configFile := ""
191-
for i, arg := range os.Args {
196+
for i, arg := range args {
192197
// 0 --config-file ss
193198
if arg == "--config-file" {
194-
if len(os.Args) > i+1 {
195-
configFile = os.Args[i+1]
199+
if len(args) > i+1 {
200+
configFile = args[i+1]
196201
}
197202
}
198203
}
199204

200205
if configFile != "" {
201-
if fi, err := os.Stat(configFile); err == nil {
202-
if fi.IsDir() {
203-
return configFile
204-
}
205-
return filepath.Dir(configFile)
206-
}
206+
return configFile
207207
}
208208

209209
return searchCwdForConfig()
210210
}
211211

212+
func searchCwdForConfig() string {
213+
cwd, err := os.Getwd()
214+
215+
if err != nil {
216+
return ""
217+
}
218+
219+
configFile := searchConfigTree(cwd)
220+
if configFile == "" {
221+
return configFile
222+
}
223+
224+
return configFile + string(os.PathSeparator) + "arduino-cli.yaml"
225+
}
226+
212227
func searchConfigTree(cwd string) string {
213228

214229
// go back up to root and search for the config file
@@ -230,13 +245,3 @@ func searchConfigTree(cwd string) string {
230245
}
231246

232247
}
233-
234-
func searchCwdForConfig() string {
235-
cwd, err := os.Getwd()
236-
237-
if err != nil {
238-
return ""
239-
}
240-
241-
return searchConfigTree(cwd)
242-
}

Diff for: configuration/configuration_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ func tmpDirOrDie() string {
3030
if err != nil {
3131
panic(fmt.Sprintf("error creating tmp dir: %v", err))
3232
}
33+
// Symlinks are evaluated becase the temp folder on Mac OS is inside /var, it's not writable
34+
// and is a symlink to /private/var, we want the full path so we do this
35+
dir, err = filepath.EvalSymlinks(dir)
36+
if err != nil {
37+
panic(fmt.Sprintf("error evaluating tmp dir symlink: %v", err))
38+
}
3339
return dir
3440
}
3541

@@ -71,3 +77,40 @@ func BenchmarkSearchConfigTree(b *testing.B) {
7177
}
7278
result = s
7379
}
80+
81+
func TestFindConfigFile(t *testing.T) {
82+
configFile := FindConfigFile([]string{"--config-file"})
83+
require.Equal(t, "", configFile)
84+
85+
configFile = FindConfigFile([]string{"--config-file", "some/path/to/config"})
86+
require.Equal(t, "some/path/to/config", configFile)
87+
88+
configFile = FindConfigFile([]string{"--config-file", "some/path/to/config/arduino-cli.yaml"})
89+
require.Equal(t, "some/path/to/config/arduino-cli.yaml", configFile)
90+
91+
configFile = FindConfigFile([]string{})
92+
require.Equal(t, "", configFile)
93+
94+
// Create temporary directories
95+
tmp := tmpDirOrDie()
96+
defer os.RemoveAll(tmp)
97+
target := filepath.Join(tmp, "foo", "bar", "baz")
98+
os.MkdirAll(target, os.ModePerm)
99+
require.Nil(t, os.Chdir(target))
100+
101+
// Create a config file
102+
f, err := os.Create(filepath.Join(target, "..", "..", "arduino-cli.yaml"))
103+
require.Nil(t, err)
104+
f.Close()
105+
106+
configFile = FindConfigFile([]string{})
107+
require.Equal(t, filepath.Join(tmp, "foo", "arduino-cli.yaml"), configFile)
108+
109+
// Create another config file
110+
f, err = os.Create(filepath.Join(target, "arduino-cli.yaml"))
111+
require.Nil(t, err)
112+
f.Close()
113+
114+
configFile = FindConfigFile([]string{})
115+
require.Equal(t, filepath.Join(target, "arduino-cli.yaml"), configFile)
116+
}

Diff for: main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
)
2626

2727
func main() {
28-
configuration.Init(configuration.FindConfigFile())
28+
configuration.Init(configuration.FindConfigFile(os.Args))
2929
i18n.Init()
3030
arduinoCmd := cli.NewCommand()
3131
if err := arduinoCmd.Execute(); err != nil {

0 commit comments

Comments
 (0)