Skip to content

Commit 5d370fc

Browse files
committed
win
1 parent 126416f commit 5d370fc

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

cli/open.go

+50-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net/url"
77
"path"
88
"path/filepath"
9+
"runtime"
910
"strings"
1011

1112
"github.com/skratchdot/open-golang/open"
@@ -119,8 +120,14 @@ func (r *RootCmd) openVSCode() *clibase.Cmd {
119120
return xerrors.Errorf("path %q requires expansion and is not supported, use an absolute path instead", d)
120121

121122
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+
}
124131

125132
// Note that we use `path` instead of `filepath` since we want Unix behavior.
126133
case directory != "" && !path.IsAbs(d):
@@ -218,3 +225,44 @@ func (r *RootCmd) openVSCode() *clibase.Cmd {
218225

219226
return cmd
220227
}
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+
}

cli/open_test.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"net/url"
55
"os"
66
"path/filepath"
7+
"runtime"
78
"testing"
89

910
"github.com/stretchr/testify/assert"
@@ -27,6 +28,7 @@ func TestOpenVSCode(t *testing.T) {
2728
client, workspace, agentToken := setupWorkspaceForAgent(t, func(agents []*proto.Agent) []*proto.Agent {
2829
agents[0].Directory = agentDir
2930
agents[0].Name = agentName
31+
agents[0].OperatingSystem = runtime.GOOS
3032
return agents
3133
})
3234

@@ -161,6 +163,7 @@ func TestOpenVSCode_NoAgentDirectory(t *testing.T) {
161163
agentName := "agent1"
162164
client, workspace, agentToken := setupWorkspaceForAgent(t, func(agents []*proto.Agent) []*proto.Agent {
163165
agents[0].Name = agentName
166+
agents[0].OperatingSystem = runtime.GOOS
164167
return agents
165168
})
166169

@@ -176,6 +179,11 @@ func TestOpenVSCode_NoAgentDirectory(t *testing.T) {
176179
wd, err := os.Getwd()
177180
require.NoError(t, err)
178181

182+
absPath := "/home/coder"
183+
if runtime.GOOS == "windows" {
184+
absPath = "C:\\home\\coder"
185+
}
186+
179187
tests := []struct {
180188
name string
181189
args []string
@@ -196,8 +204,8 @@ func TestOpenVSCode_NoAgentDirectory(t *testing.T) {
196204
},
197205
{
198206
name: "ok with absolute path",
199-
args: []string{"--test.open-error", workspace.Name, "/home/coder"},
200-
wantDir: "/home/coder",
207+
args: []string{"--test.open-error", workspace.Name, absPath},
208+
wantDir: absPath,
201209
},
202210
{
203211
name: "ok with token",

0 commit comments

Comments
 (0)