|
6 | 6 | "net/url"
|
7 | 7 | "path"
|
8 | 8 | "path/filepath"
|
| 9 | + "runtime" |
9 | 10 | "strings"
|
10 | 11 |
|
11 | 12 | "github.com/skratchdot/open-golang/open"
|
@@ -119,8 +120,14 @@ func (r *RootCmd) openVSCode() *clibase.Cmd {
|
119 | 120 | return xerrors.Errorf("path %q requires expansion and is not supported, use an absolute path instead", d)
|
120 | 121 |
|
121 | 122 | case workspaceAgent.OperatingSystem == "windows":
|
122 |
| - // TODO(mafredri): For now we keep this simple instead of discerning out relative paths on Windows. |
123 |
| - directory = d |
| 123 | + switch { |
| 124 | + case directory != "" && !isWindowsAbsPath(d): |
| 125 | + directory = windowsJoinPath(directory, d) |
| 126 | + case isWindowsAbsPath(d): |
| 127 | + directory = d |
| 128 | + default: |
| 129 | + return xerrors.Errorf("path %q not supported, use an absolute path instead", d) |
| 130 | + } |
124 | 131 |
|
125 | 132 | // Note that we use `path` instead of `filepath` since we want Unix behavior.
|
126 | 133 | case directory != "" && !path.IsAbs(d):
|
@@ -218,3 +225,44 @@ func (r *RootCmd) openVSCode() *clibase.Cmd {
|
218 | 225 |
|
219 | 226 | return cmd
|
220 | 227 | }
|
| 228 | + |
| 229 | +// isWindowsAbsPath checks if the path is an absolute path on Windows. On Unix |
| 230 | +// systems the check is very simplistic and does not cover edge cases. |
| 231 | +// |
| 232 | +//nolint:revive // Shadow path variable for readability. |
| 233 | +func isWindowsAbsPath(path string) bool { |
| 234 | + if runtime.GOOS == "windows" { |
| 235 | + return filepath.IsAbs(path) |
| 236 | + } |
| 237 | + |
| 238 | + switch { |
| 239 | + case len(path) >= 2 && path[1] == ':': |
| 240 | + // Path starts with a drive letter. |
| 241 | + return len(path) == 2 || (len(path) >= 4 && path[2] == '\\' && path[3] == '\\') |
| 242 | + default: |
| 243 | + return false |
| 244 | + } |
| 245 | +} |
| 246 | + |
| 247 | +// windowsJoinPath joins the elements into a path, using Windows path separator |
| 248 | +// and converting forward slashes to backslashes. On Unix systems a very |
| 249 | +// simplistic join operator is used. |
| 250 | +func windowsJoinPath(elem ...string) string { |
| 251 | + if runtime.GOOS == "windows" { |
| 252 | + return filepath.Join(elem...) |
| 253 | + } |
| 254 | + |
| 255 | + var s string |
| 256 | + for _, e := range elem { |
| 257 | + e = strings.ReplaceAll(e, "/", "\\") |
| 258 | + if e == "" { |
| 259 | + continue |
| 260 | + } |
| 261 | + if s == "" { |
| 262 | + s = e |
| 263 | + continue |
| 264 | + } |
| 265 | + s += "\\" + strings.TrimSuffix(s, "\\") |
| 266 | + } |
| 267 | + return s |
| 268 | +} |
0 commit comments