# HG changeset patch # User Patrick Mezard # Date 1340121923 -7200 # Node ID 05ab164c6593d3d1ab0ef4cf5a705dce7a6db354 # Parent 258169d3428be34ac7f75430fdd0794c269ffd2b obsolete: handle rebase --collapse Recording obsolete in concludenode() did not work for --collapse because only the first revision was passed to the call. The new strategy is to track the rebase state in defineparents() and concludenode() and to create markers only after a successful non-abort call. In theory, this should also fix --continue/--abort cases. The change in test-stabilize-order.t comes from concludenode() no longer creating obsolete marker. stabilize command was actually duplicating markers, once in concludenode(), once explicitely. diff -r 258169d3428b -r 05ab164c6593 hgext/obsolete.py --- a/hgext/obsolete.py Tue Jun 19 17:05:39 2012 +0200 +++ b/hgext/obsolete.py Tue Jun 19 18:05:23 2012 +0200 @@ -225,17 +225,23 @@ rebaseset = repo.revs('%ld - extinct()', rebaseset) return orig(repo, dest, rebaseset, *ags, **kws) +def defineparents(orig, repo, rev, target, state, *args, **kwargs): + rebasestate = getattr(repo, '_rebasestate', None) + if rebasestate is not None: + repo._rebasestate = dict(state) + repo._rebasetarget = target + return orig(repo, rev, target, state, *args, **kwargs) -def concludenode(orig, repo, rev, *args, **kwargs): +def concludenode(orig, repo, rev, p1, *args, **kwargs): """wrapper for rebase 's concludenode that set obsolete relation""" - newrev = orig(repo, rev, *args, **kwargs) - oldnode = repo[rev].node() - if newrev is not None: - newnode = repo[newrev].node() - else: - # Revision was emptied and removed, there is no successor. - newnode = nullid - repo.addobsolete(newnode, oldnode) + newrev = orig(repo, rev, p1, *args, **kwargs) + rebasestate = getattr(repo, '_rebasestate', None) + if rebasestate is not None: + if newrev is not None: + nrev = repo[newrev].rev() + else: + nrev = p1 + repo._rebasestate[rev] = nrev return newrev def cmdrebase(orig, ui, repo, *args, **kwargs): @@ -244,8 +250,45 @@ 'extension'), hint=_("see 'hg help obsolete'")) kwargs = dict(kwargs) kwargs['keep'] = True - return orig(ui, repo, *args, **kwargs) + # We want to mark rebased revision as obsolete and set their + # replacements if any. Doing it in concludenode() prevents + # aborting the rebase, and is not called with all relevant + # revisions in --collapse case. Instead, we try to track the + # rebase state structure by sampling/updating it in + # defineparents() and concludenode(). The obsolete markers are + # added from this state after a successful call. + repo._rebasestate = {} + repo._rebasetarget = None + maxrev = len(repo) - 1 + try: + res = orig(ui, repo, *args, **kwargs) + if not res and not kwargs.get('abort') and repo._rebasetarget: + # We have to tell rewritten revisions from removed + # ones. When collapsing, removed revisions are considered + # to be collapsed onto the final one, while in the normal + # case their are marked obsolete without successor. + emptynode = nullid + if kwargs.get('collapse'): + emptynode = repo[max(repo._rebasestate.values())].node() + # Rebased revisions are assumed to be descendants of + # targetrev. If a source revision is mapped to targetrev + # or to another rebased revision, it must have been + # removed. + targetrev = repo[repo._rebasetarget].rev() + newrevs = set([targetrev]) + for rev, newrev in sorted(repo._rebasestate.items()): + oldnode = repo[rev].node() + if newrev not in newrevs and newrev >= 0: + newnode = repo[newrev].node() + newrevs.add(newrev) + else: + newnode = emptynode + repo.addobsolete(newnode, oldnode) + return res + finally: + delattr(repo, '_rebasestate') + delattr(repo, '_rebasetarget') def extsetup(ui): @@ -262,6 +305,7 @@ rebase = extensions.find('rebase') if rebase: extensions.wrapfunction(rebase, 'buildstate', buildstate) + extensions.wrapfunction(rebase, 'defineparents', defineparents) extensions.wrapfunction(rebase, 'concludenode', concludenode) extensions.wrapcommand(rebase.cmdtable, "rebase", cmdrebase) except KeyError: diff -r 258169d3428b -r 05ab164c6593 tests/test-obsolete-rebase.t --- a/tests/test-obsolete-rebase.t Tue Jun 19 17:05:39 2012 +0200 +++ b/tests/test-obsolete-rebase.t Tue Jun 19 18:05:23 2012 +0200 @@ -69,3 +69,38 @@ $ hg debugsuccessors 102a90ea7b4a 03f017c74faa 4e322f7ce8e3 000000000000 + +Test rebase --collapse + + $ hg up 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo c > c + $ hg ci -Am addc + adding c + created new head + $ echo c >> c + $ hg ci -m changec + $ hg rebase --collapse -d 1 + merging c + $ glog --hidden + @ 7:a7773ffa7edc@default(draft) Collapsed revision + | + | o 6:03f31481307a@default(secret) changec + | | + | o 5:076e9b2ffbe1@default(secret) addc + | | + | | o 4:4e322f7ce8e3@foo(secret) changea + | |/ + +---o 3:03f017c74faa@default(draft) addb + | | + | | o 2:102a90ea7b4a@default(secret) addb + | |/ + o | 1:540395c44225@default(draft) changea + |/ + o 0:07f494440405@default(draft) adda + + $ hg debugsuccessors + 03f31481307a a7773ffa7edc + 076e9b2ffbe1 a7773ffa7edc + 102a90ea7b4a 03f017c74faa + 4e322f7ce8e3 000000000000 diff -r 258169d3428b -r 05ab164c6593 tests/test-stabilize-order.t --- a/tests/test-stabilize-order.t Tue Jun 19 17:05:39 2012 +0200 +++ b/tests/test-stabilize-order.t Tue Jun 19 18:05:23 2012 +0200 @@ -102,11 +102,10 @@ $ diff -u successors.old successors.new --- successors.old* (glob) +++ successors.new* (glob) - @@ -1,5 +1,7 @@ + @@ -1,5 +1,6 @@ 3a4a591493f8 f5ff10856e5a 3ca0ded0dc50 ab8cbb6d87ff +7a7552255fb5 5e819fbb0d27 - +7a7552255fb5 5e819fbb0d27 93418d2c0979 3a4a591493f8 93418d2c0979 f5ff10856e5a ab8cbb6d87ff 6bf44048e43f