OSDN Git Service

add package
[bytom/vapor.git] / vendor / github.com / mitchellh / go-homedir / homedir.go
diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go
new file mode 100644 (file)
index 0000000..2537853
--- /dev/null
@@ -0,0 +1,167 @@
+package homedir
+
+import (
+       "bytes"
+       "errors"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "strconv"
+       "strings"
+       "sync"
+)
+
+// DisableCache will disable caching of the home directory. Caching is enabled
+// by default.
+var DisableCache bool
+
+var homedirCache string
+var cacheLock sync.RWMutex
+
+// Dir returns the home directory for the executing user.
+//
+// This uses an OS-specific method for discovering the home directory.
+// An error is returned if a home directory cannot be detected.
+func Dir() (string, error) {
+       if !DisableCache {
+               cacheLock.RLock()
+               cached := homedirCache
+               cacheLock.RUnlock()
+               if cached != "" {
+                       return cached, nil
+               }
+       }
+
+       cacheLock.Lock()
+       defer cacheLock.Unlock()
+
+       var result string
+       var err error
+       if runtime.GOOS == "windows" {
+               result, err = dirWindows()
+       } else {
+               // Unix-like system, so just assume Unix
+               result, err = dirUnix()
+       }
+
+       if err != nil {
+               return "", err
+       }
+       homedirCache = result
+       return result, nil
+}
+
+// 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 Expand(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 := Dir()
+       if err != nil {
+               return "", err
+       }
+
+       return filepath.Join(dir, path[1:]), nil
+}
+
+// Reset clears the cache, forcing the next call to Dir to re-detect
+// the home directory. This generally never has to be called, but can be
+// useful in tests if you're modifying the home directory via the HOME
+// env var or something.
+func Reset() {
+       cacheLock.Lock()
+       defer cacheLock.Unlock()
+       homedirCache = ""
+}
+
+func dirUnix() (string, error) {
+       homeEnv := "HOME"
+       if runtime.GOOS == "plan9" {
+               // On plan9, env vars are lowercase.
+               homeEnv = "home"
+       }
+
+       // First prefer the HOME environmental variable
+       if home := os.Getenv(homeEnv); home != "" {
+               return home, nil
+       }
+
+       var stdout bytes.Buffer
+
+       // If that fails, try OS specific commands
+       if runtime.GOOS == "darwin" {
+               cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`)
+               cmd.Stdout = &stdout
+               if err := cmd.Run(); err == nil {
+                       result := strings.TrimSpace(stdout.String())
+                       if result != "" {
+                               return result, nil
+                       }
+               }
+       } else {
+               cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
+               cmd.Stdout = &stdout
+               if err := cmd.Run(); err != nil {
+                       // If the error is ErrNotFound, we ignore it. Otherwise, return it.
+                       if err != exec.ErrNotFound {
+                               return "", err
+                       }
+               } else {
+                       if passwd := strings.TrimSpace(stdout.String()); passwd != "" {
+                               // username:password:uid:gid:gecos:home:shell
+                               passwdParts := strings.SplitN(passwd, ":", 7)
+                               if len(passwdParts) > 5 {
+                                       return passwdParts[5], nil
+                               }
+                       }
+               }
+       }
+
+       // If all else fails, try the shell
+       stdout.Reset()
+       cmd := exec.Command("sh", "-c", "cd && pwd")
+       cmd.Stdout = &stdout
+       if err := cmd.Run(); err != nil {
+               return "", err
+       }
+
+       result := strings.TrimSpace(stdout.String())
+       if result == "" {
+               return "", errors.New("blank output when reading home directory")
+       }
+
+       return result, nil
+}
+
+func dirWindows() (string, error) {
+       // First prefer the HOME environmental variable
+       if home := os.Getenv("HOME"); home != "" {
+               return home, nil
+       }
+
+       // Prefer standard environment variable USERPROFILE
+       if home := os.Getenv("USERPROFILE"); home != "" {
+               return home, nil
+       }
+
+       drive := os.Getenv("HOMEDRIVE")
+       path := os.Getenv("HOMEPATH")
+       home := drive + path
+       if drive == "" || path == "" {
+               return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank")
+       }
+
+       return home, nil
+}