phases: move RemotePhasesSummary to revision number
This continue our quest to align more logic on revision number instead of
node-ids. The motivation is similar to the change to `new_heads` and
`analyze_remote_phases` a few changeset earlier.
Again, we take this as an opportunity to rename the class, and the attribute to
the new naming scheme. This will highlight the need for code update for any
code using it an expecting node-ids.
Many of the rev-num → node-id conversion we had to introduce in the previous
changesets can now be removed. More will be removed in the future as we continue
to align code toward rev-num usage.
time saved in the 100 milliseconds order of magnitude for the mozilla-try
benchmark I have been using.
#!/usr/bin/env python
"""This does HTTP requests (GET by default) given a host:port and path and
returns a subset of the headers plus the body of the result."""
import argparse
import json
import os
import sys
from mercurial import (
pycompat,
util,
)
httplib = util.httplib
try:
import msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
except ImportError:
pass
stdout = getattr(sys.stdout, 'buffer', sys.stdout)
parser = argparse.ArgumentParser()
parser.add_argument('--twice', action='store_true')
parser.add_argument('--headeronly', action='store_true')
parser.add_argument('--json', action='store_true')
parser.add_argument('--hgproto')
parser.add_argument(
'--requestheader',
nargs='*',
default=[],
help='Send an additional HTTP request header. Argument '
'value is <header>=<value>',
)
parser.add_argument('--bodyfile', help='Write HTTP response body to a file')
parser.add_argument('--method', default='GET', help='HTTP method to use')
parser.add_argument('host')
parser.add_argument('path')
parser.add_argument('show', nargs='*')
args = parser.parse_args()
twice = args.twice
headeronly = args.headeronly
formatjson = args.json
hgproto = args.hgproto
requestheaders = args.requestheader
tag = None
def request(method, host, path, show):
assert not path.startswith('/'), path
global tag
headers = {}
if tag:
headers['If-None-Match'] = tag
if hgproto:
headers['X-HgProto-1'] = hgproto
for header in requestheaders:
key, value = header.split('=', 1)
headers[key] = value
conn = httplib.HTTPConnection(host)
conn.request(method, '/' + path, None, headers)
response = conn.getresponse()
stdout.write(
b'%d %s\n' % (response.status, response.reason.encode('ascii'))
)
if show[:1] == ['-']:
show = sorted(
h for h, v in response.getheaders() if h.lower() not in show
)
for h in [h.lower() for h in show]:
if response.getheader(h, None) is not None:
stdout.write(
b"%s: %s\n"
% (h.encode('ascii'), response.getheader(h).encode('ascii'))
)
if headeronly:
# still read the body to prevent windows to be unhappy about that
# (this might some flakyness in test-hgweb-filelog.t on Windows)
data = response.read()
else:
stdout.write(b'\n')
data = response.read()
if args.bodyfile:
bodyfh = open(args.bodyfile, 'wb')
else:
bodyfh = stdout
# Pretty print JSON. This also has the beneficial side-effect
# of verifying emitted JSON is well-formed.
if formatjson:
# json.dumps() will print trailing newlines. Eliminate them
# to make tests easier to write.
data = pycompat.json_loads(data)
lines = json.dumps(data, sort_keys=True, indent=2).splitlines()
for line in lines:
bodyfh.write(pycompat.sysbytes(line.rstrip()))
bodyfh.write(b'\n')
else:
bodyfh.write(data)
if args.bodyfile:
bodyfh.close()
if twice and response.getheader('ETag', None):
tag = response.getheader('ETag')
# further try to please the windows-flakyness deity
conn.close()
return response.status
status = request(args.method, args.host, args.path, args.show)
if twice:
status = request(args.method, args.host, args.path, args.show)
if 200 <= status <= 305:
sys.exit(0)
sys.exit(1)