diff --git a/hgext/phabricator.py b/hgext/phabricator.py --- a/hgext/phabricator.py +++ b/hgext/phabricator.py @@ -11,6 +11,10 @@ revisions in a format suitable for :hg:`import`, and a ``phabupdate`` command to update statuses in batch. +A "phabstatus" view for :hg:`show` is also provided; it displays status +information of Phabricator differentials associated with unfinished +changesets. + By default, Phabricator requires ``Test Plan`` which might prevent some changeset from being sent. The requirement could be disabled by changing ``differential.require-test-plan-field`` config server side. @@ -60,7 +64,9 @@ encoding, error, exthelper, + graphmod, httpconnection as httpconnectionmod, + logcmdutil, match, mdiff, obsutil, @@ -80,6 +86,8 @@ procutil, stringutil, ) +from . import show + # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should @@ -465,6 +473,29 @@ return result +def getdrevmap(repo, revs): + """Return a dict mapping each rev in `revs` to their Differential Revision + ID or None. + """ + result = {} + for rev in revs: + result[rev] = None + ctx = repo[rev] + # Check commit message + m = _differentialrevisiondescre.search(ctx.description()) + if m: + result[rev] = int(m.group('id')) + continue + # Check tags + for tag in repo.nodetags(ctx.node()): + m = _differentialrevisiontagre.match(tag) + if m: + result[rev] = int(m.group(1)) + break + + return result + + def getdiff(ctx, diffopts): """plain-text diff without header (user, commit message, etc)""" output = util.stringio() @@ -1651,3 +1682,42 @@ return templateutil.hybriddict({b'url': url, b'id': t,}) return None + + +@show.showview(b'phabstatus', csettopic=b'work') +def phabstatusshowview(ui, repo, displayer): + """Phabricator differiential status""" + revs = repo.revs('sort(_underway(), topo)') + drevmap = getdrevmap(repo, revs) + unknownrevs, drevids, revsbydrevid = [], set([]), {} + for rev, drevid in pycompat.iteritems(drevmap): + if drevid is not None: + drevids.add(drevid) + revsbydrevid.setdefault(drevid, set([])).add(rev) + else: + unknownrevs.append(rev) + + drevs = callconduit(ui, b'differential.query', {b'ids': list(drevids)}) + drevsbyrev = {} + for drev in drevs: + for rev in revsbydrevid[int(drev[b'id'])]: + drevsbyrev[rev] = drev + + def phabstatus(ctx): + drev = drevsbyrev[ctx.rev()] + ui.write(b"\n%(uri)s %(statusName)s\n" % drev) + + revs -= smartset.baseset(unknownrevs) + revdag = graphmod.dagwalker(repo, revs) + + ui.setconfig(b'experimental', b'graphshorten', True) + displayer._exthook = phabstatus + nodelen = show.longestshortest(repo, revs) + logcmdutil.displaygraph( + ui, + repo, + revdag, + displayer, + graphmod.asciiedges, + props={b'nodelen': nodelen}, + )