diff --git a/cmd/coder/sync.go b/cmd/coder/sync.go index 0e26af96..e0d62708 100644 --- a/cmd/coder/sync.go +++ b/cmd/coder/sync.go @@ -1,7 +1,11 @@ package main import ( + "bytes" + "fmt" + "log" "os" + "os/exec" "path/filepath" "strings" @@ -29,6 +33,23 @@ func (cmd *syncCmd) RegisterFlags(fl *pflag.FlagSet) { fl.BoolVarP(&cmd.init, "init", "i", false, "do initial transfer and exit") } +// version returns local rsync protocol version as a string. +func (_ *syncCmd) version() string { + cmd := exec.Command("rsync", "--version") + out, err := cmd.CombinedOutput() + if err != nil { + log.Fatal(err) + } + + firstLine, err := bytes.NewBuffer(out).ReadString('\n') + if err != nil { + log.Fatal(err) + } + versionString := strings.Split(firstLine, "protocol version ") + + return versionString[1] +} + func (cmd *syncCmd) Run(fl *pflag.FlagSet) { var ( local = fl.Arg(0) @@ -71,6 +92,16 @@ func (cmd *syncCmd) Run(fl *pflag.FlagSet) { LocalDir: absLocal, Client: entClient, } + + localVersion := cmd.version() + remoteVersion, rsyncErr := s.Version() + + if rsyncErr != nil { + flog.Info("Unable to determine remote rsync version. Proceeding cautiously.") + } else if localVersion != remoteVersion { + flog.Fatal(fmt.Sprintf("rsync protocol mismatch. %s.", localVersion, rsyncErr)) + } + for err == nil || err == sync.ErrRestartSync { err = s.Run() } diff --git a/internal/sync/sync.go b/internal/sync/sync.go index 32086896..b00cbeb1 100644 --- a/internal/sync/sync.go +++ b/internal/sync/sync.go @@ -1,6 +1,7 @@ package sync import ( + "bytes" "context" "errors" "fmt" @@ -10,6 +11,7 @@ import ( "os/exec" "path" "path/filepath" + "strings" "sync" "sync/atomic" "time" @@ -261,6 +263,44 @@ const ( maxAcceptableDispatch = time.Millisecond * 50 ) +// Version returns remote protocol version as a string. +// Or, an error if one exists. +func (s Sync) Version() (string, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + + conn, err := s.Client.DialWsep(ctx, s.Env) + if err != nil { + return "", err + } + defer conn.Close(websocket.CloseNormalClosure, "") + + execer := wsep.RemoteExecer(conn) + process, err := execer.Start(ctx, wsep.Command{ + Command: "rsync", + Args: []string{"--version"}, + }) + if err != nil { + return "", err + } + buf := &bytes.Buffer{} + io.Copy(buf, process.Stdout()) + + err = process.Wait() + if err != nil { + return "", err + } + + firstLine, err := buf.ReadString('\n') + if err != nil { + return "", err + } + + versionString := strings.Split(firstLine, "protocol version ") + + return versionString[1], nil +} + // Run starts the sync synchronously. // Use this command to debug what wasn't sync'd correctly: // rsync -e "coder sh" -nicr ~/Projects/cdr/coder-cli/. ammar:/home/coder/coder-cli/ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy