Mercurial > evolve
changeset 298:f597421662f7
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.
author | Patrick Mezard <patrick@mezard.eu> |
---|---|
date | Thu, 21 Jun 2012 19:58:57 +0200 |
parents | 590ac023c536 |
children | eda6491ca269 |
files | hgext/evolve.py hgext/obsolete.py tests/test-obsolete-rebase.t |
diffstat | 3 files changed, 32 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- 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()
--- 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()
--- 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