From f469c8528224c548fd54875ec8b538c66a2e08e5 Mon Sep 17 00:00:00 2001 From: Arthur Sengileyev Date: Wed, 19 Mar 2025 21:06:43 +0200 Subject: [PATCH] Make argument quotation compatible with cygwin/msys2/gitbash on Windows Signed-off-by: Arthur Sengileyev --- .github/workflows/main.yml | 5 ++-- pkg/reversesshfs/reversesshfs.go | 16 ++++++++++-- pkg/reversesshfs/reversesshfs_test.go | 35 +++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 pkg/reversesshfs/reversesshfs_test.go diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 50b2a98..32e4c14 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: go-version: [1.23.x, 1.24.x] - platform: [ubuntu-latest, macos-latest] + platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v4 @@ -20,5 +20,6 @@ jobs: with: go-version: ${{ matrix.go-version }} - run: make - - run: sudo make install + - if: "${{ matrix.platform != 'windows-latest' }}" + run: sudo make install - run: go test -covermode=atomic -race -v ./... diff --git a/pkg/reversesshfs/reversesshfs.go b/pkg/reversesshfs/reversesshfs.go index c8f08b8..edec7ea 100644 --- a/pkg/reversesshfs/reversesshfs.go +++ b/pkg/reversesshfs/reversesshfs.go @@ -52,7 +52,7 @@ func (rsf *ReverseSSHFS) Prepare() error { sshArgs = append(sshArgs, "-p", strconv.Itoa(rsf.Port)) } sshArgs = append(sshArgs, rsf.Host, "--") - sshArgs = append(sshArgs, "mkdir", "-p", strconv.Quote(rsf.RemotePath)) + sshArgs = append(sshArgs, "mkdir", "-p", addQuotes(rsf.RemotePath)) sshCmd := exec.Command(sshBinary, sshArgs...) logrus.Debugf("executing ssh for preparing sshfs: %s %v", sshCmd.Path, sshCmd.Args) out, err := sshCmd.CombinedOutput() @@ -141,7 +141,7 @@ func (rsf *ReverseSSHFS) Start() error { sshArgs = append(sshArgs, "-p", strconv.Itoa(rsf.Port)) } sshArgs = append(sshArgs, rsf.Host, "--") - sshArgs = append(sshArgs, "sshfs", strconv.Quote(":"+rsf.LocalPath), strconv.Quote(rsf.RemotePath), "-o", "slave") + sshArgs = append(sshArgs, "sshfs", addQuotes(":"+rsf.LocalPath), addQuotes(rsf.RemotePath), "-o", "slave") if rsf.Readonly { sshArgs = append(sshArgs, "-o", "ro") } @@ -252,6 +252,18 @@ func (rsf *ReverseSSHFS) Start() error { return nil } +func addQuotes(input string) string { + input = strconv.Quote(input) + // exec.Command on Windows would escape wrapping double quotes in a way, which is not compatible + // with passing arguments into bash shell over ssh, replacing with single quotes as a workaround. + if runtime.GOOS == "windows" { + input = strings.TrimPrefix(input, "\"") + input = strings.TrimSuffix(input, "\"") + return fmt.Sprintf(`'%s'`, input) + } + return input +} + func (rsf *ReverseSSHFS) waitForRemoteReady() error { scriptName := "wait-for-remote-ready" scriptTemplate := `#!/bin/sh diff --git a/pkg/reversesshfs/reversesshfs_test.go b/pkg/reversesshfs/reversesshfs_test.go new file mode 100644 index 0000000..28be959 --- /dev/null +++ b/pkg/reversesshfs/reversesshfs_test.go @@ -0,0 +1,35 @@ +package reversesshfs + +import ( + "runtime" + "testing" +) + +func TestAddQuotes(t *testing.T) { + type testCase struct { + input string + expected string + } + var testCases []testCase + if runtime.GOOS != "windows" { + testCases = []testCase{ + { + input: "/user/test/path", + expected: "\"/user/test/path\"", + }, + } + } else { + testCases = []testCase{ + { + input: "/user/test/path", + expected: "'/user/test/path'", + }, + } + } + for i, tc := range testCases { + got := addQuotes(tc.input) + if got != tc.expected { + t.Errorf("#%d: expected %q, got %q", i, tc.expected, got) + } + } +}