D122: phabricator: add --amend option to phabsend
quark (Jun Wu)
phabricator at mercurial-scm.org
Tue Jul 18 04:20:07 UTC 2017
quark created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
Previously `hg phabsend` was imitating `hg email` and won't mutate
changesets. That works fine with reviewer-push workflow, reviewers run
`phabread`, `import`.
However, it does not work well with author-push workflow. Namely, the author
needs to run extra commands to get the right commit message, and remove the
local tag after push.
This patch solves those issues by adding the `--amend` option, so local
changesets will have the right commit message, and tags become unnecessary.
TEST PLAN
Given the following DAG:
o 17
o 16
| o 15
| @ 14
|/
o 13
o 12
Run `hg phabsend '(13::)-17' --amend`, check the new DAG looks like:
o 21
| o 20
| @ 19
|/
o 18
| o 17
| x 16
| x 13
|/
o 12
And commit messages are updated to contain the `Differential Revision` lines.
Also check `phabsend .` followed by a `phabsend . --amend`, the commit
message will be updated and the tag will be removed.
REPOSITORY
rHG Mercurial
REVISION DETAIL
https://phab.mercurial-scm.org/D122
AFFECTED FILES
contrib/phabricator.py
CHANGE DETAILS
diff --git a/contrib/phabricator.py b/contrib/phabricator.py
--- a/contrib/phabricator.py
+++ b/contrib/phabricator.py
@@ -38,6 +38,8 @@
from mercurial.node import bin, nullid
from mercurial.i18n import _
from mercurial import (
+ cmdutil,
+ context,
encoding,
error,
mdiff,
@@ -325,6 +327,7 @@
@command('phabsend',
[('r', 'rev', [], _('revisions to send'), _('REV')),
+ ('', 'amend', False, _('update commit messages')),
('', 'reviewer', [], _('specify reviewers'))],
_('REV [OPTIONS]'))
def phabsend(ui, repo, *revs, **opts):
@@ -334,16 +337,21 @@
with a linear dependencies relationship using the order specified by the
revset.
- For the first time uploading changesets, local tags will be created to
- maintain the association. After the first time, phabsend will check
- obsstore and tags information so it can figure out whether to update an
- existing Differential Revision, or create a new one.
+ If --amend is set, update commit messages so they have the
+ ``Differential Revision`` URL, remove related tags. This is similar to what
+ arcanist will do, and is more desired in author-push workflows. Otherwise,
+ use local tags to record the ``Differential Revision`` association.
+
+ phabsend will check obsstore and the above association to decide whether to
+ update an existing Differential Revision, or create a new one.
"""
revs = list(revs) + opts.get('rev', [])
revs = scmutil.revrange(repo, revs)
if not revs:
raise error.Abort(_('phabsend requires at least one changeset'))
+ if opts.get('amend'):
+ cmdutil.checkunfinished(repo)
actions = []
reviewers = opts.get('reviewer', [])
@@ -355,6 +363,7 @@
# Send patches one by one so we know their Differential Revision IDs and
# can provide dependency relationship
+ drevids = []
lastrevid = None
for rev in revs:
ui.debug('sending rev %d\n' % rev)
@@ -372,20 +381,55 @@
else:
action = _('created')
- # Create a local tag to note the association
- tagname = 'D%d' % newrevid
- tags.tag(repo, tagname, ctx.node(), message=None, user=None,
- date=None, local=True)
+ # Create a local tag to note the association, if commit message
+ # does not have it already
+ m = _differentialrevisiondescre.search(ctx.description())
+ if not m or int(m.group(1)) != newrevid:
+ tagname = 'D%d' % newrevid
+ tags.tag(repo, tagname, ctx.node(), message=None, user=None,
+ date=None, local=True)
else:
# Nothing changed. But still set "newrevid" so the next revision
# could depend on this one.
newrevid = revid
action = _('skipped')
ui.write(_('D%s: %s - %s: %s\n') % (newrevid, action, ctx,
ctx.description().split('\n')[0]))
+ drevids.append(newrevid)
lastrevid = newrevid
+ # Update commit messages and remove tags
+ if opts.get('amend'):
+ unfi = repo.unfiltered()
+ drevs = callconduit(repo, 'differential.query', {'ids': drevids})
+ with repo.wlock(), repo.lock(), repo.transaction('phabsend'):
+ wnode = unfi['.'].node()
+ mapping = {} # {oldnode: newnode}
+ for i, rev in enumerate(revs):
+ old = unfi[rev]
+ drevid = drevids[i]
+ drev = [d for d in drevs if int(d[r'id']) == drevid][0]
+ newdesc = getdescfromdrev(drev)
+ # Make sure commit message contain "Differential Revision"
+ if old.description() != newdesc:
+ parents = [
+ mapping.get(old.p1().node(), (old.p1(),))[0],
+ mapping.get(old.p2().node(), (old.p2(),))[0],
+ ]
+ new = context.metadataonlyctx(
+ repo, old, parents=parents, text=newdesc,
+ user=old.user(), date=old.date(), extra=old.extra())
+ mapping[old.node()] = [new.commit()]
+ # Remove local tags since it's no longer necessary
+ tagname = 'D%d' % drevid
+ if tagname in repo.tags():
+ tags.tag(repo, tagname, nullid, message=None, user=None,
+ date=None, local=True)
+ scmutil.cleanupnodes(repo, mapping, 'phabsend')
+ if wnode in mapping:
+ unfi.setparents(mapping[wnode][0])
+
# Map from "hg:meta" keys to header understood by "hg import". The order is
# consistent with "hg export" output.
_metanamemap = util.sortdict([(r'user', 'User'), (r'date', 'Date'),
EMAIL PREFERENCES
https://phab.mercurial-scm.org/settings/panel/emailpreferences/
To: quark, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list