Skip to content
This repository was archived by the owner on Jan 17, 2021. It is now read-only.

Commit 50e859c

Browse files
Add git bash and mingw support (#132)
Supports git bash and mingw on Windows. Does not support cmd.exe. Signed-off-by: Dean Sheather <[email protected]> Co-authored-by: Merith <[email protected]>
1 parent ceab32b commit 50e859c

File tree

4 files changed

+64
-10
lines changed

4 files changed

+64
-10
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ vendor
22
bin
33
.vscode
44
sshcode
5+
sshcode.exe

main.go

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"math/rand"
66
"os"
7+
"runtime"
78
"strings"
89
"time"
910

@@ -80,6 +81,11 @@ func (c *rootCmd) Run(fl *pflag.FlagSet) {
8081
dir = "~"
8182
}
8283

84+
// Get linux relative path if on windows.
85+
if runtime.GOOS == "windows" {
86+
dir = gitbashWindowsDir(dir)
87+
}
88+
8389
err := sshCode(host, dir, options{
8490
skipSync: c.skipSync,
8591
sshFlags: c.sshFlags,

settings.go

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ func configDir() (string, error) {
2424
path = os.ExpandEnv("$HOME/.config/Code/User/")
2525
case "darwin":
2626
path = os.ExpandEnv("$HOME/Library/Application Support/Code/User/")
27+
case "windows":
28+
return os.ExpandEnv("/c/Users/$USERNAME/AppData/Roaming/Code/User"), nil
2729
default:
2830
return "", xerrors.Errorf("unsupported platform: %s", runtime.GOOS)
2931
}
@@ -39,6 +41,8 @@ func extensionsDir() (string, error) {
3941
switch runtime.GOOS {
4042
case "linux", "darwin":
4143
path = os.ExpandEnv("$HOME/.vscode/extensions/")
44+
case "windows":
45+
return os.ExpandEnv("/c/Users/$USERNAME/.vscode/extensions"), nil
4246
default:
4347
return "", xerrors.Errorf("unsupported platform: %s", runtime.GOOS)
4448
}

sshcode.go

+53-10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"os/exec"
1111
"os/signal"
1212
"path/filepath"
13+
"runtime"
1314
"strconv"
1415
"strings"
1516
"syscall"
@@ -106,7 +107,6 @@ func sshCode(host, dir string, o options) error {
106107

107108
// Downloads the latest code-server and allows it to be executed.
108109
sshCmdStr := fmt.Sprintf("ssh %v %v '/usr/bin/env bash -l'", o.sshFlags, host)
109-
110110
sshCmd := exec.Command("sh", "-l", "-c", sshCmdStr)
111111
sshCmd.Stdout = os.Stdout
112112
sshCmd.Stderr = os.Stderr
@@ -145,10 +145,9 @@ func sshCode(host, dir string, o options) error {
145145
flog.Info("Tunneling remote port %v to %v", o.remotePort, o.bindAddr)
146146

147147
sshCmdStr :=
148-
fmt.Sprintf("ssh -tt -q -L %v:localhost:%v %v %v 'cd %v; %v --host 127.0.0.1 --auth none --port=%v'",
149-
o.bindAddr, o.remotePort, o.sshFlags, host, dir, codeServerPath, o.remotePort,
148+
fmt.Sprintf("ssh -tt -q -L %v:localhost:%v %v %v '%v %v --host 127.0.0.1 --auth none --port=%v'",
149+
o.bindAddr, o.remotePort, o.sshFlags, host, codeServerPath, dir, o.remotePort,
150150
)
151-
152151
// Starts code-server and forwards the remote port.
153152
sshCmd := exec.Command("sh", "-l", "-c", sshCmdStr)
154153
sshCmd.Stdin = os.Stdin
@@ -266,9 +265,12 @@ func openBrowser(url string) {
266265
const (
267266
macPath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
268267
wslPath = "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"
268+
winPath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"
269269
)
270270

271271
switch {
272+
case commandExists("chrome"):
273+
openCmd = exec.Command("chrome", chromeOptions(url)...)
272274
case commandExists("google-chrome"):
273275
openCmd = exec.Command("google-chrome", chromeOptions(url)...)
274276
case commandExists("google-chrome-stable"):
@@ -281,6 +283,8 @@ func openBrowser(url string) {
281283
openCmd = exec.Command(macPath, chromeOptions(url)...)
282284
case pathExists(wslPath):
283285
openCmd = exec.Command(wslPath, chromeOptions(url)...)
286+
case pathExists(winPath):
287+
openCmd = exec.Command(winPath, chromeOptions(url)...)
284288
default:
285289
err := browser.OpenURL(url)
286290
if err != nil {
@@ -335,6 +339,11 @@ func randomPort() (string, error) {
335339
// checkSSHDirectory performs sanity and safety checks on sshDirectory, and
336340
// returns a new value for o.reuseConnection depending on the checks.
337341
func checkSSHDirectory(sshDirectory string, reuseConnection bool) bool {
342+
if runtime.GOOS == "windows" {
343+
flog.Info("OS is windows, disabling connection reuse feature")
344+
return false
345+
}
346+
338347
sshDirectoryMode, err := os.Lstat(expandPath(sshDirectory))
339348
if err != nil {
340349
if reuseConnection {
@@ -451,8 +460,10 @@ func syncUserSettings(sshFlags string, host string, back bool) error {
451460
return err
452461
}
453462

454-
const remoteSettingsDir = "~/.local/share/code-server/User/"
455-
463+
var remoteSettingsDir = "~/.local/share/code-server/User/"
464+
if runtime.GOOS == "windows" {
465+
remoteSettingsDir = ".local/share/code-server/User/"
466+
}
456467
var (
457468
src = localConfDir + "/"
458469
dest = host + ":" + remoteSettingsDir
@@ -477,7 +488,10 @@ func syncExtensions(sshFlags string, host string, back bool) error {
477488
return err
478489
}
479490

480-
const remoteExtensionsDir = "~/.local/share/code-server/extensions/"
491+
var remoteExtensionsDir = "~/.local/share/code-server/extensions/"
492+
if runtime.GOOS == "windows" {
493+
remoteExtensionsDir = ".local/share/code-server/extensions/"
494+
}
481495

482496
var (
483497
src = localExtensionsDir + "/"
@@ -505,6 +519,7 @@ func rsync(src string, dest string, sshFlags string, excludePaths ...string) err
505519
// locally in order to properly delete an extension.
506520
"--delete",
507521
"--copy-unsafe-links",
522+
"-zz",
508523
src, dest,
509524
)...,
510525
)
@@ -524,7 +539,7 @@ func downloadScript(codeServerPath string) string {
524539
525540
[ "$(uname -m)" != "x86_64" ] && echo "Unsupported server architecture $(uname -m). code-server only has releases for x86_64 systems." && exit 1
526541
pkill -f %v || true
527-
mkdir -p ~/.local/share/code-server %v
542+
mkdir -p $HOME/.local/share/code-server %v
528543
cd %v
529544
curlflags="-o latest-linux"
530545
if [ -f latest-linux ]; then
@@ -535,8 +550,8 @@ curl $curlflags https://codesrv-ci.cdr.sh/latest-linux
535550
ln latest-linux %v
536551
chmod +x %v`,
537552
codeServerPath,
538-
filepath.Dir(codeServerPath),
539-
filepath.Dir(codeServerPath),
553+
filepath.ToSlash(filepath.Dir(codeServerPath)),
554+
filepath.ToSlash(filepath.Dir(codeServerPath)),
540555
codeServerPath,
541556
codeServerPath,
542557
codeServerPath,
@@ -548,6 +563,11 @@ chmod +x %v`,
548563
func ensureDir(path string) error {
549564
_, err := os.Stat(path)
550565
if os.IsNotExist(err) {
566+
// This fixes a issue where Go reads `/c/` as `C:\c\` and creates
567+
// empty directories on the client that don't need to exist.
568+
if runtime.GOOS == "windows" && strings.HasPrefix(path, "/c/") {
569+
path = "C:" + path[2:]
570+
}
551571
err = os.MkdirAll(path, 0750)
552572
}
553573

@@ -608,3 +628,26 @@ func parseGCPSSHCmd(instance string) (ip, sshFlags string, err error) {
608628

609629
return strings.TrimSpace(userIP), sshFlags, nil
610630
}
631+
632+
// gitbashWindowsDir strips a the msys2 install directory from the beginning of
633+
// the path. On msys2, if a user provides `/workspace` sshcode will receive
634+
// `C:/msys64/workspace` which won't work on the remote host.
635+
func gitbashWindowsDir(dir string) string {
636+
637+
// Don't bother figuring out path if it's relative to home dir.
638+
if strings.HasPrefix(dir, "~/") {
639+
if dir == "~" {
640+
return "~/"
641+
}
642+
return dir
643+
}
644+
645+
mingwPrefix, err := exec.Command("sh", "-c", "{ cd / && pwd -W; }").Output()
646+
if err != nil {
647+
// Default to a sane location.
648+
mingwPrefix = []byte("C:/mingw64")
649+
}
650+
651+
prefix := strings.TrimSuffix(string(mingwPrefix), "/\n")
652+
return strings.TrimPrefix(dir, prefix)
653+
}

0 commit comments

Comments
 (0)