FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

package main import ( "context" "fmt" "math/rand" "net" "net/http" "os" "os/exec" "os/signal" "path/filepath" "runtime" "strconv" "strings" "syscall" "time" "github.com/pkg/browser" "go.coder.com/flog" "golang.org/x/xerrors" ) const codeServerPath = "~/.cache/sshcode/sshcode-server" const ( sshDirectory = "~/.ssh" sshDirectoryUnsafeModeMask = 0022 sshControlPath = sshDirectory + "/control-%h-%p-%r" ) type options struct { skipSync bool syncBack bool noOpen bool reuseConnection bool bindAddr string remotePort string sshFlags string uploadCodeServer string } func sshCode(host, dir string, o options) error { host, extraSSHFlags, err := parseHost(host) if err != nil { return xerrors.Errorf("failed to parse host IP: %w", err) } if extraSSHFlags != "" { o.sshFlags = strings.Join([]string{extraSSHFlags, o.sshFlags}, " ") } o.bindAddr, err = parseBindAddr(o.bindAddr) if err != nil { return xerrors.Errorf("failed to parse bind address: %w", err) } if o.remotePort == "" { o.remotePort, err = randomPort() } if err != nil { return xerrors.Errorf("failed to find available remote port: %w", err) } // Check the SSH directory's permissions and warn the user if it is not safe. o.reuseConnection = checkSSHDirectory(sshDirectory, o.reuseConnection) // Start SSH master connection socket. This prevents multiple password prompts from appearing as authentication // only happens on the initial connection. if o.reuseConnection { flog.Info("starting SSH master connection...") newSSHFlags, cancel, err := startSSHMaster(o.sshFlags, sshControlPath, host) defer cancel() if err != nil { flog.Error("failed to start SSH master connection: %v", err) o.reuseConnection = false } else { o.sshFlags = newSSHFlags } } // Upload local code-server or download code-server from CI server. if o.uploadCodeServer != "" { flog.Info("uploading local code-server binary...") err = copyCodeServerBinary(o.sshFlags, host, o.uploadCodeServer, codeServerPath) if err != nil { return xerrors.Errorf("failed to upload local code-server binary to remote server: %w", err) } sshCmdStr := fmt.Sprintf("ssh %v %v 'chmod +x %v'", o.sshFlags, host, codeServerPath, ) sshCmd := exec.Command("sh", "-l", "-c", sshCmdStr) sshCmd.Stdout = os.Stdout sshCmd.Stderr = os.Stderr err = sshCmd.Run() if err != nil { return xerrors.Errorf("failed to make code-server binary executable:\n---ssh cmd---\n%s: %w", sshCmdStr, err, ) } } else { flog.Info("ensuring code-server is updated...") dlScript := downloadScript(codeServerPath) // 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 sshCmd.Stdin = strings.NewReader(dlScript) err = sshCmd.Run() if err != nil { return xerrors.Errorf("failed to update code-server:\n---ssh cmd---\n%s"+ "\n---download script---\n%s: %w", sshCmdStr, dlScript, err, ) } } if !o.skipSync { start := time.Now() flog.Info("syncing settings") err = syncUserSettings(o.sshFlags, host, false) if err != nil { return xerrors.Errorf("failed to sync settings: %w", err) } flog.Info("synced settings in %s", time.Since(start)) flog.Info("syncing extensions") err = syncExtensions(o.sshFlags, host, false) if err != nil { return xerrors.Errorf("failed to sync extensions: %w", err) } flog.Info("synced extensions in %s", time.Since(start)) } flog.Info("starting code-server...") flog.Info("Tunneling remote port %v to %v", o.remotePort, o.bindAddr) sshCmdStr := 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 sshCmd.Stdout = os.Stdout sshCmd.Stderr = os.Stderr err = sshCmd.Start() if err != nil { return xerrors.Errorf("failed to start code-server: %w", err) } url := fmt.Sprintf("http://%s", o.bindAddr) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() client := http.Client{ Timeout: time.Second * 3, } for { if ctx.Err() != nil { return xerrors.Errorf("code-server didn't start in time: %w", ctx.Err()) } // Waits for code-server to be available before opening the browser. resp, err := client.Get(url) if err != nil { continue } resp.Body.Close() break } ctx, cancel = context.WithCancel(context.Background()) if !o.noOpen { openBrowser(url) } go func() { defer cancel() sshCmd.Wait() }() c := make(chan os.Signal) signal.Notify(c, os.Interrupt) select { case

Back | FazBrowse Home | New Git URL