Skip to content

Commit 97f3cea

Browse files
committed
Build for windows
1 parent 2888401 commit 97f3cea

File tree

8 files changed

+145
-93
lines changed

8 files changed

+145
-93
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ jobs:
4343
- name: test
4444
uses: ./ci/image
4545
with:
46-
args: go test ./...
46+
args: go test ./...

client_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
)
2020

2121
func TestRemoteStdin(t *testing.T) {
22+
t.Parallel()
2223
inputs := []string{
2324
"pwd",
2425
"echo 123\n456",
@@ -72,6 +73,7 @@ func mockConn(ctx context.Context, t *testing.T) (*websocket.Conn, *httptest.Ser
7273
}
7374

7475
func TestRemoteExec(t *testing.T) {
76+
t.Parallel()
7577
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
7678
defer cancel()
7779

@@ -83,6 +85,7 @@ func TestRemoteExec(t *testing.T) {
8385
}
8486

8587
func TestRemoteExecFail(t *testing.T) {
88+
t.Parallel()
8689
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
8790
defer cancel()
8891

@@ -111,6 +114,7 @@ func testExecerFail(ctx context.Context, t *testing.T, execer Execer) {
111114
}
112115

113116
func TestStderrVsStdout(t *testing.T) {
117+
t.Parallel()
114118
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
115119
defer cancel()
116120

dev/client/main.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// +build !windows
2+
13
package main
24

35
import (
@@ -9,10 +11,11 @@ import (
911

1012
"cdr.dev/wsep"
1113
"github.com/spf13/pflag"
12-
"go.coder.com/cli"
13-
"go.coder.com/flog"
1414
"golang.org/x/crypto/ssh/terminal"
1515
"nhooyr.io/websocket"
16+
17+
"go.coder.com/cli"
18+
"go.coder.com/flog"
1619
)
1720

1821
type notty struct {

localexec.go

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,16 @@
11
package wsep
22

33
import (
4-
"bytes"
5-
"context"
64
"io"
7-
"io/ioutil"
8-
"os"
95
"os/exec"
10-
"syscall"
116

12-
"github.com/creack/pty"
137
"golang.org/x/xerrors"
148
)
159

1610
// LocalExecer executes command on the local system.
1711
type LocalExecer struct {
1812
}
1913

20-
type localProcess struct {
21-
// tty may be nil
22-
tty *os.File
23-
cmd *exec.Cmd
24-
25-
stdin io.WriteCloser
26-
stdout io.Reader
27-
stderr io.Reader
28-
}
29-
3014
func (l *localProcess) Stdin() io.WriteCloser {
3115
return l.stdin
3216
}
@@ -53,81 +37,10 @@ func (l *localProcess) Close() error {
5337
return l.cmd.Process.Kill()
5438
}
5539

56-
func (l *localProcess) Resize(ctx context.Context, rows, cols uint16) error {
57-
if l.tty == nil {
58-
return nil
59-
}
60-
return pty.Setsize(l.tty, &pty.Winsize{
61-
Rows: rows,
62-
Cols: cols,
63-
})
64-
}
65-
6640
func (l *localProcess) Pid() int {
6741
return l.cmd.Process.Pid
6842
}
6943

70-
// Start executes the given command locally
71-
func (l LocalExecer) Start(ctx context.Context, c Command) (Process, error) {
72-
var (
73-
process localProcess
74-
err error
75-
)
76-
process.cmd = exec.CommandContext(ctx, c.Command, c.Args...)
77-
process.cmd.Env = append(os.Environ(), c.Env...)
78-
process.cmd.Dir = c.WorkingDir
79-
80-
if c.GID != 0 || c.UID != 0 {
81-
process.cmd.SysProcAttr = &syscall.SysProcAttr{
82-
Credential: &syscall.Credential{},
83-
}
84-
}
85-
if c.GID != 0 {
86-
process.cmd.SysProcAttr.Credential.Gid = c.GID
87-
}
88-
if c.UID != 0 {
89-
process.cmd.SysProcAttr.Credential.Uid = c.UID
90-
}
91-
92-
if c.TTY {
93-
// This special WSEP_TTY variable helps debug unexpected TTYs.
94-
process.cmd.Env = append(process.cmd.Env, "WSEP_TTY=true")
95-
process.tty, err = pty.Start(process.cmd)
96-
if err != nil {
97-
return nil, xerrors.Errorf("start command with pty: %w", err)
98-
}
99-
process.stdout = process.tty
100-
process.stderr = ioutil.NopCloser(bytes.NewReader(nil))
101-
process.stdin = process.tty
102-
} else {
103-
if c.Stdin {
104-
process.stdin, err = process.cmd.StdinPipe()
105-
if err != nil {
106-
return nil, xerrors.Errorf("create pipe: %w", err)
107-
}
108-
} else {
109-
process.stdin = disabledStdinWriter{}
110-
}
111-
112-
process.stdout, err = process.cmd.StdoutPipe()
113-
if err != nil {
114-
return nil, xerrors.Errorf("create pipe: %w", err)
115-
}
116-
117-
process.stderr, err = process.cmd.StderrPipe()
118-
if err != nil {
119-
return nil, xerrors.Errorf("create pipe: %w", err)
120-
}
121-
122-
err = process.cmd.Start()
123-
if err != nil {
124-
return nil, xerrors.Errorf("start command: %w", err)
125-
}
126-
}
127-
128-
return &process, nil
129-
}
130-
13144
type disabledStdinWriter struct{}
13245

13346
func (w disabledStdinWriter) Close() error {

localexec_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
)
1616

1717
func TestLocalExec(t *testing.T) {
18+
t.Parallel()
1819
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
1920
defer cancel()
2021

@@ -58,11 +59,12 @@ func testExecer(ctx context.Context, t *testing.T, execer Execer) {
5859
}
5960

6061
func TestExitCode(t *testing.T) {
62+
t.Parallel()
6163
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
6264
defer cancel()
6365

6466
process, err := LocalExecer{}.Start(ctx, Command{
65-
Command: "/bin/sh",
67+
Command: "sh",
6668
Args: []string{"-c", `"fakecommand"`},
6769
})
6870
assert.Success(t, "start local cmd", err)
@@ -97,6 +99,7 @@ func TestStdin(t *testing.T) {
9799
}
98100

99101
func TestStdinFail(t *testing.T) {
102+
t.Parallel()
100103
ctx, cancel := context.WithCancel(context.Background())
101104
defer cancel()
102105

localexec_unix.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// +build !windows
2+
3+
package wsep
4+
5+
import (
6+
"bytes"
7+
"context"
8+
"io"
9+
"io/ioutil"
10+
"os"
11+
"os/exec"
12+
"syscall"
13+
14+
"github.com/creack/pty"
15+
"golang.org/x/xerrors"
16+
)
17+
18+
type localProcess struct {
19+
// tty may be nil
20+
tty *os.File
21+
cmd *exec.Cmd
22+
23+
stdin io.WriteCloser
24+
stdout io.Reader
25+
stderr io.Reader
26+
}
27+
28+
func (l *localProcess) Resize(_ context.Context, rows, cols uint16) error {
29+
if l.tty == nil {
30+
return nil
31+
}
32+
return pty.Setsize(l.tty, &pty.Winsize{
33+
Rows: rows,
34+
Cols: cols,
35+
})
36+
}
37+
38+
// Start executes the given command locally
39+
func (l LocalExecer) Start(ctx context.Context, c Command) (Process, error) {
40+
var (
41+
process localProcess
42+
err error
43+
)
44+
process.cmd = exec.CommandContext(ctx, c.Command, c.Args...)
45+
process.cmd.Env = append(os.Environ(), c.Env...)
46+
process.cmd.Dir = c.WorkingDir
47+
48+
if c.GID != 0 || c.UID != 0 {
49+
process.cmd.SysProcAttr = &syscall.SysProcAttr{
50+
Credential: &syscall.Credential{},
51+
}
52+
}
53+
if c.GID != 0 {
54+
process.cmd.SysProcAttr.Credential.Gid = c.GID
55+
}
56+
if c.UID != 0 {
57+
process.cmd.SysProcAttr.Credential.Uid = c.UID
58+
}
59+
60+
if c.TTY {
61+
// This special WSEP_TTY variable helps debug unexpected TTYs.
62+
process.cmd.Env = append(process.cmd.Env, "WSEP_TTY=true")
63+
process.tty, err = pty.Start(process.cmd)
64+
if err != nil {
65+
return nil, xerrors.Errorf("start command with pty: %w", err)
66+
}
67+
process.stdout = process.tty
68+
process.stderr = ioutil.NopCloser(bytes.NewReader(nil))
69+
process.stdin = process.tty
70+
} else {
71+
if c.Stdin {
72+
process.stdin, err = process.cmd.StdinPipe()
73+
if err != nil {
74+
return nil, xerrors.Errorf("create pipe: %w", err)
75+
}
76+
} else {
77+
process.stdin = disabledStdinWriter{}
78+
}
79+
80+
process.stdout, err = process.cmd.StdoutPipe()
81+
if err != nil {
82+
return nil, xerrors.Errorf("create pipe: %w", err)
83+
}
84+
85+
process.stderr, err = process.cmd.StderrPipe()
86+
if err != nil {
87+
return nil, xerrors.Errorf("create pipe: %w", err)
88+
}
89+
90+
err = process.cmd.Start()
91+
if err != nil {
92+
return nil, xerrors.Errorf("start command: %w", err)
93+
}
94+
}
95+
96+
return &process, nil
97+
}

localexec_windows.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// +build windows
2+
3+
package wsep
4+
5+
import (
6+
"context"
7+
"io"
8+
"os/exec"
9+
10+
"golang.org/x/xerrors"
11+
)
12+
13+
type localProcess struct {
14+
// tty may be nil
15+
tty uintptr
16+
cmd *exec.Cmd
17+
18+
stdin io.WriteCloser
19+
stdout io.Reader
20+
stderr io.Reader
21+
}
22+
23+
func (l *localProcess) Resize(_ context.Context, rows, cols uint16) error {
24+
return xerrors.Errorf("Windows local execution is not supported")
25+
}
26+
27+
// Start executes the given command locally
28+
func (l LocalExecer) Start(ctx context.Context, c Command) (Process, error) {
29+
return nil, xerrors.Errorf("Windows local execution is not supported")
30+
}

tty_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
)
1414

1515
func TestTTY(t *testing.T) {
16+
t.Parallel()
17+
1618
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
1719
defer cancel()
1820

@@ -26,11 +28,11 @@ func TestTTY(t *testing.T) {
2628

2729
func testTTY(ctx context.Context, t *testing.T, e Execer) {
2830
process, err := e.Start(ctx, Command{
29-
Command: "bash",
31+
Command: "sh",
3032
TTY: true,
3133
Stdin: true,
3234
})
33-
assert.Success(t, "start bash", err)
35+
assert.Success(t, "start sh", err)
3436
var wg sync.WaitGroup
3537
wg.Add(1)
3638
go func() {

0 commit comments

Comments
 (0)