From f91303f50769e1eadb74bd33aeddfacc507e8c4c Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Wed, 13 Apr 2016 18:51:01 -0400 Subject: [PATCH] Lookup actual home directory when expanding ~. This fixes home directory expansion on Windows and OS X. Previously on these platforms, a leading ~ would expand to %LOCALAPPDATA% on Windows or ~/Library/Application Support/ on OS X. While here, add support for ~otheruser expansion to expand to otheruser's home directory. --- config.go | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/config.go b/config.go index 3855bff..5142f01 100644 --- a/config.go +++ b/config.go @@ -8,7 +8,9 @@ import ( "fmt" "net" "os" + "os/user" "path/filepath" + "runtime" "sort" "strings" @@ -99,16 +101,50 @@ type config struct { // cleanAndExpandPath expands environement variables and leading ~ in the // passed path, cleans the result, and returns it. func cleanAndExpandPath(path string) string { - // Expand initial ~ to OS specific home directory. - if strings.HasPrefix(path, "~") { - homeDir := filepath.Dir(defaultAppDataDir) - path = strings.Replace(path, "~", homeDir, 1) - } - // NOTE: The os.ExpandEnv doesn't work with Windows cmd.exe-style // %VARIABLE%, but they variables can still be expanded via POSIX-style // $VARIABLE. - return filepath.Clean(os.ExpandEnv(path)) + path = os.ExpandEnv(path) + + if !strings.HasPrefix(path, "~") { + return filepath.Clean(path) + } + + // Expand initial ~ to the current user's home directory, or ~otheruser + // to otheruser's home directory. On Windows, both forward and backward + // slashes can be used. + path = path[1:] + + var pathSeparators string + if runtime.GOOS == "windows" { + pathSeparators = string(os.PathSeparator) + "/" + } else { + pathSeparators = string(os.PathSeparator) + } + + userName := "" + if i := strings.IndexAny(path, pathSeparators); i != -1 { + userName = path[:i] + path = path[i:] + } + + homeDir := "" + var u *user.User + var err error + if userName == "" { + u, err = user.Current() + } else { + u, err = user.Lookup(userName) + } + if err == nil { + homeDir = u.HomeDir + } + // Fallback to CWD if user lookup fails or user has no home directory. + if homeDir == "" { + homeDir = "." + } + + return filepath.Join(homeDir, path) } // validLogLevel returns whether or not logLevel is a valid debug log level.