# HG changeset patch # User Pierre-Yves David # Date 1345536644 -7200 # Node ID abeb17a9e313baea490006929f1903863ed0b1d5 # Parent 6b1b6d3384787f586be3697700c01fd3f4739671 stabilize: handle latecomer Merge are not handled yet. diff -r 6b1b6d338478 -r abeb17a9e313 hgext/evolve.py --- 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', diff -r 6b1b6d338478 -r abeb17a9e313 tests/test-evolve.t --- a/tests/test-evolve.t Mon Aug 20 18:59:07 2012 +0200 +++ b/tests/test-evolve.t Tue Aug 21 10:10:44 2012 +0200 @@ -298,18 +298,28 @@ | o 0 : base - test - $ hg stabilize --any - latecomer not handled yet - [4] + $ hg stabilize --any --traceback + recreate:[8] another feature that rox + atop:[7] another feature + computing new diff + commited as 8d77fa12ab0c $ hg glog - @ 8 feature-B: another feature that rox - test + @ 9 feature-B: latecomer update to 5f4744038ed5: - test | - | o 7 : another feature - test - |/ + o 7 : another feature - test + | o 6 feature-A: a nifty feature - test | o 0 : base - test + $ hg diff -r 9 -r 8 + $ hg diff -r 9^ -r 9 + diff --git a/main-file-1 b/main-file-1 + --- a/main-file-1 + +++ b/main-file-1 + @@ -3,1 +3,1 @@ + -Zwei + +deux $ cd .. diff -r 6b1b6d338478 -r abeb17a9e313 tests/test-stabilize-result.t --- 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 +