t/cmd: expand functionality of lfs-ssh-echo

Currently, the only thing that lfs-ssh-echo does is provide the output
for git-lfs-authenticate.  However, in the future, we'll want to support
git-lfs-transfer, and for our testing functionality, we'll want to
pretend to have an SSH transport for cloning and pushing.

In order to do so, let's refactor out some code.  Let's plan to spawn a
shell with the argument if we get a Git command or a git-lfs-transfer
command, and let's make things work properly on both Unix (where we'll
want sh) and Windows (where sh is not always available but we can rely
on bash).

Let's also gracefully handle the fact that we may not always have the
same number of arguments.  Git will think we're a simple transport
helper and so we won't receive a port in the tests that use mock SSH
URLs, so let's accommodate the lack of port argument and the lack of
-- arguments passed by Git.

Since the error handling has changed somewhat, update the SSH test to
make it look for the new error message and extract the command line from
the trace output, since we no longer print it as part of the error
message in this case.

Additionally, include some examples of the new syntax forms we're
expecting here, so it's easier for future developers to reason about
this code.

While we're at it, let's do some long-overdue cleanups.  First, fix a
long-standing bug in this code.  The check for the length of authLine
was against the quantity 13, which was probably a typo for 3, which used
to be the number of arguments in the final argument string.  However,
because we just printed an error and didn't exit, we never noticed this
problem.  Let's fix this here by adding a suitable os.Exit call.  Note
that the check is now against the quanity 2 because when invoking
git-receive-pack or git-upload-pack, we receive only the program name
and repo, but no operation.

Additionally, remove an extra debugging statement and an unused variable
from the tests.
This commit is contained in:
brian m. carlson 2021-05-14 17:47:40 +00:00
parent 1b72076964
commit 25347c593e
No known key found for this signature in database
GPG Key ID: 2D0C9BC12F82B3A1
3 changed files with 63 additions and 17 deletions

@ -6,7 +6,10 @@ import (
"encoding/json"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
"syscall"
"time"
)
@ -17,36 +20,81 @@ type sshResponse struct {
ExpiresIn int `json:"expires_in,omitempty"`
}
func shell() string {
if runtime.GOOS == "windows" {
return "bash"
}
return "sh"
}
func spawnCommand(command string) error {
cmd := exec.Command(shell(), "-c", command)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if e, ok := err.(*exec.ExitError); ok {
var ws syscall.WaitStatus
ws, ok = e.ProcessState.Sys().(syscall.WaitStatus)
if ok {
os.Exit(ws.ExitStatus())
}
}
return err
}
func main() {
// expect args:
// lfs-ssh-echo -p PORT -- git@127.0.0.1 git-lfs-authenticate REPO OPERATION
if len(os.Args) != 6 {
// lfs-ssh-echo -p PORT -- git@127.0.0.1 "git-lfs-authenticate REPO OPERATION"
// lfs-ssh-echo -p PORT -- git@127.0.0.1 "git-lfs-transfer REPO OPERATION"
// lfs-ssh-echo -- git@127.0.0.1 "git-lfs-transfer REPO OPERATION"
// lfs-ssh-echo git@127.0.0.1 "git-upload-pack REPO"
// lfs-ssh-echo git@127.0.0.1 "git-receive-pack REPO"
if len(os.Args) < 3 {
fmt.Fprintf(os.Stderr, "got %d args: %v", len(os.Args), os.Args)
os.Exit(1)
}
if os.Args[1] != "-p" {
offset := 4
if os.Args[1] == "--" {
offset = 2
} else if os.Args[1] == "git@127.0.0.1" {
offset = 1
} else if os.Args[1] != "-p" {
fmt.Fprintf(os.Stderr, "$1 expected \"-p\", got %q", os.Args[1])
os.Exit(1)
}
if os.Args[3] != "--" {
} else if os.Args[3] != "--" {
fmt.Fprintf(os.Stderr, "$3 expected \"--\", got %q", os.Args[3])
os.Exit(1)
}
if os.Args[4] != "git@127.0.0.1" {
fmt.Fprintf(os.Stderr, "$4 expected \"git@127.0.0.1\", got %q", os.Args[4])
if len(os.Args) < offset+2 {
fmt.Fprintf(os.Stderr, "got %d args: %v", len(os.Args), os.Args)
os.Exit(1)
}
// just "git-lfs-authenticate REPO OPERATION"
authLine := strings.Split(os.Args[5], " ")
if len(authLine) < 13 {
fmt.Fprintf(os.Stderr, "bad git-lfs-authenticate line: %s\nargs: %v", authLine, os.Args)
if os.Args[offset] != "git@127.0.0.1" {
fmt.Fprintf(os.Stderr, "$4 expected \"git@127.0.0.1\", got %q", os.Args[offset])
os.Exit(1)
}
repo := authLine[1]
// just "git-lfs-(authenticate|transfer) REPO OPERATION" or "git-(upload|receive)-pack REPO"
remoteCmd := strings.Split(os.Args[offset+1], " ")
if len(remoteCmd) < 2 {
fmt.Fprintf(os.Stderr, "bad command line: %s\nargs: %v", remoteCmd, os.Args)
os.Exit(1)
}
if remoteCmd[0] == "git-lfs-transfer" || remoteCmd[0] == "git-upload-pack" || remoteCmd[0] == "git-receive-pack" {
err := spawnCommand(os.Args[offset+1])
if err != nil {
fmt.Fprintf(os.Stderr, "error running command %q: %v", remoteCmd[0], err)
os.Exit(1)
}
return
}
repo := remoteCmd[1]
r := &sshResponse{
Href: fmt.Sprintf("http://127.0.0.1:%s/%s.git/info/lfs", os.Args[2], repo),

@ -114,7 +114,6 @@ begin_test "batch transfers with ssh endpoint"
git lfs env
contents="test"
oid="$(calc_oid "$contents")"
git lfs track "*.dat"
printf "%s" "$contents" > test.dat
git add .gitattributes test.dat

@ -11,7 +11,6 @@ begin_test "ssh with proxy command in lfs.url"
clone_repo "$reponame" "$reponame"
sshurl="${GITSERVER/http:\/\//ssh://-oProxyCommand=ssh-proxy-test/}/$reponame"
echo $sshurl
git config lfs.url "$sshurl"
contents="test"
@ -21,13 +20,13 @@ begin_test "ssh with proxy command in lfs.url"
git add .gitattributes test.dat
git commit -m "initial commit"
git push origin main 2>&1 | tee push.log
GIT_TRACE=1 git push origin main 2>&1 | tee push.log
if [ "0" -eq "${PIPESTATUS[0]}" ]; then
echo >&2 "fatal: push succeeded"
exit 1
fi
grep "got 4 args" push.log
grep 'expected.*git@127.0.0.1' push.log
grep "lfs-ssh-echo -- -oProxyCommand" push.log
)
end_test