Show More
@@ -38,6 +38,8 b' import re' | |||||
38 | from mercurial.node import bin, nullid |
|
38 | from mercurial.node import bin, nullid | |
39 | from mercurial.i18n import _ |
|
39 | from mercurial.i18n import _ | |
40 | from mercurial import ( |
|
40 | from mercurial import ( | |
|
41 | cmdutil, | |||
|
42 | context, | |||
41 | encoding, |
|
43 | encoding, | |
42 | error, |
|
44 | error, | |
43 | mdiff, |
|
45 | mdiff, | |
@@ -315,7 +317,7 b' def createdifferentialrevision(ctx, revi' | |||||
315 | if not revision: |
|
317 | if not revision: | |
316 | raise error.Abort(_('cannot create revision for %s') % ctx) |
|
318 | raise error.Abort(_('cannot create revision for %s') % ctx) | |
317 |
|
319 | |||
318 | return revision |
|
320 | return revision, diff | |
319 |
|
321 | |||
320 | def userphids(repo, names): |
|
322 | def userphids(repo, names): | |
321 | """convert user names to PHIDs""" |
|
323 | """convert user names to PHIDs""" | |
@@ -333,6 +335,7 b' def userphids(repo, names):' | |||||
333 |
|
335 | |||
334 | @command('phabsend', |
|
336 | @command('phabsend', | |
335 | [('r', 'rev', [], _('revisions to send'), _('REV')), |
|
337 | [('r', 'rev', [], _('revisions to send'), _('REV')), | |
|
338 | ('', 'amend', False, _('update commit messages')), | |||
336 | ('', 'reviewer', [], _('specify reviewers')), |
|
339 | ('', 'reviewer', [], _('specify reviewers')), | |
337 | ('', 'confirm', None, _('ask for confirmation before sending'))], |
|
340 | ('', 'confirm', None, _('ask for confirmation before sending'))], | |
338 | _('REV [OPTIONS]')) |
|
341 | _('REV [OPTIONS]')) | |
@@ -348,18 +351,28 b' def phabsend(ui, repo, *revs, **opts):' | |||||
348 | obsstore and tags information so it can figure out whether to update an |
|
351 | obsstore and tags information so it can figure out whether to update an | |
349 | existing Differential Revision, or create a new one. |
|
352 | existing Differential Revision, or create a new one. | |
350 |
|
353 | |||
|
354 | If --amend is set, update commit messages so they have the | |||
|
355 | ``Differential Revision`` URL, remove related tags. This is similar to what | |||
|
356 | arcanist will do, and is more desired in author-push workflows. Otherwise, | |||
|
357 | use local tags to record the ``Differential Revision`` association. | |||
|
358 | ||||
351 | The --confirm option lets you confirm changesets before sending them. You |
|
359 | The --confirm option lets you confirm changesets before sending them. You | |
352 | can also add following to your configuration file to make it default |
|
360 | can also add following to your configuration file to make it default | |
353 | behaviour. |
|
361 | behaviour. | |
354 |
|
362 | |||
355 | [phabsend] |
|
363 | [phabsend] | |
356 | confirm = true |
|
364 | confirm = true | |
|
365 | ||||
|
366 | phabsend will check obsstore and the above association to decide whether to | |||
|
367 | update an existing Differential Revision, or create a new one. | |||
357 | """ |
|
368 | """ | |
358 | revs = list(revs) + opts.get('rev', []) |
|
369 | revs = list(revs) + opts.get('rev', []) | |
359 | revs = scmutil.revrange(repo, revs) |
|
370 | revs = scmutil.revrange(repo, revs) | |
360 |
|
371 | |||
361 | if not revs: |
|
372 | if not revs: | |
362 | raise error.Abort(_('phabsend requires at least one changeset')) |
|
373 | raise error.Abort(_('phabsend requires at least one changeset')) | |
|
374 | if opts.get('amend'): | |||
|
375 | cmdutil.checkunfinished(repo) | |||
363 |
|
376 | |||
364 | confirm = ui.configbool('phabsend', 'confirm') |
|
377 | confirm = ui.configbool('phabsend', 'confirm') | |
365 | confirm |= bool(opts.get('confirm')) |
|
378 | confirm |= bool(opts.get('confirm')) | |
@@ -377,6 +390,9 b' def phabsend(ui, repo, *revs, **opts):' | |||||
377 | # {newnode: (oldnode, olddiff, olddrev} |
|
390 | # {newnode: (oldnode, olddiff, olddrev} | |
378 | oldmap = getoldnodedrevmap(repo, [repo[r].node() for r in revs]) |
|
391 | oldmap = getoldnodedrevmap(repo, [repo[r].node() for r in revs]) | |
379 |
|
392 | |||
|
393 | drevids = [] # [int] | |||
|
394 | diffmap = {} # {newnode: diff} | |||
|
395 | ||||
380 | # Send patches one by one so we know their Differential Revision IDs and |
|
396 | # Send patches one by one so we know their Differential Revision IDs and | |
381 | # can provide dependency relationship |
|
397 | # can provide dependency relationship | |
382 | lastrevid = None |
|
398 | lastrevid = None | |
@@ -386,20 +402,24 b' def phabsend(ui, repo, *revs, **opts):' | |||||
386 |
|
402 | |||
387 | # Get Differential Revision ID |
|
403 | # Get Differential Revision ID | |
388 | oldnode, olddiff, revid = oldmap.get(ctx.node(), (None, None, None)) |
|
404 | oldnode, olddiff, revid = oldmap.get(ctx.node(), (None, None, None)) | |
389 | if oldnode != ctx.node(): |
|
405 | if oldnode != ctx.node() or opts.get('amend'): | |
390 | # Create or update Differential Revision |
|
406 | # Create or update Differential Revision | |
391 |
revision = createdifferentialrevision( |
|
407 | revision, diff = createdifferentialrevision( | |
392 |
|
|
408 | ctx, revid, lastrevid, oldnode, olddiff, actions) | |
|
409 | diffmap[ctx.node()] = diff | |||
393 | newrevid = int(revision[r'object'][r'id']) |
|
410 | newrevid = int(revision[r'object'][r'id']) | |
394 | if revid: |
|
411 | if revid: | |
395 | action = _('updated') |
|
412 | action = _('updated') | |
396 | else: |
|
413 | else: | |
397 | action = _('created') |
|
414 | action = _('created') | |
398 |
|
415 | |||
399 | # Create a local tag to note the association |
|
416 | # Create a local tag to note the association, if commit message | |
400 | tagname = 'D%d' % newrevid |
|
417 | # does not have it already | |
401 | tags.tag(repo, tagname, ctx.node(), message=None, user=None, |
|
418 | m = _differentialrevisiondescre.search(ctx.description()) | |
402 | date=None, local=True) |
|
419 | if not m or int(m.group(1)) != newrevid: | |
|
420 | tagname = 'D%d' % newrevid | |||
|
421 | tags.tag(repo, tagname, ctx.node(), message=None, user=None, | |||
|
422 | date=None, local=True) | |||
403 | else: |
|
423 | else: | |
404 | # Nothing changed. But still set "newrevid" so the next revision |
|
424 | # Nothing changed. But still set "newrevid" so the next revision | |
405 | # could depend on this one. |
|
425 | # could depend on this one. | |
@@ -408,8 +428,43 b' def phabsend(ui, repo, *revs, **opts):' | |||||
408 |
|
428 | |||
409 | ui.write(_('D%s: %s - %s: %s\n') % (newrevid, action, ctx, |
|
429 | ui.write(_('D%s: %s - %s: %s\n') % (newrevid, action, ctx, | |
410 | ctx.description().split('\n')[0])) |
|
430 | ctx.description().split('\n')[0])) | |
|
431 | drevids.append(newrevid) | |||
411 | lastrevid = newrevid |
|
432 | lastrevid = newrevid | |
412 |
|
433 | |||
|
434 | # Update commit messages and remove tags | |||
|
435 | if opts.get('amend'): | |||
|
436 | unfi = repo.unfiltered() | |||
|
437 | drevs = callconduit(repo, 'differential.query', {'ids': drevids}) | |||
|
438 | with repo.wlock(), repo.lock(), repo.transaction('phabsend'): | |||
|
439 | wnode = unfi['.'].node() | |||
|
440 | mapping = {} # {oldnode: [newnode]} | |||
|
441 | for i, rev in enumerate(revs): | |||
|
442 | old = unfi[rev] | |||
|
443 | drevid = drevids[i] | |||
|
444 | drev = [d for d in drevs if int(d[r'id']) == drevid][0] | |||
|
445 | newdesc = getdescfromdrev(drev) | |||
|
446 | # Make sure commit message contain "Differential Revision" | |||
|
447 | if old.description() != newdesc: | |||
|
448 | parents = [ | |||
|
449 | mapping.get(old.p1().node(), (old.p1(),))[0], | |||
|
450 | mapping.get(old.p2().node(), (old.p2(),))[0], | |||
|
451 | ] | |||
|
452 | new = context.metadataonlyctx( | |||
|
453 | repo, old, parents=parents, text=newdesc, | |||
|
454 | user=old.user(), date=old.date(), extra=old.extra()) | |||
|
455 | newnode = new.commit() | |||
|
456 | mapping[old.node()] = [newnode] | |||
|
457 | # Update diff property | |||
|
458 | writediffproperties(unfi[newnode], diffmap[old.node()]) | |||
|
459 | # Remove local tags since it's no longer necessary | |||
|
460 | tagname = 'D%d' % drevid | |||
|
461 | if tagname in repo.tags(): | |||
|
462 | tags.tag(repo, tagname, nullid, message=None, user=None, | |||
|
463 | date=None, local=True) | |||
|
464 | scmutil.cleanupnodes(repo, mapping, 'phabsend') | |||
|
465 | if wnode in mapping: | |||
|
466 | unfi.setparents(mapping[wnode][0]) | |||
|
467 | ||||
413 | # Map from "hg:meta" keys to header understood by "hg import". The order is |
|
468 | # Map from "hg:meta" keys to header understood by "hg import". The order is | |
414 | # consistent with "hg export" output. |
|
469 | # consistent with "hg export" output. | |
415 | _metanamemap = util.sortdict([(r'user', 'User'), (r'date', 'Date'), |
|
470 | _metanamemap = util.sortdict([(r'user', 'User'), (r'date', 'Date'), |
General Comments 0
You need to be logged in to leave comments.
Login now