@@ -34,39 +34,7 @@ const (
34
34
// installation should be attempted and whether or not the remote environment is
35
35
// cmd.exe-based.
36
36
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
- pathSeparator := "/"
54
- if cmdExe {
55
- pathSeparator = "\\ "
56
- }
57
- dataDirectoryName := filesystem .MutagenDataDirectoryName
58
- if mutagen .DevelopmentModeEnabled {
59
- dataDirectoryName = filesystem .MutagenDataDirectoryDevelopmentName
60
- }
61
- agentInvocationPath := strings .Join ([]string {
62
- dataDirectoryName ,
63
- filesystem .MutagenAgentsDirectoryName ,
64
- mutagen .Version ,
65
- BaseName ,
66
- }, pathSeparator )
67
-
68
- // Compute the command to invoke.
69
- 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 ())
70
38
71
39
// Set up (but do not start) an agent process.
72
40
message := "Connecting to agent (POSIX)..."
@@ -176,6 +144,55 @@ func connect(logger *logging.Logger, transport Transport, mode, prompter string,
176
144
return stream , false , false , nil
177
145
}
178
146
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
+ dataDirectoryName := filesystem .MutagenDataDirectoryName
151
+ if mutagen .DevelopmentModeEnabled {
152
+ dataDirectoryName = filesystem .MutagenDataDirectoryDevelopmentName
153
+ }
154
+ return remotePathFromHome (cmdExe ,
155
+ dataDirectoryName ,
156
+ filesystem .MutagenAgentsDirectoryName ,
157
+ mutagen .Version ,
158
+ BaseName ,
159
+ )
160
+ }
161
+
162
+ // remotePathFromHome constructs a path string from the given components as a list of relative path components from
163
+ // the user's home directory. If cmdExe is true, construct a path cmd.exe will understand.
164
+ func remotePathFromHome (cmdExe bool , components ... string ) string {
165
+ // Unless we have reason to assume that this is a cmd.exe environment, we
166
+ // construct a path using forward slashes. This will work for all POSIX
167
+ // systems and POSIX-like environments on Windows. If we know we're hitting
168
+ // a cmd.exe environment, then we use backslashes, otherwise the invocation
169
+ // won't work. Watching for cmd.exe to fail on commands with forward slashes
170
+ // is actually the way that we detect cmd.exe environments.
171
+ //
172
+ // HACK: We're assuming that none of these path components have spaces in
173
+ // them, but since we control all of them, this is probably okay.
174
+ //
175
+ // HACK: When invoking on Windows systems (whether inside a POSIX
176
+ // environment or cmd.exe), we can leave the "exe" suffix off the target
177
+ // name. Fortunately this allows us to also avoid having to try the
178
+ // combination of forward slashes + ".exe" for Windows POSIX environments.
179
+ //
180
+ // HACK: When invoking on cmd.exe, we leave off the ~ prefix, since cmd.exe
181
+ // doesn't recognize it. In most cases the initial working directory for SSH
182
+ // commands is the home directory, but when possible we try to be explicit,
183
+ // to work around systems that use a different directory, such as Coder
184
+ // workspaces, which allow different initial working directories to be
185
+ // configured.
186
+ pathSeparator := "/"
187
+ pathComponents := []string {filesystem .HomeDirectorySpecial }
188
+ if cmdExe {
189
+ pathSeparator = "\\ "
190
+ pathComponents = nil
191
+ }
192
+ pathComponents = append (pathComponents , components ... )
193
+ return strings .Join (pathComponents , pathSeparator )
194
+ }
195
+
179
196
// Dial connects to an agent-based endpoint using the specified transport,
180
197
// connection mode, and prompter.
181
198
func Dial (logger * logging.Logger , transport Transport , mode , prompter string ) (io.ReadWriteCloser , error ) {
@@ -204,7 +221,7 @@ func Dial(logger *logging.Logger, transport Transport, mode, prompter string) (i
204
221
}
205
222
206
223
// Attempt to install.
207
- if err := install (logger , transport , prompter ); err != nil {
224
+ if err := install (logger , transport , prompter , cmdExe ); err != nil {
208
225
return nil , fmt .Errorf ("unable to install agent: %w" , err )
209
226
}
210
227
0 commit comments