--- 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',