comparison hgext/phabricator.py @ 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 16b607e9f714
children 79c0121220e3
comparison
equal deleted inserted replaced
43838:a47ccdcce4f9 43839:70060915c3f2
8 8
9 This extension provides a ``phabsend`` command which sends a stack of 9 This extension provides a ``phabsend`` command which sends a stack of
10 changesets to Phabricator, and a ``phabread`` command which prints a stack of 10 changesets to Phabricator, and a ``phabread`` command which prints a stack of
11 revisions in a format suitable for :hg:`import`, and a ``phabupdate`` command 11 revisions in a format suitable for :hg:`import`, and a ``phabupdate`` command
12 to update statuses in batch. 12 to update statuses in batch.
13
14 A "phabstatus" view for :hg:`show` is also provided; it displays status
15 information of Phabricator differentials associated with unfinished
16 changesets.
13 17
14 By default, Phabricator requires ``Test Plan`` which might prevent some 18 By default, Phabricator requires ``Test Plan`` which might prevent some
15 changeset from being sent. The requirement could be disabled by changing 19 changeset from being sent. The requirement could be disabled by changing
16 ``differential.require-test-plan-field`` config server side. 20 ``differential.require-test-plan-field`` config server side.
17 21
58 cmdutil, 62 cmdutil,
59 context, 63 context,
60 encoding, 64 encoding,
61 error, 65 error,
62 exthelper, 66 exthelper,
67 graphmod,
63 httpconnection as httpconnectionmod, 68 httpconnection as httpconnectionmod,
69 logcmdutil,
64 match, 70 match,
65 mdiff, 71 mdiff,
66 obsutil, 72 obsutil,
67 parser, 73 parser,
68 patch, 74 patch,
78 ) 84 )
79 from mercurial.utils import ( 85 from mercurial.utils import (
80 procutil, 86 procutil,
81 stringutil, 87 stringutil,
82 ) 88 )
89 from . import show
90
83 91
84 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for 92 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
85 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should 93 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
86 # be specifying the version(s) of Mercurial they are tested with, or 94 # be specifying the version(s) of Mercurial they are tested with, or
87 # leave the attribute unspecified. 95 # leave the attribute unspecified.
459 oldnode = getnode(lastdiff) 467 oldnode = getnode(lastdiff)
460 if oldnode and not has_node(oldnode): 468 if oldnode and not has_node(oldnode):
461 oldnode = None 469 oldnode = None
462 470
463 result[newnode] = (oldnode, lastdiff, drev) 471 result[newnode] = (oldnode, lastdiff, drev)
472
473 return result
474
475
476 def getdrevmap(repo, revs):
477 """Return a dict mapping each rev in `revs` to their Differential Revision
478 ID or None.
479 """
480 result = {}
481 for rev in revs:
482 result[rev] = None
483 ctx = repo[rev]
484 # Check commit message
485 m = _differentialrevisiondescre.search(ctx.description())
486 if m:
487 result[rev] = int(m.group('id'))
488 continue
489 # Check tags
490 for tag in repo.nodetags(ctx.node()):
491 m = _differentialrevisiontagre.match(tag)
492 if m:
493 result[rev] = int(m.group(1))
494 break
464 495
465 return result 496 return result
466 497
467 498
468 def getdiff(ctx, diffopts): 499 def getdiff(ctx, diffopts):
1649 url += b'/' 1680 url += b'/'
1650 url += t 1681 url += t
1651 1682
1652 return templateutil.hybriddict({b'url': url, b'id': t,}) 1683 return templateutil.hybriddict({b'url': url, b'id': t,})
1653 return None 1684 return None
1685
1686
1687 @show.showview(b'phabstatus', csettopic=b'work')
1688 def phabstatusshowview(ui, repo, displayer):
1689 """Phabricator differiential status"""
1690 revs = repo.revs('sort(_underway(), topo)')
1691 drevmap = getdrevmap(repo, revs)
1692 unknownrevs, drevids, revsbydrevid = [], set([]), {}
1693 for rev, drevid in pycompat.iteritems(drevmap):
1694 if drevid is not None:
1695 drevids.add(drevid)
1696 revsbydrevid.setdefault(drevid, set([])).add(rev)
1697 else:
1698 unknownrevs.append(rev)
1699
1700 drevs = callconduit(ui, b'differential.query', {b'ids': list(drevids)})
1701 drevsbyrev = {}
1702 for drev in drevs:
1703 for rev in revsbydrevid[int(drev[b'id'])]:
1704 drevsbyrev[rev] = drev
1705
1706 def phabstatus(ctx):
1707 drev = drevsbyrev[ctx.rev()]
1708 ui.write(b"\n%(uri)s %(statusName)s\n" % drev)
1709
1710 revs -= smartset.baseset(unknownrevs)
1711 revdag = graphmod.dagwalker(repo, revs)
1712
1713 ui.setconfig(b'experimental', b'graphshorten', True)
1714 displayer._exthook = phabstatus
1715 nodelen = show.longestshortest(repo, revs)
1716 logcmdutil.displaygraph(
1717 ui,
1718 repo,
1719 revdag,
1720 displayer,
1721 graphmod.asciiedges,
1722 props={b'nodelen': nodelen},
1723 )