| package homedir |
| |
| import ( |
| "bytes" |
| "errors" |
| "os" |
| "os/exec" |
| "runtime" |
| "strings" |
| ) |
| |
| // 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 runtime.GOOS == "windows" { |
| return dirWindows() |
| } |
| |
| // Unix-like system, so just assume Unix |
| return dirUnix() |
| } |
| |
| // 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 path[0] != '~' { |
| return path, nil |
| } |
| |
| if path[1] != '/' && path[1] != '\\' { |
| return "", errors.New("cannot expand user-specific home dir") |
| } |
| |
| dir, err := Dir() |
| if err != nil { |
| return "", err |
| } |
| |
| return dir + path[1:], nil |
| } |
| |
| func dirUnix() (string, error) { |
| // First prefer the HOME environmental variable |
| if home := os.Getenv("HOME"); home != "" { |
| return home, nil |
| } |
| |
| // If that fails, try the shell |
| var stdout bytes.Buffer |
| cmd := exec.Command("sh", "-c", "eval echo ~$USER") |
| 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) { |
| drive := os.Getenv("HOMEDRIVE") |
| path := os.Getenv("HOMEPATH") |
| home := drive + path |
| if drive == "" || path == "" { |
| home = os.Getenv("USERPROFILE") |
| } |
| if home == "" { |
| return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank") |
| } |
| |
| return home, nil |
| } |