ResolvePath expands a leading "~", "~/", or "~username/" in path to the corresponding home directory, mirroring shell tilde expansion. A path without a leading "~" or whose tilde cannot be resolved is returned unchanged so callers can pass any user-supplied path through this helper without worrying
(path string)
| 113 | // other platforms because they are legal characters in usernames and |
| 114 | // path segments there. |
| 115 | func ResolvePath(path string) string { |
| 116 | |
| 117 | if !strings.HasPrefix(path, "~") { |
| 118 | return path |
| 119 | } |
| 120 | |
| 121 | if path == "~" { |
| 122 | if usr, err := user.Current(); err == nil { |
| 123 | return usr.HomeDir |
| 124 | } |
| 125 | return path |
| 126 | } |
| 127 | |
| 128 | isSep := func(b byte) bool { |
| 129 | return b == '/' || b == byte(filepath.Separator) |
| 130 | } |
| 131 | |
| 132 | if isSep(path[1]) { |
| 133 | if usr, err := user.Current(); err == nil { |
| 134 | return filepath.Join(usr.HomeDir, path[2:]) |
| 135 | } |
| 136 | return path |
| 137 | } |
| 138 | |
| 139 | // "~username" or "~username<sep>rest" |
| 140 | name := path[1:] |
| 141 | rest := "" |
| 142 | for i := 0; i < len(name); i++ { |
| 143 | if isSep(name[i]) { |
| 144 | rest = name[i+1:] |
| 145 | name = name[:i] |
| 146 | break |
| 147 | } |
| 148 | } |
| 149 | usr, err := user.Lookup(name) |
| 150 | if err != nil { |
| 151 | return path |
| 152 | } |
| 153 | if rest == "" { |
| 154 | return usr.HomeDir |
| 155 | } |
| 156 | return filepath.Join(usr.HomeDir, rest) |
| 157 | } |
| 158 | |
| 159 | // ResolveCommaSeparatedPaths splits paths on "," and runs each entry through |
| 160 | // ResolvePath, then rejoins them. This lets flags like `weed mini -dir` or |