diff --git a/internal/cli/cli.go b/internal/cli/cli.go index 91651b03c23..0bc445b3632 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -181,9 +181,12 @@ func NewCommand(srv rpc.ArduinoCoreServiceServer) *cobra.Command { cmd.PersistentFlags().StringSliceVar(&additionalUrls, "additional-urls", defaultAdditionalURLs, i18n.Tr("Comma-separated list of additional URLs for the Boards Manager.")) cmd.PersistentFlags().BoolVar(&noColor, "no-color", defaultOutputNoColor, "Disable colored output.") - // We are not using cobra to parse this flag, because we manually parse it in main.go. - // Just leaving it here so cobra will not complain about it. - cmd.PersistentFlags().String("config-file", "", i18n.Tr("The custom config file (if not specified the default will be used).")) + // We are not using cobra to parse the following flags, because we manually parse them in main.go. + // Just leaving it here so cobra will output help usage and not complain about them. + cmd.PersistentFlags().String("config-file", "", + i18n.Tr("The custom config file (if not specified the default will be used).")) + cmd.PersistentFlags().String("config-dir", "", + i18n.Tr("Sets the default data directory (Arduino CLI will look for configuration file in this directory).")) return cmd } diff --git a/internal/cli/configuration/configuration.go b/internal/cli/configuration/configuration.go index 8ceef039af6..c567955382a 100644 --- a/internal/cli/configuration/configuration.go +++ b/internal/cli/configuration/configuration.go @@ -16,6 +16,7 @@ package configuration import ( + "fmt" "os" "path/filepath" "runtime" @@ -23,6 +24,7 @@ import ( "github.com/arduino/arduino-cli/internal/cli/feedback" "github.com/arduino/arduino-cli/internal/go-configmap" "github.com/arduino/arduino-cli/internal/i18n" + "github.com/arduino/go-paths-helper" "github.com/arduino/go-win32-utils" ) @@ -42,8 +44,15 @@ func NewSettings() *Settings { return res } +var userProvidedDefaultDataDir *string + // getDefaultArduinoDataDir returns the full path to the default arduino folder func getDefaultArduinoDataDir() string { + // This is overridden by --config-dir flag + if userProvidedDefaultDataDir != nil { + return *userProvidedDefaultDataDir + } + userHomeDir, err := os.UserHomeDir() if err != nil { feedback.Warning(i18n.Tr("Unable to get user home dir: %v", err)) @@ -92,10 +101,25 @@ func getDefaultUserDir() string { } } -// FindConfigFileInArgsFallbackOnEnv returns the config file path using the +// FindConfigFlagsInArgsOrFallbackOnEnv returns the config file path using the // argument '--config-file' (if specified), if empty looks for the ARDUINO_CONFIG_FILE env, // or looking in the current working dir -func FindConfigFileInArgsFallbackOnEnv(args []string) string { +func FindConfigFlagsInArgsOrFallbackOnEnv(args []string) string { + // Look for '--config-dir' argument + for i, arg := range args { + if arg == "--config-dir" { + if len(args) > i+1 { + absArgs, err := paths.New(args[i+1]).Abs() + if err != nil { + feedback.FatalError(fmt.Errorf("invalid --config-dir value: %w", err), feedback.ErrBadArgument) + } + configDir := absArgs.String() + userProvidedDefaultDataDir = &configDir + break + } + } + } + // Look for '--config-file' argument for i, arg := range args { if arg == "--config-file" { diff --git a/internal/cli/configuration/configuration_test.go b/internal/cli/configuration/configuration_test.go index 23af3a964e1..8e448fa15b7 100644 --- a/internal/cli/configuration/configuration_test.go +++ b/internal/cli/configuration/configuration_test.go @@ -19,6 +19,7 @@ import ( "path/filepath" "testing" + "github.com/arduino/go-paths-helper" "github.com/stretchr/testify/require" ) @@ -43,23 +44,31 @@ func TestInit(t *testing.T) { func TestFindConfigFile(t *testing.T) { defaultConfigFile := filepath.Join(getDefaultArduinoDataDir(), "arduino-cli.yaml") - configFile := FindConfigFileInArgsFallbackOnEnv([]string{"--config-file"}) + configFile := FindConfigFlagsInArgsOrFallbackOnEnv([]string{"--config-file"}) require.Equal(t, defaultConfigFile, configFile) - configFile = FindConfigFileInArgsFallbackOnEnv([]string{"--config-file", "some/path/to/config"}) + configFile = FindConfigFlagsInArgsOrFallbackOnEnv([]string{"--config-file", "some/path/to/config"}) require.Equal(t, "some/path/to/config", configFile) - configFile = FindConfigFileInArgsFallbackOnEnv([]string{"--config-file", "some/path/to/config/arduino-cli.yaml"}) + configFile = FindConfigFlagsInArgsOrFallbackOnEnv([]string{"--config-file", "some/path/to/config/arduino-cli.yaml"}) require.Equal(t, "some/path/to/config/arduino-cli.yaml", configFile) - configFile = FindConfigFileInArgsFallbackOnEnv([]string{}) + configFile = FindConfigFlagsInArgsOrFallbackOnEnv([]string{}) require.Equal(t, defaultConfigFile, configFile) t.Setenv("ARDUINO_CONFIG_FILE", "some/path/to/config") - configFile = FindConfigFileInArgsFallbackOnEnv([]string{}) + configFile = FindConfigFlagsInArgsOrFallbackOnEnv([]string{}) require.Equal(t, "some/path/to/config", configFile) // when both env and flag are specified flag takes precedence - configFile = FindConfigFileInArgsFallbackOnEnv([]string{"--config-file", "flag/path"}) + configFile = FindConfigFlagsInArgsOrFallbackOnEnv([]string{"--config-file", "flag/path"}) require.Equal(t, "flag/path", configFile) } + +func TestFindConfigDir(t *testing.T) { + // Check behaviour with --config-dir + expected, err := paths.New("anotherpath", "arduino-cli.yaml").Abs() + require.NoError(t, err) + configFile := FindConfigFlagsInArgsOrFallbackOnEnv([]string{"--config-dir", "anotherpath"}) + require.Equal(t, expected.String(), configFile) +} diff --git a/main.go b/main.go index 3bf2fdd77be..84896ac19fe 100644 --- a/main.go +++ b/main.go @@ -37,13 +37,13 @@ func main() { // Disable logging until it is setup in the arduino-cli pre-run logrus.SetOutput(io.Discard) - // Create a new ArduinoCoreServer - srv := commands.NewArduinoCoreServer() - // Search for the configuration file in the command line arguments and in the environment - configFile := configuration.FindConfigFileInArgsFallbackOnEnv(os.Args) + configFile := configuration.FindConfigFlagsInArgsOrFallbackOnEnv(os.Args) ctx := config.SetConfigFile(context.Background(), configFile) + // Create a new ArduinoCoreServer + srv := commands.NewArduinoCoreServer() + // Read the settings from the configuration file openReq := &rpc.ConfigurationOpenRequest{SettingsFormat: "yaml"} var configFileLoadingWarnings []string