--- 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',
--- a/tests/test-stabilize-result.t Mon Aug 20 18:59:07 2012 +0200
+++ b/tests/test-stabilize-result.t Tue Aug 21 10:10:44 2012 +0200
@@ -96,3 +96,77 @@
$ hg resolve -m a
$ hg stabilize --continue
grafting revision 5
+
+Stabilize of late comer with different parent
+==================================================
+(the with same parent is handled in test-evolve.t)
+
+ $ glog
+ @ 8:e3183e9c0961@default(draft) bk:[] newer a
+ |
+ o 7:e8cc1b534401@default(draft) bk:[changea] changea
+ |
+ o 0:07f494440405@default(draft) bk:[] adda
+
+Add another commit
+
+ $ hg gdown
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ [7] changea
+ $ echo 'c' > c
+ $ hg add c
+ $ hg commit -m 'add c'
+ created new head
+
+Get a successors of 8 on it
+
+ $ hg graft -O 8
+ grafting revision 8
+
+Add real change to the successors
+
+ $ echo 'babar' >> a
+ $ hg amend
+
+Make precursors public
+
+ $ hg phase --public 8
+ 1 new latecomers changesets
+ $ glog
+ @ 12:15c83af6f3a3@default(draft) bk:[] newer a
+ |
+ o 9:355c5cda4de1@default(draft) bk:[] add c
+ |
+ | o 8:e3183e9c0961@default(public) bk:[] newer a
+ |/
+ o 7:e8cc1b534401@default(public) bk:[changea] changea
+ |
+ o 0:07f494440405@default(public) bk:[] adda
+
+
+Stabilize !
+
+ $ hg stabilize --any --dry-run
+ recreate:[12] newer a
+ atop:[8] newer a
+ hg rebase --rev 15c83af6f3a3 --detach e8cc1b534401;
+ hg update e3183e9c0961;
+ hg revert --all --rev 15c83af6f3a3;
+ hg commit --msg "latecomer update to %s" (no-eol)
+ $ hg stabilize --any
+ recreate:[12] newer a
+ atop:[8] newer a
+ rebasing to destination parent: e8cc1b534401
+ computing new diff
+ commited as 1d94fef80e85
+ $ glog
+ @ 14:1d94fef80e85@default(draft) bk:[] latecomer update to e3183e9c0961:
+ |
+ | o 9:355c5cda4de1@default(draft) bk:[] add c
+ | |
+ o | 8:e3183e9c0961@default(public) bk:[] newer a
+ |/
+ o 7:e8cc1b534401@default(public) bk:[changea] changea
+ |
+ o 0:07f494440405@default(public) bk:[] adda
+