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

Commit

Permalink
Add git bash and mingw support (#132)
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
deansheather and Merith-TK committed Apr 27, 2020
1 parent ceab32b commit 50e859c
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ vendor
bin
.vscode
sshcode
sshcode.exe
6 changes: 6 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"math/rand"
"os"
"runtime"
"strings"
"time"

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

// Get linux relative path if on windows.
if runtime.GOOS == "windows" {
dir = gitbashWindowsDir(dir)
}

err := sshCode(host, dir, options{
skipSync: c.skipSync,
sshFlags: c.sshFlags,
Expand Down
4 changes: 4 additions & 0 deletions settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func configDir() (string, error) {
path = os.ExpandEnv("$HOME/.config/Code/User/")
case "darwin":
path = os.ExpandEnv("$HOME/Library/Application Support/Code/User/")
case "windows":
return os.ExpandEnv("/c/Users/$USERNAME/AppData/Roaming/Code/User"), nil
default:
return "", xerrors.Errorf("unsupported platform: %s", runtime.GOOS)
}
Expand All @@ -39,6 +41,8 @@ func extensionsDir() (string, error) {
switch runtime.GOOS {
case "linux", "darwin":
path = os.ExpandEnv("$HOME/.vscode/extensions/")
case "windows":
return os.ExpandEnv("/c/Users/$USERNAME/.vscode/extensions"), nil
default:
return "", xerrors.Errorf("unsupported platform: %s", runtime.GOOS)
}
Expand Down
63 changes: 53 additions & 10 deletions sshcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os/exec"
"os/signal"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
Expand Down Expand Up @@ -106,7 +107,6 @@ func sshCode(host, dir string, o options) error {

// Downloads the latest code-server and allows it to be executed.
sshCmdStr := fmt.Sprintf("ssh %v %v '/usr/bin/env bash -l'", o.sshFlags, host)

sshCmd := exec.Command("sh", "-l", "-c", sshCmdStr)
sshCmd.Stdout = os.Stdout
sshCmd.Stderr = os.Stderr
Expand Down Expand Up @@ -145,10 +145,9 @@ func sshCode(host, dir string, o options) error {
flog.Info("Tunneling remote port %v to %v", o.remotePort, o.bindAddr)

sshCmdStr :=
fmt.Sprintf("ssh -tt -q -L %v:localhost:%v %v %v 'cd %v; %v --host 127.0.0.1 --auth none --port=%v'",
o.bindAddr, o.remotePort, o.sshFlags, host, dir, codeServerPath, o.remotePort,
fmt.Sprintf("ssh -tt -q -L %v:localhost:%v %v %v '%v %v --host 127.0.0.1 --auth none --port=%v'",
o.bindAddr, o.remotePort, o.sshFlags, host, codeServerPath, dir, o.remotePort,
)

// Starts code-server and forwards the remote port.
sshCmd := exec.Command("sh", "-l", "-c", sshCmdStr)
sshCmd.Stdin = os.Stdin
Expand Down Expand Up @@ -266,9 +265,12 @@ func openBrowser(url string) {
const (
macPath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
wslPath = "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"
winPath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"
)

switch {
case commandExists("chrome"):
openCmd = exec.Command("chrome", chromeOptions(url)...)
case commandExists("google-chrome"):
openCmd = exec.Command("google-chrome", chromeOptions(url)...)
case commandExists("google-chrome-stable"):
Expand All @@ -281,6 +283,8 @@ func openBrowser(url string) {
openCmd = exec.Command(macPath, chromeOptions(url)...)
case pathExists(wslPath):
openCmd = exec.Command(wslPath, chromeOptions(url)...)
case pathExists(winPath):
openCmd = exec.Command(winPath, chromeOptions(url)...)
default:
err := browser.OpenURL(url)
if err != nil {
Expand Down Expand Up @@ -335,6 +339,11 @@ func randomPort() (string, error) {
// checkSSHDirectory performs sanity and safety checks on sshDirectory, and
// returns a new value for o.reuseConnection depending on the checks.
func checkSSHDirectory(sshDirectory string, reuseConnection bool) bool {
if runtime.GOOS == "windows" {
flog.Info("OS is windows, disabling connection reuse feature")
return false
}

sshDirectoryMode, err := os.Lstat(expandPath(sshDirectory))
if err != nil {
if reuseConnection {
Expand Down Expand Up @@ -451,8 +460,10 @@ func syncUserSettings(sshFlags string, host string, back bool) error {
return err
}

const remoteSettingsDir = "~/.local/share/code-server/User/"

var remoteSettingsDir = "~/.local/share/code-server/User/"
if runtime.GOOS == "windows" {
remoteSettingsDir = ".local/share/code-server/User/"
}
var (
src = localConfDir + "/"
dest = host + ":" + remoteSettingsDir
Expand All @@ -477,7 +488,10 @@ func syncExtensions(sshFlags string, host string, back bool) error {
return err
}

const remoteExtensionsDir = "~/.local/share/code-server/extensions/"
var remoteExtensionsDir = "~/.local/share/code-server/extensions/"
if runtime.GOOS == "windows" {
remoteExtensionsDir = ".local/share/code-server/extensions/"
}

var (
src = localExtensionsDir + "/"
Expand Down Expand Up @@ -505,6 +519,7 @@ func rsync(src string, dest string, sshFlags string, excludePaths ...string) err
// locally in order to properly delete an extension.
"--delete",
"--copy-unsafe-links",
"-zz",
src, dest,
)...,
)
Expand All @@ -524,7 +539,7 @@ func downloadScript(codeServerPath string) string {
[ "$(uname -m)" != "x86_64" ] && echo "Unsupported server architecture $(uname -m). code-server only has releases for x86_64 systems." && exit 1
pkill -f %v || true
mkdir -p ~/.local/share/code-server %v
mkdir -p $HOME/.local/share/code-server %v
cd %v
curlflags="-o latest-linux"
if [ -f latest-linux ]; then
Expand All @@ -535,8 +550,8 @@ curl $curlflags https://codesrv-ci.cdr.sh/latest-linux
ln latest-linux %v
chmod +x %v`,
codeServerPath,
filepath.Dir(codeServerPath),
filepath.Dir(codeServerPath),
filepath.ToSlash(filepath.Dir(codeServerPath)),
filepath.ToSlash(filepath.Dir(codeServerPath)),
codeServerPath,
codeServerPath,
codeServerPath,
Expand All @@ -548,6 +563,11 @@ chmod +x %v`,
func ensureDir(path string) error {
_, err := os.Stat(path)
if os.IsNotExist(err) {
// This fixes a issue where Go reads `/c/` as `C:\c\` and creates
// empty directories on the client that don't need to exist.
if runtime.GOOS == "windows" && strings.HasPrefix(path, "/c/") {
path = "C:" + path[2:]
}
err = os.MkdirAll(path, 0750)
}

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

return strings.TrimSpace(userIP), sshFlags, nil
}

// gitbashWindowsDir strips a the msys2 install directory from the beginning of
// the path. On msys2, if a user provides `/workspace` sshcode will receive
// `C:/msys64/workspace` which won't work on the remote host.
func gitbashWindowsDir(dir string) string {

// Don't bother figuring out path if it's relative to home dir.
if strings.HasPrefix(dir, "~/") {
if dir == "~" {
return "~/"
}
return dir
}

mingwPrefix, err := exec.Command("sh", "-c", "{ cd / && pwd -W; }").Output()
if err != nil {
// Default to a sane location.
mingwPrefix = []byte("C:/mingw64")
}

prefix := strings.TrimSuffix(string(mingwPrefix), "/\n")
return strings.TrimPrefix(dir, prefix)
}

0 comments on commit 50e859c

Please sign in to comment.