Mercurial > public > mercurial-scm > evolve
diff hgext/evolve.py @ 485:41bf6c27a122
evolve: stabilize now handle conflicting changeset
Some a lot of rough edge but it just damn work.
author | Pierre-Yves David <pierre-yves.david@logilab.fr> |
---|---|
date | Thu, 23 Aug 2012 17:40:28 +0200 |
parents | 20e2f2dd71f1 |
children | 8096833e9226 |
line wrap: on
line diff
--- a/hgext/evolve.py Thu Aug 23 14:15:36 2012 +0200 +++ b/hgext/evolve.py Thu Aug 23 17:40:28 2012 +0200 @@ -22,6 +22,7 @@ from mercurial import context from mercurial import copies from mercurial import util +from mercurial import merge from mercurial.i18n import _ from mercurial.commands import walkopts, commitopts, commitopts2 from mercurial import hg @@ -264,14 +265,14 @@ else: ui.write_err(_('no troubled changeset\n')) return 1 + cmdutil.bailifchanged(repo) troubles = tr.troubles() if 'unstable' in troubles: return _solveunstable(ui, repo, tr, opts['dry_run']) elif 'latecomer' in troubles: return _solvelatecomer(ui, repo, tr, opts['dry_run']) elif 'conflicting' in troubles: - ui.write_err(_('conflicting not handled yet\n')) - return 4 + return _solveconflicting(ui, repo, tr, opts['dry_run']) else: assert False # WHAT? unknown troubles @@ -444,6 +445,99 @@ finally: wlock.release() +def _solveconflicting(ui, repo, conflicting, dryrun=False): + obsolete = extensions.find('obsolete') + base, others = conflictingdata(conflicting) + if len(others) > 1: + raise util.Abort("We do not handle split yet") + other = others[0] + if conflicting.phase() <= phases.public: + raise util.Abort("We can't resolve this conflict from the public side") + if len(other.parents()) > 1: + raise util.Abort("conflicting changeset can't be a merge (yet)") + if other.p1() not in conflicting.parents(): + raise util.Abort("parent are not common (not handled yet)") + + displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) + ui.status(_('merge:')) + if not ui.quiet: + displayer.show(conflicting) + ui.status(_('with: ')) + if not ui.quiet: + displayer.show(other) + ui.status(_('base: ')) + if not ui.quiet: + displayer.show(base) + if dryrun: + ui.write('hg update -c %s &&\n' % conflicting) + ui.write('hg merge %s && \n' % other) + ui.write('hg commit -m "auto merge resolving conflict between %s and %s"&&\n' + % (conflicting, other)) + ui.write('hg up -C %s &&\n' % base) + ui.write('hg revert --all --rev tip &&\n') + ui.write('hg commit -m "`hg log -r %s --template={desc}`";\n' % conflicting) + return + #oldphase = max(conflicting.phase(), other.phase()) + wlock = repo.wlock() + try: + lock = repo.lock() + try: + if conflicting not in repo[None].parents(): + repo.ui.status(_('updating to "local" conflict\n')) + hg.update(repo, conflicting.rev()) + repo.ui.note(_('merging conflicting changeset\n')) + stats = merge.update(repo, + other.node(), + branchmerge=True, + force=False, + partial=None, + ancestor=base.node(), + mergeancestor=True) + hg._showstats(repo, stats) + if stats[3]: + repo.ui.status(_("use 'hg resolve' to retry unresolved file merges " + "or 'hg update -C .' to abandon\n")) + #repo.dirstate.write() + if stats[3] > 0: + raise util.Abort('GASP! Merge Conflict! You are on you own chap!') + tr = repo.transaction('stabilize-conflicting') + try: + repo.dirstate.setparents(conflicting.node(), node.nullid) + oldlen = len(repo) + amend(ui, repo) + if oldlen == len(repo): + new = conflicting + # no changes + else: + new = repo['.'] + obsolete.createmarkers(repo, [(other, (new,))]) + phases.retractboundary(repo, other.phase(), [new.node()]) + tr.close() + finally: + tr.release() + finally: + lock.release() + finally: + wlock.release() + + +def conflictingdata(ctx): + """return base, other part of a conflict + + This only return the first one. + + XXX this woobly function won't survive XXX + """ + obsolete = extensions.find('obsolete') + for base in ctx._repo.set('reverse(precursors(%d))', ctx): + newer = obsolete.newerversion(ctx._repo, base.node()) + # drop filter and solution including the original ctx + newer = [n for n in newer if n and ctx.node() not in n] + if newer: + return base, tuple(ctx._repo[o] for o in newer[0]) + raise KeyError('Base seem unknown. This case is not handled yet.') + + shorttemplate = '[{rev}] {desc|firstline}\n'