mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 08:47:12 +03:00
deb57a25ed
Summary: In preparation of moving away from SSH as an intermediate entry point for Mononoke, let Mononoke work with newly introduced Metadata. This removes any assumptions we now make about how certain data is presented to us, making the current "ssh preamble" no longer central. Metadata is primarily based around identities and provides some backwards-compatible entry points to make sure we can satisfy downstream consumers of commits like hooks and logs. Simarly we now do our own reverse DNS resolving instead of relying on what's been provided by the client. This is done in an async matter and we don't rely on the result, so Mononoke can keep functioning in case DNS is offline. Reviewed By: farnz Differential Revision: D23596262 fbshipit-source-id: 3a4e97a429b13bae76ae1cdf428de0246e684a27
135 lines
3.3 KiB
Python
Executable File
135 lines
3.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import os
|
|
import shlex
|
|
import subprocess
|
|
import sys
|
|
import threading
|
|
from typing import Optional, TypeVar
|
|
|
|
|
|
_T = TypeVar("_T")
|
|
|
|
|
|
def none_throws(optional: Optional[_T]) -> _T:
|
|
assert optional is not None, "Unexpected None"
|
|
return optional
|
|
|
|
|
|
os.chdir(none_throws(os.getenv("TESTTMP")))
|
|
|
|
|
|
def parse(cmd):
|
|
"""
|
|
matches hg-ssh-wrapper
|
|
"""
|
|
try:
|
|
return shlex.split(cmd)
|
|
except ValueError as e:
|
|
print('Illegal command "%s": %s\n' % (cmd, e), file=sys.stderr)
|
|
sys.exit(255)
|
|
|
|
|
|
def parse_repo_path(path):
|
|
"""
|
|
matches hg-ssh-wrapper
|
|
"""
|
|
path = path.split("?")
|
|
if len(path) == 1:
|
|
repo = path[0]
|
|
marker = None
|
|
elif len(path) == 2:
|
|
repo = path[0]
|
|
marker = path[1]
|
|
else:
|
|
print("Illegal repo name: %s\n" % "?".join(path), file=sys.stderr)
|
|
sys.exit(255)
|
|
|
|
return repo, marker
|
|
|
|
|
|
# Skipping SSH options
|
|
host_index = 1
|
|
while host_index < len(sys.argv) and sys.argv[host_index].startswith("-"):
|
|
host_index += 1
|
|
|
|
if sys.argv[host_index] != "user@dummy":
|
|
sys.exit(-1)
|
|
|
|
os.environ["SSH_CLIENT"] = "%s 1 2" % os.environ.get("LOCALIP", "127.0.0.1")
|
|
|
|
log = open("dummylog", "ab")
|
|
log.write(b"Got arguments")
|
|
for i, arg in enumerate(sys.argv[1:]):
|
|
log.write(b" %d:%s" % (i + 1, arg.encode("utf-8")))
|
|
log.write(b"\n")
|
|
log.close()
|
|
hgcmd = sys.argv[host_index + 1]
|
|
if os.name == "nt":
|
|
# hack to make simple unix single quote quoting work on windows
|
|
hgcmd = hgcmd.replace("'", '"')
|
|
|
|
cmdargv = parse(hgcmd)
|
|
if cmdargv[:2] == ["hg", "-R"] and cmdargv[3:] == ["serve", "--stdio"]:
|
|
path, marker = parse_repo_path(cmdargv[2])
|
|
if marker == "read_copy":
|
|
path = path + "_copy"
|
|
cmdargv[2] = path
|
|
hgcmd = subprocess.list2cmdline(cmdargv)
|
|
|
|
if "hgcli" in hgcmd:
|
|
certdir = os.environ.get("HGTEST_CERTDIR") or os.environ.get("TEST_CERTS")
|
|
if certdir is None:
|
|
raise ValueError("No cert dir")
|
|
certdir = none_throws(certdir)
|
|
cert = os.path.join(certdir, "localhost.crt")
|
|
capem = os.path.join(certdir, "root-ca.crt")
|
|
privatekey = os.path.join(certdir, "localhost.key")
|
|
|
|
hgcmd += (
|
|
" --mononoke-path [::1]:"
|
|
+ none_throws(os.getenv("MONONOKE_SOCKET"))
|
|
+ (
|
|
" --cert %s --ca-pem %s --private-key %s --common-name localhost"
|
|
% (cert, capem, privatekey)
|
|
)
|
|
)
|
|
|
|
mock_username = os.environ.get("MOCK_USERNAME")
|
|
if mock_username:
|
|
hgcmd += " --mock-username '{}'".format(mock_username)
|
|
|
|
client_debug = os.environ.get("CLIENT_DEBUG")
|
|
if client_debug == "true":
|
|
hgcmd += " --client-debug"
|
|
|
|
if os.environ.get("DUMMYSSH_STABLE_ORDER"):
|
|
# Buffer all stderr outputs until the end of connection. This reduces test
|
|
# flakiness where stderr and stdout output order is nondeterministic.
|
|
p = subprocess.Popen(hgcmd, shell=True, stderr=subprocess.PIPE)
|
|
errbuf = [b""]
|
|
|
|
def readstderr():
|
|
while True:
|
|
ch = p.stderr.read(1)
|
|
if not ch:
|
|
break
|
|
errbuf[0] += ch
|
|
|
|
t = threading.Thread(target=readstderr)
|
|
t.start()
|
|
|
|
p.wait()
|
|
t.join()
|
|
|
|
if sys.version_info[0] >= 3:
|
|
sys.stderr.buffer.write(errbuf[0])
|
|
else:
|
|
sys.stderr.write(errbuf[0])
|
|
sys.stderr.flush()
|
|
|
|
sys.exit(p.returncode)
|
|
else:
|
|
r = os.system(hgcmd)
|
|
sys.exit(bool(r))
|