Add a configuration option to control the SSH protocol is used

Some people have very slow SSH round trips and the extra time to attempt
a failed git-lfs-transfer operation is bothersome.  Let's add an option
to allow users to use either the pure SSH protocol or the older hybrid
protocol based on the URL in question to let them choose the right value
if they know what it should be.
This commit is contained in:
brian m. carlson 2023-10-25 19:03:14 +00:00
parent 2c048843dd
commit 3ee26845d9
No known key found for this signature in database
GPG Key ID: 2D0C9BC12F82B3A1
4 changed files with 39 additions and 0 deletions

@ -318,6 +318,13 @@ Supports URL config lookup as described in:
https://git-scm.com/docs/git-config#git-config-httplturlgt. To set this
value per-host:
`git config --global lfs.https://github.com/.locksverify [true|false]`.
* `lfs.sshtransfer` / `lfs.<url>.sshtransfer`
+
Configures whether SSH transfers (the pure SSH protocol) are used.
By default (or if the value is set to `negotiate`), the pure SSH protocol is
tried first, and then the older hybrid protocol. If `always` is used, then
only the pure SSH protocol is tried. Similarly, if `never` is used, then only
the hybrid protocol is attempted.
* `lfs.<url>.contenttype`
+
Determines whether Git LFS should attempt to detect an appropriate HTTP

@ -1,6 +1,7 @@
package lfsapi
import (
"github.com/git-lfs/git-lfs/v3/config"
"github.com/git-lfs/git-lfs/v3/creds"
"github.com/git-lfs/git-lfs/v3/errors"
"github.com/git-lfs/git-lfs/v3/lfshttp"
@ -59,6 +60,11 @@ func (c *Client) SSHTransfer(operation, remote string) *ssh.SSHTransfer {
if len(endpoint.SSHMetadata.UserAndHost) == 0 {
return nil
}
uc := config.NewURLConfig(c.context.GitEnv())
if val, ok := uc.Get("lfs", endpoint.OriginalUrl, "sshtransfer"); ok && val != "negotiate" && val != "always" {
tracerx.Printf("skipping pure SSH protocol connection by request")
return nil
}
ctx := c.Context()
tracerx.Printf("attempting pure SSH protocol connection")
sshTransfer, err := ssh.NewSSHTransfer(ctx.OSEnv(), ctx.GitEnv(), &endpoint.SSHMetadata, operation)

@ -209,6 +209,12 @@ func (c *Client) sshResolveWithRetries(e Endpoint, method string) (*sshAuthRespo
var sshRes sshAuthResponse
var err error
uc := config.NewURLConfig(c.gitEnv)
if val, ok := uc.Get("lfs", e.OriginalUrl, "sshtransfer"); ok && val != "negotiate" && val != "never" {
tracerx.Printf("skipping SSH-HTTPS hybrid protocol connection by request")
return nil, errors.New("git-lfs-authenticate has been disabled by request")
}
requests := tools.MaxInt(0, c.sshTries) + 1
for i := 0; i < requests; i++ {
sshRes, err = c.SSH.Resolve(e, method)

@ -72,6 +72,16 @@ begin_test "list a single lock (SSH; git-lfs-authenticate)"
grep "f.dat" locks.log
grep "Git LFS Tests" locks.log
grep "lfs-ssh-echo.*git-lfs-authenticate /$reponame download" trace.log
GIT_TRACE=1 git -c lfs."$sshurl".sshtransfer=never lfs locks --path "f.dat" 2>trace.log | tee locks.log
[ $(wc -l < locks.log) -eq 1 ]
grep "f.dat" locks.log
grep "Git LFS Tests" locks.log
grep "lfs-ssh-echo.*git-lfs-authenticate /$reponame download" trace.log
grep "skipping pure SSH protocol" trace.log
GIT_TRACE=1 git -c lfs."$sshurl".sshtransfer=always lfs locks --path "f.dat" 2>trace.log && exit 1
grep "git-lfs-authenticate has been disabled by request" trace.log
)
end_test
@ -98,6 +108,16 @@ begin_test "list a single lock (SSH; git-lfs-transfer)"
[ $(wc -l < locks.log) -eq 1 ]
grep "f.dat" locks.log
grep "lfs-ssh-echo.*git-lfs-transfer .*$reponame.git download" trace.log
GIT_TRACE=1 git -c lfs."$sshurl".sshtransfer=always lfs locks --path "f.dat" 2>trace.log | tee locks.log
[ $(wc -l < locks.log) -eq 1 ]
grep "f.dat" locks.log
grep "lfs-ssh-echo.*git-lfs-transfer .*$reponame.git download" trace.log
GIT_TRACE=1 git -c lfs."$sshurl".sshtransfer=negotiate lfs locks --path "f.dat" 2>trace.log | tee locks.log
[ $(wc -l < locks.log) -eq 1 ]
grep "f.dat" locks.log
grep "lfs-ssh-echo.*git-lfs-transfer .*$reponame.git download" trace.log
)
end_test