Updated aiohttp v3.12.12 -> v3.12.13 Updated attrs v23.1.0 -> v23.2.0 Updated blessed v1.19.1 -> v1.21.0 Updated cbor2 v4.0.1 -> v4.1.2 Updated compare-locales v9.0.1 -> v9.0.4 Updated distro v1.8.0 -> v1.9.0 Updated fluent-migrate v0.13.2 -> v0.13.3 Updated importlib-metadata v6.0.0 -> v6.11.0 Updated jsmin v3.0.0 -> v3.0.1 Updated json-e v4.5.3 -> v4.8.0 Updated looseversion v1.0.1 -> v1.3.0 Updated mozilla-taskgraph v3.3.1 -> v3.3.2 Updated multidict v6.4.4 -> v6.5.0 Updated pathspec v0.9.0 -> v0.12.1 Updated pyasn1 v0.4.8 -> v0.6.1 Updated pyasn1-modules v0.2.8 -> v0.4.2 Updated pylru v1.0.9 -> v1.2.1 Updated python-hglib v2.4 -> v2.6.2 Updated redo v2.0.3 -> v2.0.4 Updated requests-unixsocket v0.2.0 -> v0.4.1 Updated responses v0.10.6 -> v0.25.7 Updated rsa v4.9 -> v4.9.1 Updated sentry-sdk v1.14.0 -> v1.45.1 Updated six v1.16.0 -> v1.17.0 Updated tomlkit v0.12.3 -> v0.13.3 Updated tqdm v4.66.3 -> v4.67.1 Updated typing-extensions v4.12.2 -> v4.14.0 Updated voluptuous v0.12.1 -> v0.15.2 Updated yamllint v1.23.0 -> v1.37.1 Differential Revision: https://phabricator.services.mozilla.com/D254096
242 lines
6.2 KiB
Python
242 lines
6.2 KiB
Python
import os, subprocess, sys
|
|
from hglib import error
|
|
try:
|
|
from io import BytesIO
|
|
except ImportError:
|
|
from cStringIO import StringIO as BytesIO
|
|
|
|
if sys.version_info[0] > 2:
|
|
izip = zip
|
|
integertypes = (int,)
|
|
|
|
def b(s):
|
|
"""Encode the string as bytes."""
|
|
return s.encode('latin-1')
|
|
else:
|
|
from itertools import izip
|
|
integertypes = (long, int)
|
|
bytes = str # Defined in Python 2.6/2.7, but to the same value.
|
|
|
|
def b(s):
|
|
"""Encode the string as bytes."""
|
|
return s
|
|
|
|
def strtobytes(s):
|
|
"""Return the bytes of the string representation of an object."""
|
|
return str(s).encode('latin-1')
|
|
|
|
def grouper(n, iterable):
|
|
''' list(grouper(2, range(4))) -> [(0, 1), (2, 3)] '''
|
|
args = [iter(iterable)] * n
|
|
return izip(*args)
|
|
|
|
def eatlines(s, n):
|
|
"""
|
|
>>> eatlines(b("1\\n2"), 1) == b('2')
|
|
True
|
|
>>> eatlines(b("1\\n2"), 2) == b('')
|
|
True
|
|
>>> eatlines(b("1\\n2"), 3) == b('')
|
|
True
|
|
>>> eatlines(b("1\\n2\\n3"), 1) == b('2\\n3')
|
|
True
|
|
"""
|
|
cs = BytesIO(s)
|
|
|
|
for line in cs:
|
|
n -= 1
|
|
if n == 0:
|
|
return cs.read()
|
|
return b('')
|
|
|
|
def skiplines(s, prefix):
|
|
"""
|
|
Skip lines starting with prefix in s
|
|
|
|
>>> skiplines(b('a\\nb\\na\\n'), b('a')) == b('b\\na\\n')
|
|
True
|
|
>>> skiplines(b('a\\na\\n'), b('a')) == b('')
|
|
True
|
|
>>> skiplines(b(''), b('a')) == b('')
|
|
True
|
|
>>> skiplines(b('a\\nb'), b('b')) == b('a\\nb')
|
|
True
|
|
"""
|
|
cs = BytesIO(s)
|
|
|
|
for line in cs:
|
|
if not line.startswith(prefix):
|
|
return line + cs.read()
|
|
|
|
return b('')
|
|
|
|
def _cmdval(val):
|
|
if isinstance(val, bytes):
|
|
return val
|
|
else:
|
|
return strtobytes(val)
|
|
|
|
def cmdbuilder(name, *args, **kwargs):
|
|
"""
|
|
A helper for building the command arguments
|
|
|
|
args are the positional arguments
|
|
|
|
kwargs are the options
|
|
keys that are single lettered are prepended with '-', others with '--',
|
|
underscores are replaced with dashes
|
|
|
|
keys with False boolean values are ignored, lists add the key multiple times
|
|
|
|
None arguments are skipped
|
|
|
|
>>> cmdbuilder(b('cmd'), a=True, b=False, c=None) == [b('cmd'), b('-a')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), long=True) == [b('cmd'), b('--long')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), s=b('hort')) == [b('cmd'), b('-short')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), str=b('s')) == [b('cmd'), b('--str=s')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), d_ash=True) == [b('cmd'), b('--d-ash')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), _=True) == [b('cmd'), b('-')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), l=[1, 2]) == [b('cmd'), b('-l1'), b('-l2')]
|
|
True
|
|
>>> expect = [b('cmd'), b('--list=1'), b('--list=2')]
|
|
>>> cmdbuilder(b('cmd'), list=[1, 2]) == expect
|
|
True
|
|
>>> cmdbuilder(b('cmd'), None) == [b('cmd')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), b('-a')) == [b('cmd'), b('--'), b('-a')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), b('')) == [b('cmd'), b('--'), b('')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), s=b('')) == [b('cmd'), b('-s'), b('')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), s=[b('')]) == [b('cmd'), b('-s'), b('')]
|
|
True
|
|
>>> cmdbuilder(b('cmd'), long=b('')) == [b('cmd'), b('--long=')]
|
|
True
|
|
"""
|
|
cmd = [name]
|
|
for arg, val in kwargs.items():
|
|
if val is None:
|
|
continue
|
|
|
|
arg = pfx = arg.encode('latin-1').replace(b('_'), b('-'))
|
|
short = (len(arg) == 1)
|
|
if arg != b('-'):
|
|
if short:
|
|
arg = pfx = b('-') + arg
|
|
else:
|
|
arg = b('--') + arg
|
|
pfx = arg + b('=')
|
|
if isinstance(val, bool):
|
|
if val:
|
|
cmd.append(arg)
|
|
elif isinstance(val, list):
|
|
for v in val:
|
|
s = _cmdval(v)
|
|
if s or not short:
|
|
cmd.append(pfx + s)
|
|
else:
|
|
cmd.extend([arg, s])
|
|
else:
|
|
s = _cmdval(val)
|
|
if s or not short:
|
|
cmd.append(pfx + s)
|
|
else:
|
|
cmd.extend([arg, s])
|
|
|
|
args = [a for a in args if a is not None]
|
|
if args:
|
|
cmd.append(b('--'))
|
|
for a in args:
|
|
cmd.append(a)
|
|
|
|
return cmd
|
|
|
|
class reterrorhandler(object):
|
|
"""This class is meant to be used with rawcommand() error handler
|
|
argument. It remembers the return value the command returned if
|
|
it's one of allowed values, which is only 1 if none are given.
|
|
Otherwise it raises a CommandError.
|
|
|
|
>>> e = reterrorhandler('')
|
|
>>> bool(e)
|
|
True
|
|
>>> e(1, 'a', '')
|
|
'a'
|
|
>>> bool(e)
|
|
False
|
|
|
|
"""
|
|
def __init__(self, args, allowed=None):
|
|
self.args = args
|
|
self.ret = 0
|
|
if allowed is None:
|
|
self.allowed = [1]
|
|
else:
|
|
self.allowed = allowed
|
|
|
|
def __call__(self, ret, out, err):
|
|
self.ret = ret
|
|
if ret not in self.allowed:
|
|
raise error.CommandError(self.args, ret, out, err)
|
|
return out
|
|
|
|
def __nonzero__(self):
|
|
""" Returns True if the return code was 0, False otherwise """
|
|
return self.ret == 0
|
|
|
|
def __bool__(self):
|
|
return self.__nonzero__()
|
|
|
|
class propertycache(object):
|
|
"""
|
|
Decorator that remembers the return value of a function call.
|
|
|
|
>>> execcount = 0
|
|
>>> class obj(object):
|
|
... def func(self):
|
|
... global execcount
|
|
... execcount += 1
|
|
... return []
|
|
... func = propertycache(func)
|
|
>>> o = obj()
|
|
>>> o.func
|
|
[]
|
|
>>> execcount
|
|
1
|
|
>>> o.func
|
|
[]
|
|
>>> execcount
|
|
1
|
|
"""
|
|
def __init__(self, func):
|
|
self.func = func
|
|
self.name = func.__name__
|
|
def __get__(self, obj, type=None):
|
|
result = self.func(obj)
|
|
setattr(obj, self.name, result)
|
|
return result
|
|
|
|
close_fds = os.name == 'posix'
|
|
|
|
startupinfo = None
|
|
if os.name == 'nt':
|
|
startupinfo = subprocess.STARTUPINFO()
|
|
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
|
|
|
def popen(args, env=None):
|
|
environ = None
|
|
if env:
|
|
environ = dict(os.environ)
|
|
environ.update(env)
|
|
|
|
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE, close_fds=close_fds,
|
|
startupinfo=startupinfo, env=environ)
|