mirror of
https://gerrit.googlesource.com/git-repo
synced 2024-12-21 07:16:21 +00:00
ssh: Set git protocol version 2 on SSH ControlMaster
According to https://git-scm.com/docs/protocol-v2#_ssh_and_file_transport, when using SSH, the environment variable GIT_PROTOCOL must be set when establishing the connection to the git server. Normally git does this by itself. But in repo-tool where the SSH connection is managed by the repo-tool, it must be passed in explicitly instead. Under some circumstances of environment configuration, this caused all repo sync commands over ssh to always use git protocol version 1. Even when git was configured to use version 2. Using git protocol v2 can significantly improve fetch speeds, since it uses server side filtering of refs, reducing the amount of unneccessary objects to send. Change-Id: I6d4c3b7300a6090d707480b1a638ed03622fa71a Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/411362 Tested-by: Erik Elmeke <erik@haleytek.corp-partner.google.com> Reviewed-by: Mike Frysinger <vapier@google.com> Commit-Queue: Erik Elmeke <erik@haleytek.corp-partner.google.com>
This commit is contained in:
parent
2c5fb84d35
commit
eede374e3e
58
ssh.py
58
ssh.py
@ -24,6 +24,7 @@ import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from git_command import git
|
||||
import platform_utils
|
||||
from repo_trace import Trace
|
||||
|
||||
@ -211,7 +212,33 @@ class ProxyManager:
|
||||
# and print to the log there.
|
||||
pass
|
||||
|
||||
command = command_base[:1] + ["-M", "-N"] + command_base[1:]
|
||||
# Git protocol V2 is a new feature in git 2.18.0, made default in
|
||||
# git 2.26.0
|
||||
# It is faster and more efficient than V1.
|
||||
# To enable it when using SSH, the environment variable GIT_PROTOCOL
|
||||
# must be set in the SSH side channel when establishing the connection
|
||||
# to the git server.
|
||||
# See https://git-scm.com/docs/protocol-v2#_ssh_and_file_transport
|
||||
# Normally git does this by itself. But here, where the SSH connection
|
||||
# is established manually over ControlMaster via the repo-tool, it must
|
||||
# be passed in explicitly instead.
|
||||
# Based on https://git-scm.com/docs/gitprotocol-pack#_extra_parameters,
|
||||
# GIT_PROTOCOL is considered an "Extra Parameter" and must be ignored
|
||||
# by servers that do not understand it. This means that it is safe to
|
||||
# set it even when connecting to older servers.
|
||||
# It should also be safe to set the environment variable for older
|
||||
# local git versions, since it is only part of the ssh side channel.
|
||||
git_protocol_version = _get_git_protocol_version()
|
||||
ssh_git_protocol_args = [
|
||||
"-o",
|
||||
f"SetEnv GIT_PROTOCOL=version={git_protocol_version}",
|
||||
]
|
||||
|
||||
command = (
|
||||
command_base[:1]
|
||||
+ ["-M", "-N", *ssh_git_protocol_args]
|
||||
+ command_base[1:]
|
||||
)
|
||||
p = None
|
||||
try:
|
||||
with Trace("Call to ssh: %s", " ".join(command)):
|
||||
@ -293,3 +320,32 @@ class ProxyManager:
|
||||
tempfile.mkdtemp("", "ssh-", tmp_dir), "master-" + tokens
|
||||
)
|
||||
return self._sock_path
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=1)
|
||||
def _get_git_protocol_version() -> str:
|
||||
"""Return the git protocol version.
|
||||
|
||||
The version is found by first reading the global git config.
|
||||
If no git config for protocol version exists, try to deduce the default
|
||||
protocol version based on the git version.
|
||||
|
||||
See https://git-scm.com/docs/gitprotocol-v2 for details.
|
||||
"""
|
||||
try:
|
||||
return subprocess.check_output(
|
||||
["git", "config", "--get", "--global", "protocol.version"],
|
||||
encoding="utf-8",
|
||||
stderr=subprocess.PIPE,
|
||||
).strip()
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode == 1:
|
||||
# Exit code 1 means that the git config key was not found.
|
||||
# Try to imitate the defaults that git would have used.
|
||||
git_version = git.version_tuple()
|
||||
if git_version >= (2, 26, 0):
|
||||
# Since git version 2.26, protocol v2 is the default.
|
||||
return "2"
|
||||
return "1"
|
||||
# Other exit codes indicate error with reading the config.
|
||||
raise
|
||||
|
Loading…
Reference in New Issue
Block a user