Mercurial > public > mercurial-scm > evolve
diff hgext/evolve.py @ 469:abeb17a9e313
stabilize: handle latecomer
Merge are not handled yet.
author | Pierre-Yves David <pierre-yves.david@logilab.fr> |
---|---|
date | Tue, 21 Aug 2012 10:10:44 +0200 |
parents | 6b1b6d338478 |
children | a2dfe82f27a0 |
line wrap: on
line diff
--- a/hgext/evolve.py Mon Aug 20 18:59:07 2012 +0200 +++ b/hgext/evolve.py Tue Aug 21 10:10:44 2012 +0200 @@ -176,6 +176,7 @@ repo._bookmarks[book] = dest.node() if oldbookmarks or destbookmarks: bookmarks.write(repo) + return nodenew except util.Abort: # Invalidate the previous setparents repo.dirstate.invalidate() @@ -263,10 +264,9 @@ return 1 troubles = tr.troubles() if 'unstable' in troubles: - return _stabunstable(ui, repo, tr, opts['dry_run']) + return _solveunstable(ui, repo, tr, opts['dry_run']) elif 'latecomer' in troubles: - ui.write_err(_('latecomer not handled yet\n')) - return 4 + return _solvelatecomer(ui, repo, tr, opts['dry_run']) elif 'conflicting' in troubles: ui.write_err(_('conflicting not handled yet\n')) return 4 @@ -287,7 +287,7 @@ return tr -def _stabunstable(ui, repo, orig, dryrun=False): +def _solveunstable(ui, repo, orig, dryrun=False): """Stabilize a unstable changeset""" obsolete = extensions.find('obsolete') obs = orig.parents()[0] @@ -334,6 +334,109 @@ finally: lock.release() +def _solvelatecomer(ui, repo, latecomer, dryrun=False): + """Stabilize a latecomer changeset""" + # For now we deny latecomer merge + if len(latecomer.parents()) > 1: + raise util.Abort('late comer stabilization is confused by latecomer' + ' %s being a merge' % latecomer) + prec = repo.set('last(allprecursors(%d) and public())', latecomer).next() + # For now we deny target merge + if len(prec.parents()) > 1: + raise util.Abort('late comer stabilization is confused by precursors' + ' %s being a merge' % prec) + + displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) + repo.ui.status(_('recreate:')) + if not ui.quiet: + displayer.show(latecomer) + repo.ui.status(_('atop:')) + if not ui.quiet: + displayer.show(prec) + obsolete = extensions.find('obsolete') + if dryrun: + todo = 'hg rebase --rev %s --detach %s;\n' % (latecomer, prec.p1()) + repo.ui.write(todo) + repo.ui.write('hg update %s;\n' % prec) + repo.ui.write('hg revert --all --rev %s;\n' % latecomer) + repo.ui.write('hg commit --msg "latecomer update to %s"') + return 0 + wlock = repo.wlock() + try: + newid = tmpctx = None + tmpctx = latecomer + lock = repo.lock() + try: + bmupdate = _bookmarksupdater(repo, latecomer.node()) + # Basic check for common parent. Far too complicated and fragile + tr = repo.transaction('latecomer-stabilize') + try: + if not list(repo.set('parents(%d) and parents(%d)', latecomer, prec)): + # Need to rebase the changeset at the right place + repo.ui.status(_('rebasing to destination parent: %s\n') % prec.p1()) + try: + tmpid = relocate(repo, latecomer, prec.p1()) + if tmpid is not None: + tmpctx = repo[tmpid] + obsolete.createmarkers(repo, [(latecomer, (tmpctx,))]) + except MergeFailure: + repo.opener.write('graftstate', latecomer.hex() + '\n') + repo.ui.write_err(_('stabilize failed!\n')) + repo.ui.write_err(_('fix conflict and run "hg stabilize --continue"\n')) + raise + # Create the new commit context + repo.ui.status(_('computing new diff\n')) + files = set() + copied = copies.pathcopies(prec, latecomer) + precmanifest = prec.manifest() + for key, val in latecomer.manifest().iteritems(): + if precmanifest.pop(key, None) != val: + files.add(key) + files.update(precmanifest) # add missing files + # commit it + if files: # something to commit! + def filectxfn(repo, ctx, path): + if path in latecomer: + fctx = latecomer[path] + flags = fctx.flags() + mctx = context.memfilectx(fctx.path(), fctx.data(), + islink='l' in flags, + isexec='x' in flags, + copied=copied.get(path)) + return mctx + raise IOError() + text = 'latecomer update to %s:\n\n' % prec + text += latecomer.description() + + new = context.memctx(repo, + parents=[prec.node(), node.nullid], + text=text, + files=files, + filectxfn=filectxfn, + user=latecomer.user(), + date=latecomer.date(), + extra=latecomer.extra()) + + newid = repo.commitctx(new) + if newid is None: + obsolete.createmarkers(repo, [(tmpctx, ())]) + newid = prec.node() + else: + phases.retractboundary(repo, latecomer.phase(), [newid]) + obsolete.createmarkers(repo, [(tmpctx, (repo[newid],))]) + bmupdate(newid) + tr.close() + repo.ui.status(_('commited as %s\n') % node.short(newid)) + finally: + tr.release() + finally: + lock.release() + # reroute the working copy parent to the new changeset + repo.dirstate.setparents(newid, node.nullid) + finally: + wlock.release() + + shorttemplate = '[{rev}] {desc|firstline}\n' @command('^gdown',