diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -3425,3 +3425,90 @@ with repo.wlock(): graftstate = statemod.cmdstate(repo, 'graftstate') return abortgraft(ui, repo, graftstate) + +def continuegraft(ui, repo): + """logic to resume interrupted graft using 'hg continue'""" + with repo.wlock(): + graftstate = statemod.cmdstate(repo, 'graftstate') + statedata = readgraftstate(repo, graftstate) + opts = {} + cont = True + if statedata.get('date'): + opts['date'] = statedata['date'] + if statedata.get('user'): + opts['user'] = statedata['user'] + if statedata.get('log'): + opts['log'] = True + if statedata.get('no_commit'): + opts['no_commit'] = statedata.get('no_commit') + nodes = statedata['nodes'] + revs = [repo[node].rev() for node in nodes] + + skipped = set() + for rev in repo.revs('%ld and merge()', revs): + ui.warn(_('skipping ungraftable merge revision %d\n') % rev) + skipped.add(rev) + revs = [r for r in revs if r not in skipped] + if not revs: + return -1 + + for pos, ctx in enumerate(repo.set("%ld", revs)): + desc = '%d:%s "%s"' % (ctx.rev(), ctx, + ctx.description().split('\n', 1)[0]) + names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node()) + if names: + desc += ' (%s)' % ' '.join(names) + ui.status(_('grafting %s\n') % desc) + + source = ctx.extra().get('source') + extra = {} + if source: + extra['source'] = source + extra['intermediate-source'] = ctx.hex() + else: + extra['source'] = ctx.hex() + user = ctx.user() + if opts.get('user'): + user = opts['user'] + statedata['user'] = user + date = ctx.date() + if opts.get('date'): + date = opts['date'] + statedata['date'] = date + message = ctx.description() + if opts.get('log'): + message += '\n(grafted from %s)' % ctx.hex() + statedata['log'] = True + if not cont: + # perform the graft merge with p1(rev) as 'ancestor' + overrides = {('ui', 'forcemerge'): opts.get('tool', '')} + base = ctx.p1() + with ui.configoverride(overrides, 'graft'): + stats = mergemod.graft(repo, ctx, base, ['local', 'graft']) + # report any conflicts + if stats.unresolvedcount > 0: + # write out state for --continue + nodes = [repo[rev].hex() for rev in revs[pos:]] + statedata['nodes'] = nodes + stateversion = 1 + graftstate.save(stateversion, statedata) + hint = _("use 'hg resolve' and 'hg graft --continue'") + raise error.Abort( + _("unresolved conflicts, can't continue"), + hint=hint) + else: + cont = False + editor = getcommiteditor(editform='graft', + **pycompat.strkwargs(opts)) + if not opts.get('no_commit'): + node = repo.commit(text=message, user=user, date=date, + extra=extra, editor=editor) + if node is None: + ui.warn( + _('note: graft of %d:%s created no changes to commit\n') % + (ctx.rev(), ctx)) + # checking that newnodes exist because old state files won't have it + if statedata.get('newnodes') is not None: + statedata['newnodes'].append(node) + graftstate.delete() + return 0 diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2706,6 +2706,7 @@ statemod.addunfinished( 'graft', fname='graftstate', clearable=True, stopflag=True, continueflag=True, abortfunc=cmdutil.hgabortgraft, + continuefunc=cmdutil.continuegraft, cmdhint=_("use 'hg graft --continue' or 'hg graft --stop' to stop") ) diff --git a/tests/test-graft.t b/tests/test-graft.t --- a/tests/test-graft.t +++ b/tests/test-graft.t @@ -1,4 +1,4 @@ -#testcases abortcommand abortflag +#testcases abortcommand abortflag continueflag continuecommand $ cat >> $HGRCPATH < [extdiff] @@ -13,6 +13,13 @@ > EOF #endif +#if continueflag + $ cat >> $HGRCPATH < [alias] + > continue = graft --continue + > EOF +#endif + Create a repo with some stuff in it: $ hg init a @@ -92,9 +99,11 @@ $ hg -q up -cr tip $ hg rm -q e - $ hg graft --continue - abort: no graft in progress + $ hg continue + abort: no graft in progress (continueflag !) + abort: no operation in progress (no-continueflag !) [255] + $ hg revert -r . -q e Need to specify a rev: @@ -1697,7 +1706,13 @@ $ hg resolve -m (no more unresolved files) continue: hg graft --continue - $ hg graft --continue + +#if continuecommand + $ hg continue --dry-run + graft in progress, will be resumed +#endif + + $ hg continue grafting 1:80e6d2c47cfe "added b" grafting 2:8be98ac1a569 "added c" @@ -1754,7 +1769,7 @@ (no more unresolved files) continue: hg graft --continue - $ hg graft --continue + $ hg continue grafting 1:80e6d2c47cfe "added b" grafting 2:8be98ac1a569 "added c" @@ -1803,7 +1818,7 @@ $ hg resolve -m (no more unresolved files) continue: hg graft --continue - $ hg graft --continue + $ hg continue grafting 1:80e6d2c47cfe "added b" grafting 2:8be98ac1a569 "added c" @@ -1843,7 +1858,7 @@ (no more unresolved files) continue: hg graft --continue - $ hg graft --continue + $ hg continue grafting 1:80e6d2c47cfe "added b" grafting 2:8be98ac1a569 "added c" @@ -1997,7 +2012,7 @@ $ hg abort abort: no interrupted graft to abort (abortflag !) - abort: no operation in progress (abortcommand !) + abort: no operation in progress (no-abortflag !) [255] when stripping is required @@ -2273,7 +2288,7 @@ (no more unresolved files) continue: hg graft --continue - $ hg graft --continue + $ hg continue grafting 3:09e253b87e17 "A in file a" $ hg log -GT "{rev}:{node|short} {desc}\n" @ 4:2aa9ad1006ff B in file a @@ -2350,7 +2365,7 @@ $ hg resolve --mark (no more unresolved files) continue: hg graft --continue - $ hg graft --continue + $ hg continue grafting 3:09e253b87e17 "A in file a" $ hg diff diff -r 2aa9ad1006ff a