changeset 43839:70060915c3f2

phabricator: add a "phabstatus" show view We add a "phabstatus" show view (called as "hg show phabstatus") which renders a dag with underway revisions associated with a differential revision and displays their status. The revisions shown is a subset of that shown by "work" view, only including revisions with known by Phabricator. Differential Revision: https://phab.mercurial-scm.org/D7506
author Denis Laxalde <denis@laxalde.org>
date Sat, 23 Nov 2019 11:04:19 +0100
parents a47ccdcce4f9
children 79c0121220e3
files hgext/phabricator.py
diffstat 1 files changed, 70 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/phabricator.py	Tue Dec 10 14:40:44 2019 -0800
+++ b/hgext/phabricator.py	Sat Nov 23 11:04:19 2019 +0100
@@ -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},
+    )