Skip to content
Snippets Groups Projects
Commit 7159426c8d13 authored by Pierre-Yves David's avatar Pierre-Yves David
Browse files

rebase: properly handle unrebased revision between rebased one

With rebase taking multiple roots it is possible to have revision in the "rebase
domain" not rebased themself. We do not want rebased revision above them to be
detached. We want such revision to be rebased on the nearest rebased ancestors.
This allows to preserve the topology of the rebase set as much a possible

To achieve this we introduce a new state `revignored` which informs
`defineparents` of the situation.

The test in `test-rebase-obsolete.t` was actually wrote and his now fixed.
parent c83d36b81df1
No related branches found
No related tags found
No related merge requests found
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
import os, errno import os, errno
nullmerge = -2 nullmerge = -2
revignored = -3
cmdtable = {} cmdtable = {}
command = cmdutil.command(cmdtable) command = cmdutil.command(cmdtable)
...@@ -392,6 +393,15 @@ ...@@ -392,6 +393,15 @@
# have to allow merging with it. # have to allow merging with it.
return merge.update(repo, rev, True, True, False, base, collapse) return merge.update(repo, rev, True, True, False, base, collapse)
def nearestrebased(repo, rev, state):
"""return the nearest ancestors of rev in the rebase result"""
rebased = [r for r in state if state[r] > nullmerge]
candidates = repo.revs('max(%ld and (::%d))', rebased, rev)
if candidates:
return state[candidates[0]]
else:
return None
def defineparents(repo, rev, target, state, targetancestors): def defineparents(repo, rev, target, state, targetancestors):
'Return the new parent relationship of the revision that will be rebased' 'Return the new parent relationship of the revision that will be rebased'
parents = repo[rev].parents() parents = repo[rev].parents()
...@@ -403,6 +413,10 @@ ...@@ -403,6 +413,10 @@
elif P1n in state: elif P1n in state:
if state[P1n] == nullmerge: if state[P1n] == nullmerge:
p1 = target p1 = target
elif state[P1n] == revignored:
p1 = nearestrebased(repo, P1n, state)
if p1 is None:
p1 = target
else: else:
p1 = state[P1n] p1 = state[P1n]
else: # P1n external else: # P1n external
...@@ -415,6 +429,11 @@ ...@@ -415,6 +429,11 @@
if P2n in state: if P2n in state:
if p1 == target: # P1n in targetancestors or external if p1 == target: # P1n in targetancestors or external
p1 = state[P2n] p1 = state[P2n]
elif state[P2n] == revignored:
p2 = nearestrebased(repo, P2n, state)
if p2 is None:
# no ancestors rebased yet, detach
p2 = target
else: else:
p2 = state[P2n] p2 = state[P2n]
else: # P2n external else: # P2n external
...@@ -532,5 +551,7 @@ ...@@ -532,5 +551,7 @@
keepbranches = bool(int(l)) keepbranches = bool(int(l))
else: else:
oldrev, newrev = l.split(':') oldrev, newrev = l.split(':')
if newrev != str(nullmerge): if newrev in (str(nullmerge), str(revignored)):
state[repo[oldrev].rev()] = int(newrev)
else:
state[repo[oldrev].rev()] = repo[newrev].rev() state[repo[oldrev].rev()] = repo[newrev].rev()
...@@ -536,6 +557,4 @@ ...@@ -536,6 +557,4 @@
state[repo[oldrev].rev()] = repo[newrev].rev() state[repo[oldrev].rev()] = repo[newrev].rev()
else:
state[repo[oldrev].rev()] = int(newrev)
skipped = set() skipped = set()
# recompute the set of skipped revs # recompute the set of skipped revs
if not collapse: if not collapse:
...@@ -658,6 +677,15 @@ ...@@ -658,6 +677,15 @@
for r in detachset: for r in detachset:
if r not in state: if r not in state:
state[r] = nullmerge state[r] = nullmerge
if len(roots) > 1:
# If we have multiple roots, we may have "hole" in the rebase set.
# Rebase roots that descend from those "hole" should not be detached as
# other root are. We use the special `revignored` to inform rebase that
# the revision should be ignored but that `defineparent` should search
# a rebase destination that make sense regarding rebaset topology.
rebasedomain = set(repo.revs('%ld::%ld', rebaseset, rebaseset))
for ignored in set(rebasedomain) - set(rebaseset):
state[ignored] = revignored
return repo['.'].rev(), dest.rev(), state return repo['.'].rev(), dest.rev(), state
def clearrebased(ui, repo, state, skipped, collapsedas=None): def clearrebased(ui, repo, state, skipped, collapsedas=None):
......
...@@ -366,6 +366,6 @@ ...@@ -366,6 +366,6 @@
$ hg rebase --dest 4 --rev '7+11+9' $ hg rebase --dest 4 --rev '7+11+9'
$ hg log -G $ hg log -G
@ 14:00891d85fcfc C @ 14:1e8370e38cca C
| |
| o 13:102b4c1d889b D | o 13:102b4c1d889b D
...@@ -370,7 +370,7 @@ ...@@ -370,7 +370,7 @@
| |
| o 13:102b4c1d889b D | o 13:102b4c1d889b D
|/ | |
| o 12:bfe264faf697 H o | 12:bfe264faf697 H
|/ |/
| o 10:7c6027df6a99 B | o 10:7c6027df6a99 B
| | | |
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment