Skip to content

Commit 49025a5

Browse files
committed
win
1 parent 126416f commit 49025a5

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

cli/open.go

+47-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,11 @@ 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+
if !isWindowsAbsPath(d) {
124+
directory = windowsJoinPath(workspaceAgent.ExpandedDirectory, d)
125+
} else {
126+
directory = d
127+
}
124128

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

219223
return cmd
220224
}
225+
226+
// isWindowsAbsPath checks if the path is an absolute path on Windows. On Unix
227+
// systems the check is very simplistic and does not cover edge cases.
228+
//
229+
//nolint:revive // Shadow path variable for readability.
230+
func isWindowsAbsPath(path string) bool {
231+
if runtime.GOOS == "windows" {
232+
return filepath.IsAbs(path)
233+
}
234+
235+
switch {
236+
case len(path) >= 2 && path[1] == ':':
237+
// Path starts with a drive letter.
238+
return len(path) == 2 || (len(path) >= 4 && path[2] == '\\' && path[3] == '\\')
239+
default:
240+
return false
241+
}
242+
}
243+
244+
// windowsJoinPath joins the elements into a path, using Windows path separator
245+
// and converting forward slashes to backslashes. On Unix systems a very
246+
// simplistic join operator is used.
247+
func windowsJoinPath(elem ...string) string {
248+
if runtime.GOOS == "windows" {
249+
return filepath.Join(elem...)
250+
}
251+
252+
var s string
253+
for _, e := range elem {
254+
e = strings.ReplaceAll(e, "/", "\\")
255+
if e == "" {
256+
continue
257+
}
258+
if s == "" {
259+
s = e
260+
continue
261+
}
262+
s += "\\" + strings.TrimSuffix(s, "\\")
263+
}
264+
return s
265+
}

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)