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 |
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 ) |