Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
wtf/cfg/config_files.go /
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
237 lines (194 sloc)
5.61 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package cfg | |
| import ( | |
| "errors" | |
| "fmt" | |
| "io/ioutil" | |
| "os" | |
| "os/user" | |
| "path/filepath" | |
| "github.com/olebedev/config" | |
| ) | |
| const ( | |
| // XdgConfigDir defines the path to the minimal XDG-compatible configuration directory | |
| XdgConfigDir = "~/.config/" | |
| // WtfConfigDirV1 defines the path to the first version of configuration. Do not use this | |
| WtfConfigDirV1 = "~/.wtf/" | |
| // WtfConfigDirV2 defines the path to the second version of the configuration. Use this. | |
| WtfConfigDirV2 = "~/.config/wtf/" | |
| // WtfConfigFile defines the name of the default config file | |
| WtfConfigFile = "config.yml" | |
| ) | |
| /* -------------------- Exported Functions -------------------- */ | |
| // CreateFile creates the named file in the config directory, if it does not already exist. | |
| // If the file exists it does not recreate it. | |
| // If successful, eturns the absolute path to the file | |
| // If unsuccessful, returns an error | |
| func CreateFile(fileName string) (string, error) { | |
| configDir, err := WtfConfigDir() | |
| if err != nil { | |
| return "", err | |
| } | |
| filePath := fmt.Sprintf("%s/%s", configDir, fileName) | |
| // Check if the file already exists; if it does not, create it | |
| _, err = os.Stat(filePath) | |
| if err != nil { | |
| if os.IsNotExist(err) { | |
| _, err = os.Create(filePath) | |
| if err != nil { | |
| return "", err | |
| } | |
| } else { | |
| return "", err | |
| } | |
| } | |
| return filePath, nil | |
| } | |
| // Initialize takes care of settings up the initial state of WTF configuration | |
| // It ensures necessary directories and files exist | |
| func Initialize(hasCustom bool) { | |
| if hasCustom == false { | |
| migrateOldConfig() | |
| } | |
| // These always get created because this is where modules should write any permanent | |
| // data they need to persist between runs (i.e.: log, textfile, etc.) | |
| createXdgConfigDir() | |
| createWtfConfigDir() | |
| if hasCustom == false { | |
| createWtfConfigFile() | |
| chmodConfigFile() | |
| } | |
| } | |
| // WtfConfigDir returns the absolute path to the configuration directory | |
| func WtfConfigDir() (string, error) { | |
| configDir, err := expandHomeDir(WtfConfigDirV2) | |
| if err != nil { | |
| return "", err | |
| } | |
| return configDir, nil | |
| } | |
| // LoadWtfConfigFile loads the specified config file | |
| func LoadWtfConfigFile(filePath string, isCustomConfig bool) *config.Config { | |
| absPath, _ := expandHomeDir(filePath) | |
| cfg, err := config.ParseYamlFile(absPath) | |
| if err != nil { | |
| if isCustomConfig { | |
| displayWtfCustomConfigFileLoadError(err) | |
| } else { | |
| displayWtfConfigFileLoadError(err) | |
| } | |
| os.Exit(1) | |
| } | |
| return cfg | |
| } | |
| /* -------------------- Unexported Functions -------------------- */ | |
| // chmodConfigFile sets the mode of the config file to r+w for the owner only | |
| func chmodConfigFile() { | |
| relPath := fmt.Sprintf("%s%s", WtfConfigDirV2, WtfConfigFile) | |
| absPath, _ := expandHomeDir(relPath) | |
| _, err := os.Stat(absPath) | |
| if err != nil && os.IsNotExist(err) { | |
| return | |
| } | |
| err = os.Chmod(absPath, 0600) | |
| if err != nil { | |
| return | |
| } | |
| } | |
| // createXdgConfigDir creates the necessary base directory for storing the config file | |
| // If ~/.config is missing, it will try to create it | |
| func createXdgConfigDir() { | |
| xdgConfigDir, _ := expandHomeDir(XdgConfigDir) | |
| if _, err := os.Stat(xdgConfigDir); os.IsNotExist(err) { | |
| err := os.Mkdir(xdgConfigDir, os.ModePerm) | |
| if err != nil { | |
| displayXdgConfigDirCreateError(err) | |
| os.Exit(1) | |
| } | |
| } | |
| } | |
| // createWtfConfigDir creates the necessary directories for storing the default config file | |
| // If ~/.config/wtf is missing, it will try to create it | |
| func createWtfConfigDir() { | |
| wtfConfigDir, _ := WtfConfigDir() | |
| if _, err := os.Stat(wtfConfigDir); os.IsNotExist(err) { | |
| err := os.Mkdir(wtfConfigDir, os.ModePerm) | |
| if err != nil { | |
| displayWtfConfigDirCreateError(err) | |
| os.Exit(1) | |
| } | |
| } | |
| } | |
| // createWtfConfigFile creates a simple config file in the config directory if | |
| // one does not already exist | |
| func createWtfConfigFile() { | |
| filePath, err := CreateFile(WtfConfigFile) | |
| if err != nil { | |
| displayDefaultConfigCreateError(err) | |
| os.Exit(1) | |
| } | |
| // If the file is empty, write to it | |
| file, _ := os.Stat(filePath) | |
| if file.Size() == 0 { | |
| if ioutil.WriteFile(filePath, []byte(defaultConfigFile), 0600) != nil { | |
| displayDefaultConfigWriteError(err) | |
| os.Exit(1) | |
| } | |
| } | |
| } | |
| // Expand expands the path to include the home directory if the path | |
| // is prefixed with `~`. If it isn't prefixed with `~`, the path is | |
| // returned as-is. | |
| func expandHomeDir(path string) (string, error) { | |
| if len(path) == 0 { | |
| return path, nil | |
| } | |
| if path[0] != '~' { | |
| return path, nil | |
| } | |
| if len(path) > 1 && path[1] != '/' && path[1] != '\\' { | |
| return "", errors.New("cannot expand user-specific home dir") | |
| } | |
| dir, err := home() | |
| if err != nil { | |
| return "", err | |
| } | |
| return filepath.Join(dir, path[1:]), nil | |
| } | |
| // Dir returns the home directory for the executing user. | |
| // An error is returned if a home directory cannot be detected. | |
| func home() (string, error) { | |
| currentUser, err := user.Current() | |
| if err != nil { | |
| return "", err | |
| } | |
| if currentUser.HomeDir == "" { | |
| return "", errors.New("cannot find user-specific home dir") | |
| } | |
| return currentUser.HomeDir, nil | |
| } | |
| // migrateOldConfig copies any existing configuration from the old location | |
| // to the new, XDG-compatible location | |
| func migrateOldConfig() { | |
| srcDir, _ := expandHomeDir(WtfConfigDirV1) | |
| destDir, _ := expandHomeDir(WtfConfigDirV2) | |
| // If the old config directory doesn't exist, do not move | |
| if _, err := os.Stat(srcDir); os.IsNotExist(err) { | |
| return | |
| } | |
| // If the new config directory already exists, do not move | |
| if _, err := os.Stat(destDir); err == nil { | |
| return | |
| } | |
| // Time to move | |
| err := Copy(srcDir, destDir) | |
| if err != nil { | |
| panic(err) | |
| } | |
| // Delete the old directory if the new one exists | |
| if _, err := os.Stat(destDir); err == nil { | |
| err := os.RemoveAll(srcDir) | |
| if err != nil { | |
| fmt.Println(err) | |
| } | |
| } | |
| } |