Skip to content

Commit caee378

Browse files
committed
fixup test on Windows
1 parent 970b115 commit caee378

File tree

2 files changed

+29
-27
lines changed

2 files changed

+29
-27
lines changed

cli/configssh_internal_test.go

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -193,16 +193,17 @@ func Test_sshConfigMatchExecEscape(t *testing.T) {
193193
t.Parallel()
194194

195195
tests := []struct {
196-
name string
197-
path string
198-
wantErr bool
196+
name string
197+
path string
198+
wantErrOther bool
199+
wantErrWindows bool
199200
}{
200-
{"no spaces", "simple", false},
201-
{"spaces", "path with spaces", false},
202-
{"quotes fails", "path with \"quotes\"", true},
203-
{"backslashes", "path with \\backslashes", false},
204-
{"tabs", "path with \ttabs", false},
205-
{"newline fails", "path with \nnewline", true},
201+
{"no spaces", "simple", false, false},
202+
{"spaces", "path with spaces", false, false},
203+
{"quotes", "path with \"quotes\"", false, true},
204+
{"backslashes", "path with\\backslashes", false, false},
205+
{"tabs", "path with \ttabs", false, true},
206+
{"newline fails", "path with \nnewline", true, true},
206207
}
207208
// nolint:paralleltest // Fixes a flake
208209
for _, tt := range tests {
@@ -214,24 +215,26 @@ func Test_sshConfigMatchExecEscape(t *testing.T) {
214215
if runtime.GOOS == "windows" {
215216
cmd = "cmd.exe"
216217
arg = "/c"
217-
contents = []byte("echo yay\n")
218+
contents = []byte("@echo yay\n")
218219
}
219220

220221
dir := filepath.Join(t.TempDir(), tt.path)
221-
err := os.MkdirAll(dir, 0o755)
222-
require.NoError(t, err)
223222
bin := filepath.Join(dir, "coder.bat") // Windows will treat it as batch, Linux doesn't care
224-
225-
err = os.WriteFile(bin, contents, 0o755) //nolint:gosec
226-
require.NoError(t, err)
227-
228223
escaped, err := sshConfigMatchExecEscape(bin)
229-
if tt.wantErr {
224+
if (runtime.GOOS == "windows" && tt.wantErrWindows) || (runtime.GOOS != "windows" && tt.wantErrOther) {
230225
require.Error(t, err)
231226
return
232227
}
233228
require.NoError(t, err)
234229

230+
err = os.MkdirAll(dir, 0o755)
231+
require.NoError(t, err)
232+
233+
err = os.WriteFile(bin, contents, 0o755) //nolint:gosec
234+
require.NoError(t, err)
235+
236+
// OpenSSH processes %% escape sequences into %
237+
escaped = strings.ReplaceAll(escaped, "%%", "%")
235238
b, err := exec.Command(cmd, arg, escaped).CombinedOutput() //nolint:gosec
236239
require.NoError(t, err)
237240
got := strings.TrimSpace(string(b))

cli/configssh_windows.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,24 @@ var hideForceUnixSlashes = false
3434
//
3535
// Other notes:
3636
// - @ in `@cmd.exe` suppresses echoing it, so you don't get this command printed
37-
// - without another invocation of cmd.exe (e.g. `do @cmd.exe /c %%aC:\Program Files\Coder\bin\coder.exe%%a`) then
38-
// the double-quote gets interpreted as part of the path and you get: '"C:\Program' is not recognized. Constructing
39-
// the string and then passing it to another instance of cmd.exe does this trick here.
37+
// - we need another invocation of cmd.exe (e.g. `do @cmd.exe /c %%aC:\Program Files\Coder\bin\coder.exe%%a`). Without
38+
// it the double-quote gets interpreted as part of the path, and you get: '"C:\Program' is not recognized.
39+
// Constructing the string and then passing it to another instance of cmd.exe does this trick here.
4040
// - OpenSSH passes the `Match exec` command to cmd.exe regardless of whether the user has a unix-like shell like
4141
// git bash, so we don't have a `forceUnixPath` option like for the ProxyCommand which does respect the user's
42-
// configured shell.
42+
// configured shell on Windows.
4343
func sshConfigMatchExecEscape(path string) (string, error) {
4444
// This is unlikely to ever happen, but newlines are allowed on
4545
// certain filesystems, but cannot be used inside ssh config.
4646
if strings.ContainsAny(path, "\n") {
4747
return "", xerrors.Errorf("invalid path: %s", path)
4848
}
49-
// Windows does not allow double-quotes in paths. If we get one it is an error.
50-
if strings.Contains(path, `"`) {
51-
return "", xerrors.Errorf("path must not contain quotes: %q", path)
49+
// Windows does not allow double-quotes or tabs in paths. If we get one it is an error.
50+
if strings.ContainsAny(path, "\"\t") {
51+
return "", xerrors.Errorf("path must not contain quotes or tabs: %q", path)
5252
}
53-
// A space or a tab requires quoting, but tabs must not be escaped
54-
// (\t) since OpenSSH interprets it as a literal \t, not a tab.
55-
if strings.ContainsAny(path, " \t") {
53+
54+
if strings.ContainsAny(path, " ") {
5655
// c.f. function comment for how this works.
5756
path = fmt.Sprintf("for /f %%%%a in ('powershell.exe -Command [char]34') do @cmd.exe /c %%%%a%s%%%%a", path) //nolint:gocritic // We don't want %q here.
5857
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy