2444 if ui.verbose or not m.exact(f): |
2444 if ui.verbose or not m.exact(f): |
2445 ui.status(_('removing %s\n') % m.rel(f)) |
2445 ui.status(_('removing %s\n') % m.rel(f)) |
2446 |
2446 |
2447 repo[None].forget(forget) |
2447 repo[None].forget(forget) |
2448 return errs |
2448 return errs |
|
2449 |
|
2450 @command('graft', |
|
2451 [], |
|
2452 _('[OPTION]... REVISION...')) |
|
2453 def graft(ui, repo, rev, *revs, **opts): |
|
2454 '''copy changes from other branches onto the current branch |
|
2455 |
|
2456 This command uses Mercurial's merge logic to copy individual |
|
2457 changes from other branches without merging branches in the |
|
2458 history graph. This is sometimes known as 'backporting' or |
|
2459 'cherry-picking'. |
|
2460 |
|
2461 Changesets that are ancestors of the current revision, that have |
|
2462 already been grafted, or that are merges will be skipped. |
|
2463 |
|
2464 Returns 0 on successful completion. |
|
2465 ''' |
|
2466 |
|
2467 cmdutil.bailifchanged(repo) |
|
2468 |
|
2469 revs = [rev] + list(revs) |
|
2470 revs = scmutil.revrange(repo, revs) |
|
2471 |
|
2472 # check for merges |
|
2473 for ctx in repo.set('%ld and merge()', revs): |
|
2474 ui.warn(_('skipping ungraftable merge revision %s\n') % ctx.rev()) |
|
2475 revs.remove(ctx.rev()) |
|
2476 if not revs: |
|
2477 return -1 |
|
2478 |
|
2479 # check for ancestors of dest branch |
|
2480 for ctx in repo.set('::. and %ld', revs): |
|
2481 ui.warn(_('skipping ancestor revision %s\n') % ctx.rev()) |
|
2482 revs.remove(ctx.rev()) |
|
2483 if not revs: |
|
2484 return -1 |
|
2485 |
|
2486 # check ancestors for earlier grafts |
|
2487 ui.debug('scanning for existing transplants') |
|
2488 for ctx in repo.set("::. - ::%ld", revs): |
|
2489 n = ctx.extra().get('source') |
|
2490 if n and n in repo: |
|
2491 r = repo[n].rev() |
|
2492 ui.warn(_('skipping already grafted revision %s\n') % r) |
|
2493 revs.remove(r) |
|
2494 if not revs: |
|
2495 return -1 |
|
2496 |
|
2497 for ctx in repo.set("%ld", revs): |
|
2498 current = repo['.'] |
|
2499 ui.debug('grafting revision %s', ctx.rev()) |
|
2500 # perform the graft merge with p1(rev) as 'ancestor' |
|
2501 stats = mergemod.update(repo, ctx.node(), True, True, False, |
|
2502 ctx.p1().node()) |
|
2503 # drop the second merge parent |
|
2504 repo.dirstate.setparents(current.node(), nullid) |
|
2505 repo.dirstate.write() |
|
2506 # fix up dirstate for copies and renames |
|
2507 cmdutil.duplicatecopies(repo, ctx.rev(), current.node(), nullid) |
|
2508 # report any conflicts |
|
2509 if stats and stats[3] > 0: |
|
2510 raise util.Abort(_("unresolved conflicts, can't continue"), |
|
2511 hint=_('use hg resolve and hg graft --continue')) |
|
2512 # commit |
|
2513 extra = {'source': ctx.hex()} |
|
2514 repo.commit(text=ctx.description(), user=ctx.user(), |
|
2515 date=ctx.date(), extra=extra) |
|
2516 |
|
2517 return 0 |
2449 |
2518 |
2450 @command('grep', |
2519 @command('grep', |
2451 [('0', 'print0', None, _('end fields with NUL')), |
2520 [('0', 'print0', None, _('end fields with NUL')), |
2452 ('', 'all', None, _('print all revisions that match')), |
2521 ('', 'all', None, _('print all revisions that match')), |
2453 ('a', 'text', None, _('treat all files as text')), |
2522 ('a', 'text', None, _('treat all files as text')), |