Comply with XDG Base Directory specification

Fixes #868
This commit is contained in:
Dario Giovannetti 2017-01-14 11:47:55 +08:00 committed by Nick Craig-Wood
parent 9fdeb82328
commit 9d36258923
2 changed files with 78 additions and 25 deletions

View File

@ -8,9 +8,9 @@ Configure
--------- ---------
First you'll need to configure rclone. As the object storage systems First you'll need to configure rclone. As the object storage systems
have quite complicated authentication these are kept in a config file have quite complicated authentication these are kept in a config file.
`.rclone.conf` in your home directory by default. (You can use the (See the `--config` entry for how to find the config file and choose
`--config` option to choose a different config file.) its location.)
The easiest way to make the config is to run rclone with the config The easiest way to make the config is to run rclone with the config
option: option:
@ -281,11 +281,18 @@ they are incorrect as it would normally.
### --config=CONFIG_FILE ### ### --config=CONFIG_FILE ###
Specify the location of the rclone config file. Normally this is in Specify the location of the rclone config file.
your home directory as a file called `.rclone.conf`. If you run
`rclone -h` and look at the help for the `--config` option you will Normally the config file is in your home directory as a file called
see where the default location is for you. Use this flag to override `.config/rclone/rclone.conf` (or `.rclone.conf` if created with an
the config location, eg `rclone --config=".myconfig" .config`. older version). If `$XDG_CONFIG_HOME` is set it will be at
`$XDG_CONFIG_HOME/rclone/rclone.conf`
If you run `rclone -h` and look at the help for the `--config` option
you will see where the default location is for you.
Use this flag to override the config location, eg `rclone
--config=".myconfig" .config`.
### --contimeout=TIME ### ### --contimeout=TIME ###

View File

@ -16,7 +16,7 @@ import (
"log" "log"
"os" "os"
"os/user" "os/user"
"path" "path/filepath"
"regexp" "regexp"
"sort" "sort"
"strconv" "strconv"
@ -31,7 +31,8 @@ import (
) )
const ( const (
configFileName = ".rclone.conf" configFileName = "rclone.conf"
hiddenConfigFileName = "." + configFileName
// ConfigToken is the key used to store the token under // ConfigToken is the key used to store the token under
ConfigToken = "token" ConfigToken = "token"
@ -50,10 +51,8 @@ const (
var ( var (
// configData is the config file data structure // configData is the config file data structure
configData *goconfig.ConfigFile configData *goconfig.ConfigFile
// HomeDir is the home directory of the user
HomeDir = configHome()
// ConfigPath points to the config file // ConfigPath points to the config file
ConfigPath = path.Join(HomeDir, configFileName) ConfigPath = makeConfigPath()
// Config is the global config // Config is the global config
Config = &ConfigInfo{} Config = &ConfigInfo{}
// Flags // Flags
@ -215,25 +214,72 @@ type ConfigInfo struct {
Suffix string Suffix string
} }
// Find the config directory // Return the path to the configuration file
func configHome() string { func makeConfigPath() string {
// Find users home directory // Find user's home directory
usr, err := user.Current() usr, err := user.Current()
var homedir string
if err == nil { if err == nil {
return usr.HomeDir homedir = usr.HomeDir
} else {
// Fall back to reading $HOME - work around user.Current() not
// working for cross compiled binaries on OSX.
// https://github.com/golang/go/issues/6376
homedir = os.Getenv("HOME")
} }
// Fall back to reading $HOME - work around user.Current() not
// working for cross compiled binaries on OSX. // Possibly find the user's XDG config paths
// https://github.com/golang/go/issues/6376 // See XDG Base Directory specification
home := os.Getenv("HOME") // https://specifications.freedesktop.org/basedir-spec/latest/
if home != "" { xdgdir := os.Getenv("XDG_CONFIG_HOME")
return home var xdgcfgdir string
if xdgdir != "" {
xdgcfgdir = filepath.Join(xdgdir, "rclone")
} else if homedir != "" {
xdgdir = filepath.Join(homedir, ".config")
xdgcfgdir = filepath.Join(xdgdir, "rclone")
} }
ErrorLog(nil, "Couldn't find home directory or read HOME environment variable.")
// Use $XDG_CONFIG_HOME/rclone/rclone.conf if already existing
var xdgconf string
if xdgcfgdir != "" {
xdgconf = filepath.Join(xdgcfgdir, configFileName)
_, err := os.Stat(xdgconf)
if err == nil {
return xdgconf
}
}
// Use $HOME/.rclone.conf if already existing
var homeconf string
if homedir != "" {
homeconf = filepath.Join(homedir, hiddenConfigFileName)
_, err := os.Stat(homeconf)
if err == nil {
return homeconf
}
}
// Try to create $XDG_CONFIG_HOME/rclone/rclone.conf
if xdgconf != "" {
// xdgconf != "" implies xdgcfgdir != ""
err := os.MkdirAll(xdgcfgdir, os.ModePerm)
if err == nil {
return xdgconf
}
}
// Try to create $HOME/.rclone.conf
if homeconf != "" {
return homeconf
}
// Default to ./.rclone.conf (current working directory)
ErrorLog(nil, "Couldn't find home directory or read HOME or XDG_CONFIG_HOME environment variables.")
ErrorLog(nil, "Defaulting to storing config in current directory.") ErrorLog(nil, "Defaulting to storing config in current directory.")
ErrorLog(nil, "Use -config flag to workaround.") ErrorLog(nil, "Use -config flag to workaround.")
ErrorLog(nil, "Error was: %v", err) ErrorLog(nil, "Error was: %v", err)
return "" return hiddenConfigFileName
} }
// LoadConfig loads the config file // LoadConfig loads the config file