sapling/contrib/hgclient.py
Lukasz Langa dfda82e492 Upgrade to 18.5b1
Summary: Mostly empty lines removed and added.  A few bugfixes on excessive line splitting.

Reviewed By: quark-zju

Differential Revision: D8199128

fbshipit-source-id: 90c1616061bfd7cfbba0b75f03f89683340374d5
2018-05-30 02:23:58 -07:00

136 lines
3.2 KiB
Python

# A minimal client for Mercurial's command server
from __future__ import absolute_import, print_function
import os
import signal
import socket
import struct
import subprocess
import sys
import time
try:
import cStringIO as io
stringio = io.StringIO
except ImportError:
import io
stringio = io.StringIO
def connectpipe(path=None):
cmdline = ["hg", "serve", "--cmdserver", "pipe"]
if path:
cmdline += ["-R", path]
server = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
return server
class unixconnection(object):
def __init__(self, sockpath):
self.sock = sock = socket.socket(socket.AF_UNIX)
sock.connect(sockpath)
self.stdin = sock.makefile("wb")
self.stdout = sock.makefile("rb")
def wait(self):
self.stdin.close()
self.stdout.close()
self.sock.close()
class unixserver(object):
def __init__(self, sockpath, logpath=None, repopath=None):
self.sockpath = sockpath
cmdline = ["hg", "serve", "--cmdserver", "unix", "-a", sockpath]
if repopath:
cmdline += ["-R", repopath]
if logpath:
stdout = open(logpath, "a")
stderr = subprocess.STDOUT
else:
stdout = stderr = None
self.server = subprocess.Popen(cmdline, stdout=stdout, stderr=stderr)
# wait for listen()
while self.server.poll() is None:
if os.path.exists(sockpath):
break
time.sleep(0.1)
def connect(self):
return unixconnection(self.sockpath)
def shutdown(self):
os.kill(self.server.pid, signal.SIGTERM)
self.server.wait()
def writeblock(server, data):
server.stdin.write(struct.pack(">I", len(data)))
server.stdin.write(data)
server.stdin.flush()
def readchannel(server):
data = server.stdout.read(5)
if not data:
raise EOFError
channel, length = struct.unpack(">cI", data)
if channel in "IL":
return channel, length
else:
return channel, server.stdout.read(length)
def sep(text):
return text.replace("\\", "/")
def runcommand(
server, args, output=sys.stdout, error=sys.stderr, input=None, outfilter=lambda x: x
):
print("*** runcommand", " ".join(args))
sys.stdout.flush()
server.stdin.write("runcommand\n")
writeblock(server, "\0".join(args))
if not input:
input = stringio()
while True:
ch, data = readchannel(server)
if ch == "o":
output.write(outfilter(data))
output.flush()
elif ch == "e":
error.write(data)
error.flush()
elif ch == "I":
writeblock(server, input.read(data))
elif ch == "L":
writeblock(server, input.readline(data))
elif ch == "r":
ret, = struct.unpack(">i", data)
if ret != 0:
print(" [%d]" % ret)
return ret
else:
print("unexpected channel %c: %r" % (ch, data))
if ch.isupper():
return
def check(func, connect=connectpipe):
sys.stdout.flush()
server = connect()
try:
return func(server)
finally:
server.stdin.close()
server.wait()