Skip to content

Commit 36d4929

Browse files
committed
ssh: add tests for explicit ~
1 parent c8b9b65 commit 36d4929

File tree

4 files changed

+66
-52
lines changed

4 files changed

+66
-52
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# Build output
22
/build/
3+
.idea/

pkg/agent/dial.go

+45-44
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"errors"
66
"fmt"
7+
"github.com/mutagen-io/mutagen/pkg/prompting"
78
"io"
89
"strings"
910
"time"
@@ -14,7 +15,6 @@ import (
1415
"github.com/mutagen-io/mutagen/pkg/logging"
1516
"github.com/mutagen-io/mutagen/pkg/mutagen"
1617
"github.com/mutagen-io/mutagen/pkg/platform/terminal"
17-
"github.com/mutagen-io/mutagen/pkg/prompting"
1818
streampkg "github.com/mutagen-io/mutagen/pkg/stream"
1919
)
2020

@@ -34,49 +34,7 @@ const (
3434
// installation should be attempted and whether or not the remote environment is
3535
// cmd.exe-based.
3636
func connect(logger *logging.Logger, transport Transport, mode, prompter string, cmdExe bool) (io.ReadWriteCloser, bool, bool, error) {
37-
// Compute the agent invocation command, relative to the user's home
38-
// directory on the remote. Unless we have reason to assume that this is a
39-
// cmd.exe environment, we construct a path using forward slashes. This will
40-
// work for all POSIX systems and POSIX-like environments on Windows. If we
41-
// know we're hitting a cmd.exe environment, then we use backslashes,
42-
// otherwise the invocation won't work. Watching for cmd.exe to fail on
43-
// commands with forward slashes is actually the way that we detect cmd.exe
44-
// environments.
45-
//
46-
// HACK: We're assuming that none of these path components have spaces in
47-
// them, but since we control all of them, this is probably okay.
48-
//
49-
// HACK: When invoking on Windows systems (whether inside a POSIX
50-
// environment or cmd.exe), we can leave the "exe" suffix off the target
51-
// name. Fortunately this allows us to also avoid having to try the
52-
// combination of forward slashes + ".exe" for Windows POSIX environments.
53-
//
54-
// HACK: When invoking on cmd.exe, we leave off the ~ prefix, since cmd.exe
55-
// doesn't recognize it. In most cases the initial working directory for SSH
56-
// commands is the home directory, but when possible we try to be explicit,
57-
// to work around systems that use a different directory, such as Coder
58-
// workspaces, which allow different initial working directories to be
59-
// configured.
60-
pathSeparator := "/"
61-
pathComponents := []string{filesystem.HomeDirectorySpecial}
62-
if cmdExe {
63-
pathSeparator = "\\"
64-
pathComponents = nil
65-
}
66-
dataDirectoryName := filesystem.MutagenDataDirectoryName
67-
if mutagen.DevelopmentModeEnabled {
68-
dataDirectoryName = filesystem.MutagenDataDirectoryDevelopmentName
69-
}
70-
pathComponents = append(pathComponents,
71-
dataDirectoryName,
72-
filesystem.MutagenAgentsDirectoryName,
73-
mutagen.Version,
74-
BaseName,
75-
)
76-
agentInvocationPath := strings.Join(pathComponents, pathSeparator)
77-
78-
// Compute the command to invoke.
79-
command := fmt.Sprintf("%s %s --%s=%s", agentInvocationPath, mode, FlagLogLevel, logger.Level())
37+
command := fmt.Sprintf("%s %s --%s=%s", agentInvocationPath(cmdExe), mode, FlagLogLevel, logger.Level())
8038

8139
// Set up (but do not start) an agent process.
8240
message := "Connecting to agent (POSIX)..."
@@ -186,6 +144,49 @@ func connect(logger *logging.Logger, transport Transport, mode, prompter string,
186144
return stream, false, false, nil
187145
}
188146

147+
// agentInvocationPath computes the agent invocation path, relative to the user's home
148+
// directory on the remote.
149+
func agentInvocationPath(cmdExe bool) string {
150+
// Unless we have reason to assume that this is a cmd.exe environment, we
151+
// construct a path using forward slashes. This will work for all POSIX
152+
// systems and POSIX-like environments on Windows. If we know we're hitting
153+
// a cmd.exe environment, then we use backslashes, otherwise the invocation
154+
// won't work. Watching for cmd.exe to fail on commands with forward slashes
155+
// is actually the way that we detect cmd.exe environments.
156+
//
157+
// HACK: We're assuming that none of these path components have spaces in
158+
// them, but since we control all of them, this is probably okay.
159+
//
160+
// HACK: When invoking on Windows systems (whether inside a POSIX
161+
// environment or cmd.exe), we can leave the "exe" suffix off the target
162+
// name. Fortunately this allows us to also avoid having to try the
163+
// combination of forward slashes + ".exe" for Windows POSIX environments.
164+
//
165+
// HACK: When invoking on cmd.exe, we leave off the ~ prefix, since cmd.exe
166+
// doesn't recognize it. In most cases the initial working directory for SSH
167+
// commands is the home directory, but when possible we try to be explicit,
168+
// to work around systems that use a different directory, such as Coder
169+
// workspaces, which allow different initial working directories to be
170+
// configured.
171+
pathSeparator := "/"
172+
pathComponents := []string{filesystem.HomeDirectorySpecial}
173+
if cmdExe {
174+
pathSeparator = "\\"
175+
pathComponents = nil
176+
}
177+
dataDirectoryName := filesystem.MutagenDataDirectoryName
178+
if mutagen.DevelopmentModeEnabled {
179+
dataDirectoryName = filesystem.MutagenDataDirectoryDevelopmentName
180+
}
181+
pathComponents = append(pathComponents,
182+
dataDirectoryName,
183+
filesystem.MutagenAgentsDirectoryName,
184+
mutagen.Version,
185+
BaseName,
186+
)
187+
return strings.Join(pathComponents, pathSeparator)
188+
}
189+
189190
// Dial connects to an agent-based endpoint using the specified transport,
190191
// connection mode, and prompter.
191192
func Dial(logger *logging.Logger, transport Transport, mode, prompter string) (io.ReadWriteCloser, error) {

pkg/agent/dial_test.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
11
package agent
22

3-
// TODO: Implement.
3+
import (
4+
"fmt"
5+
"github.com/mutagen-io/mutagen/pkg/mutagen"
6+
"testing"
7+
)
8+
9+
func TestAgentInvocationPath(t *testing.T) {
10+
path := agentInvocationPath(false)
11+
expected := fmt.Sprintf("~/.mutagen/agents/%s/mutagen-agent", mutagen.Version)
12+
if path != expected {
13+
t.Errorf("Invocation path cmdExe=false, expected %s, got %s", expected, path)
14+
}
15+
16+
path = agentInvocationPath(true)
17+
expected = fmt.Sprintf(".mutagen\\agents\\%s\\mutagen-agent", mutagen.Version)
18+
if path != expected {
19+
t.Errorf("Invocation path cmdExe=true, expected %s, got %s", expected, path)
20+
}
21+
}

pkg/agent/install.go

+1-7
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,7 @@ func install(logger *logging.Logger, transport Transport, prompter string, cmdEx
111111
if err := prompting.Message(prompter, "Installing agent..."); err != nil {
112112
return fmt.Errorf("unable to message prompter: %w", err)
113113
}
114-
var installCommand string
115-
if posix && cmdExe {
116-
// TODO: is this path even possible?
117-
installCommand = fmt.Sprintf("./%s %s", fullRemotePath, CommandInstall)
118-
} else {
119-
installCommand = fmt.Sprintf("%s %s", fullRemotePath, CommandInstall)
120-
}
114+
installCommand := fmt.Sprintf("%s %s", fullRemotePath, CommandInstall)
121115
if err := run(transport, installCommand); err != nil {
122116
return fmt.Errorf("unable to invoke agent installation: %w", err)
123117
}

0 commit comments

Comments
 (0)