[PATCH 3 of 3] phabricator: add phabread command to read patches

Kevin Bullock kbullock+mercurial at ringworld.org
Mon Jul 3 14:27:56 EDT 2017


> On Jul 2, 2017, at 22:10, Jun Wu <quark at fb.com> wrote:
> 
> # HG changeset patch
> # User Jun Wu <quark at fb.com>
> # Date 1499051289 25200
> #      Sun Jul 02 20:08:09 2017 -0700
> # Node ID ee0c338d2115294aba8d844d62b9615d48517b94
> # Parent  edb97a6c5f1065227180e41010076ad09697b408
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #              hg pull https://bitbucket.org/quark-zju/hg-draft -r ee0c338d2115
> phabricator: add phabread command to read patches

Queued, thanks! Some notes inline.

> diff --git a/contrib/phabricator.py b/contrib/phabricator.py
> --- a/contrib/phabricator.py
> +++ b/contrib/phabricator.py
> @@ -8,5 +8,6 @@
> 
> This extension provides a ``phabsend`` command which sends a stack of
> -changesets to Phabricator without amending commit messages.
> +changesets to Phabricator without amending commit messages, and a ``phabread``
> +command which could serialize a stack of diffs to plain-text patches.

Updated in-flight to "...which prints a stack of revisions in a format suitable for :hg:`import`."

> By default, Phabricator requires ``Test Plan`` which might prevent some
> @@ -274,2 +275,64 @@ def phabsend(ui, repo, *revs, **opts):
>                                             ctx.description().split('\n')[0]))
>         lastrevid = newrevid
> +
> +_summaryre = re.compile('^Summary:\s*', re.M)
> +
> +def readpatch(repo, params, recursive=False):
> +    """generate plain-text patch readable by 'hg import'
> +
> +    params is passed to "differential.query". If recursive is True, also return
> +    dependent patches.
> +    """
> +    # Differential Revisions
> +    drevs = callconduit(repo, 'differential.query', params)
> +    if len(drevs) == 1:
> +        drev = drevs[0]
> +    else:
> +        raise error.Abort(_('cannot get Differential Revision %r') % params)
> +
> +    repo.ui.note(_('reading D%s\n') % drev[r'id'])
> +
> +    diffid = max(int(v) for v in drev[r'diffs'])
> +    body = callconduit(repo, 'differential.getrawdiff', {'diffID': diffid})
> +    desc = callconduit(repo, 'differential.getcommitmessage',
> +                       {'revision_id': drev[r'id']})
> +    header = '# HG changeset patch\n'
> +
> +    # Remove potential empty "Summary:"
> +    desc = _summaryre.sub('', desc)
> +
> +    # Try to preserve metadata (user, date) from hg:meta property
> +    diffs = callconduit(repo, 'differential.querydiffs', {'ids': [diffid]})
> +    props = diffs[str(diffid)][r'properties'] # could be empty list or dict
> +    if props and r'hg:meta' in props:
> +        meta = props[r'hg:meta']
> +        for k, v in meta.items():
> +            header += '# %s %s\n' % (k.capitalize(), v)
> +
> +    patch = ('%s%s\n%s') % (header, desc, body)
> +
> +    # Check dependencies
> +    if recursive:
> +        auxiliary = drev.get(r'auxiliary', {})
> +        depends = auxiliary.get(r'phabricator:depends-on', [])
> +        for phid in depends:
> +            patch = readpatch(repo, {'phids': [phid]}, recursive=True) + patch
> +    return patch

While the repeated API calls we need to do lend themselves to a recursive function, I worry about the memory usage this will cause on large series. For follow-up, could you make it so that we're calling the API iteratively, and print each patch as it comes in? Maybe with a custom iterator?

pacem in terris / мир / शान्ति / ‎‫سَلاَم‬ / 平和
Kevin R. Bullock



More information about the Mercurial-devel mailing list