44 "context"
55 "fmt"
66 "os"
7- "path"
7+ "path/filepath "
88 "time"
99
1010 api "github.com/bootdotdev/bootdev/client"
@@ -34,14 +34,13 @@ func Execute(currentVersion string) error {
3434
3535func init () {
3636 cobra .OnInitialize (initConfig )
37- rootCmd .PersistentFlags ().StringVar (& cfgFile , "config" , "" , "config file (default $HOME/.bootdev.yaml)" )
37+ rootCmd .PersistentFlags ().StringVar (& cfgFile , "config" , "" , "config file (default $HOME/.bootdev.yaml or $XDG_CONFIG_HOME/bootdev/config.yaml )" )
3838}
3939
4040func readViperConfig (paths []string ) error {
41- for _ , path := range paths {
42- _ , err := os .Stat (path )
43- if err == nil {
44- viper .SetConfigFile (path )
41+ for _ , p := range paths {
42+ if _ , err := os .Stat (p ); err == nil {
43+ viper .SetConfigFile (p )
4544 break
4645 }
4746 }
@@ -57,24 +56,45 @@ func initConfig() {
5756 viper .SetDefault ("last_refresh" , 0 )
5857 if cfgFile != "" {
5958 // Use config file from the flag.
60- viper .SetConfigFile (cfgFile )
61- err := viper .ReadInConfig ()
62- cobra .CheckErr (err )
59+ viper .SetConfigFile (filepath .Clean (cfgFile ))
60+ cobra .CheckErr (viper .ReadInConfig ())
6361 } else {
64- // Find home directory.
62+ // find home dir
6563 home , err := os .UserHomeDir ()
6664 cobra .CheckErr (err )
6765
68- // viper's built in config path thing sucks, let's do it ourselves
69- defaultPath := path .Join (home , ".bootdev.yaml" )
70- configPaths := []string {}
71- configPaths = append (configPaths , path .Join (home , ".config" , "bootdev" , "config.yaml" ))
72- configPaths = append (configPaths , defaultPath )
66+ // collect paths where existing config files may be located
67+ var configPaths []string
68+
69+ // first check XDG_CONFIG_HOME if set
70+ xdgConfigHome := os .Getenv ("XDG_CONFIG_HOME" )
71+ var xdgEnvPath string
72+ if xdgConfigHome != "" {
73+ xdgEnvPath = filepath .Join (xdgConfigHome , "bootdev" , "config.yaml" )
74+ configPaths = append (configPaths , xdgEnvPath )
75+ }
76+
77+ // then check legacy hard-coded "XDG" path, then home dotfile
78+ xdgLegacyPath := filepath .Join (home , ".config" , "bootdev" , "config.yaml" )
79+ homeDotfilePath := filepath .Join (home , ".bootdev.yaml" )
80+
81+ configPaths = append (configPaths , xdgLegacyPath )
82+ configPaths = append (configPaths , homeDotfilePath )
83+
7384 if err := readViperConfig (configPaths ); err != nil {
74- viper .SafeWriteConfigAs (defaultPath )
75- viper .SetConfigFile (defaultPath )
76- err = viper .ReadInConfig ()
77- cobra .CheckErr (err )
85+ // no existing config found; try to create a new one
86+ // respect XDG_CONFIG_HOME if set, otherwise use dotfile in home dir
87+ var newConfigPath string
88+ if xdgEnvPath != "" {
89+ newConfigPath = xdgEnvPath
90+ cobra .CheckErr (os .MkdirAll (filepath .Dir (newConfigPath ), 0o755 ))
91+ } else {
92+ newConfigPath = homeDotfilePath
93+ }
94+
95+ cobra .CheckErr (viper .SafeWriteConfigAs (newConfigPath ))
96+ viper .SetConfigFile (newConfigPath )
97+ cobra .CheckErr (viper .ReadInConfig ())
7898 }
7999 }
80100
0 commit comments