# HG changeset patch # User Patrick Mezard # Date 1340301537 -7200 # Node ID f597421662f7b2cab13746ce3a260a79812dcc03 # Parent 590ac023c53603d86d86c8a06ecfd1fffba24ada obsolete: unify collapsed revisions markers handling When collapsing A, B and C into D, amend was registering: A -> D B -> D A -> B C -> D A -> C while the rebase wrapper was doing: A -> D B -> D C -> D At this point, I have no argument to favor one or another or even a new one like: A -> B B -> C C -> D so I am aligning the rebase implementation on the older amend one. At least we can now change them all at once. diff -r 590ac023c536 -r f597421662f7 hgext/evolve.py --- a/hgext/evolve.py Thu Jun 21 19:24:19 2012 +0200 +++ b/hgext/evolve.py Thu Jun 21 19:58:57 2012 +0200 @@ -142,10 +142,8 @@ bookmarks.write(repo) # add evolution metadata - repo.addobsolete(new.node(), old.node()) - for u in updates: - repo.addobsolete(u.node(), old.node()) - repo.addobsolete(new.node(), u.node()) + collapsed = set([u.node() for u in updates] + [old.node()]) + repo.addcollapsedobsolete(collapsed, new.node()) oldbookmarks = repo.nodebookmarks(old.node()) for book in oldbookmarks: repo._bookmarks[book] = new.node() diff -r 590ac023c536 -r f597421662f7 hgext/obsolete.py --- a/hgext/obsolete.py Thu Jun 21 19:24:19 2012 +0200 +++ b/hgext/obsolete.py Thu Jun 21 19:58:57 2012 +0200 @@ -267,27 +267,34 @@ repo._rebasestate = dict(p for p in repo._rebasestate.iteritems() if p[1] >= 0) if not res and not kwargs.get('abort') and repo._rebasestate: - # 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]) + replacements = {} for rev, newrev in sorted(repo._rebasestate.items()): oldnode = repo[rev].node() if newrev not in newrevs: newnode = repo[newrev].node() newrevs.add(newrev) else: - newnode = emptynode - repo.addobsolete(newnode, oldnode) + newnode = nullid + replacements[oldnode] = newnode + + if kwargs.get('collapse'): + newnodes = set(n for n in replacements.values() if n != nullid) + if newnodes: + # Collapsing into more than one revision? + assert len(newnodes) == 1, newnodes + newnode = newnodes.pop() + else: + newnode = nullid + repo.addcollapsedobsolete(replacements, newnode) + else: + for oldnode, newnode in replacements.iteritems(): + repo.addobsolete(newnode, oldnode) return res finally: delattr(repo, '_rebasestate') @@ -813,6 +820,17 @@ finally: lock.release() + def addcollapsedobsolete(self, oldnodes, newnode): + """Mark oldnodes as collapsed into newnode.""" + # Assume oldnodes are all descendants of a single rev + rootrevs = self.revs('roots(%ln)', oldnodes) + assert len(rootrevs) == 1, rootrevs + rootnode = self[rootrevs[0]].node() + for n in oldnodes: + if n != rootnode: + self.addobsolete(n, rootnode) + self.addobsolete(newnode, n) + def _turn_extinct_secret(self): """ensure all extinct changeset are secret""" self._clearobsoletecache() diff -r 590ac023c536 -r f597421662f7 tests/test-obsolete-rebase.t --- a/tests/test-obsolete-rebase.t Thu Jun 21 19:24:19 2012 +0200 +++ b/tests/test-obsolete-rebase.t Thu Jun 21 19:58:57 2012 +0200 @@ -109,6 +109,7 @@ $ hg debugsuccessors 03f31481307a a7773ffa7edc + 076e9b2ffbe1 03f31481307a 076e9b2ffbe1 a7773ffa7edc 4e322f7ce8e3 000000000000 98e4a024635e 9c5494949763 @@ -176,8 +177,9 @@ $ diff -u ../successors.old ../successors.new --- ../successors.old* (glob) +++ ../successors.new* (glob) - @@ -1,4 +1,6 @@ + @@ -1,5 +1,7 @@ 03f31481307a a7773ffa7edc + 076e9b2ffbe1 03f31481307a 076e9b2ffbe1 a7773ffa7edc +4b9d80f48523 1951ead97108 4e322f7ce8e3 000000000000