##// END OF EJS Templates
rebase: exclude descendants of obsoletes w/o a successor in dest (issue5300)...
Denis Laxalde -
r35049:a68c3420 default
parent child Browse files
Show More
@@ -179,6 +179,7 b' class rebaseruntime(object):'
179 # other extensions
179 # other extensions
180 self.keepopen = opts.get('keepopen', False)
180 self.keepopen = opts.get('keepopen', False)
181 self.obsoletenotrebased = {}
181 self.obsoletenotrebased = {}
182 self.obsoletewithoutsuccessorindestination = set()
182
183
183 @property
184 @property
184 def repo(self):
185 def repo(self):
@@ -311,9 +312,10 b' class rebaseruntime(object):'
311 if not self.ui.configbool('experimental', 'rebaseskipobsolete'):
312 if not self.ui.configbool('experimental', 'rebaseskipobsolete'):
312 return
313 return
313 obsoleteset = set(obsoleterevs)
314 obsoleteset = set(obsoleterevs)
314 self.obsoletenotrebased = _computeobsoletenotrebased(self.repo,
315 self.obsoletenotrebased, self.obsoletewithoutsuccessorindestination = \
315 obsoleteset, destmap)
316 _computeobsoletenotrebased(self.repo, obsoleteset, destmap)
316 skippedset = set(self.obsoletenotrebased)
317 skippedset = set(self.obsoletenotrebased)
318 skippedset.update(self.obsoletewithoutsuccessorindestination)
317 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
319 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
318
320
319 def _prepareabortorcontinue(self, isabort):
321 def _prepareabortorcontinue(self, isabort):
@@ -419,12 +421,26 b' class rebaseruntime(object):'
419 def _performrebasesubset(self, tr, subset, pos, total):
421 def _performrebasesubset(self, tr, subset, pos, total):
420 repo, ui, opts = self.repo, self.ui, self.opts
422 repo, ui, opts = self.repo, self.ui, self.opts
421 sortedrevs = repo.revs('sort(%ld, -topo)', subset)
423 sortedrevs = repo.revs('sort(%ld, -topo)', subset)
424 allowdivergence = self.ui.configbool(
425 'experimental', 'evolution.allowdivergence')
426 if not allowdivergence:
427 sortedrevs -= repo.revs(
428 'descendants(%ld) and not %ld',
429 self.obsoletewithoutsuccessorindestination,
430 self.obsoletewithoutsuccessorindestination,
431 )
422 for rev in sortedrevs:
432 for rev in sortedrevs:
423 dest = self.destmap[rev]
433 dest = self.destmap[rev]
424 ctx = repo[rev]
434 ctx = repo[rev]
425 desc = _ctxdesc(ctx)
435 desc = _ctxdesc(ctx)
426 if self.state[rev] == rev:
436 if self.state[rev] == rev:
427 ui.status(_('already rebased %s\n') % desc)
437 ui.status(_('already rebased %s\n') % desc)
438 elif (not allowdivergence
439 and rev in self.obsoletewithoutsuccessorindestination):
440 msg = _('note: not rebasing %s and its descendants as '
441 'this would cause divergence\n') % desc
442 repo.ui.status(msg)
443 self.skipped.add(rev)
428 elif rev in self.obsoletenotrebased:
444 elif rev in self.obsoletenotrebased:
429 succ = self.obsoletenotrebased[rev]
445 succ = self.obsoletenotrebased[rev]
430 if succ is None:
446 if succ is None:
@@ -1616,11 +1632,16 b' def _filterobsoleterevs(repo, revs):'
1616 return set(r for r in revs if repo[r].obsolete())
1632 return set(r for r in revs if repo[r].obsolete())
1617
1633
1618 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
1634 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
1619 """return a mapping obsolete => successor for all obsolete nodes to be
1635 """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
1620 rebased that have a successors in the destination
1636
1637 `obsoletenotrebased` is a mapping mapping obsolete => successor for all
1638 obsolete nodes to be rebased given in `rebaseobsrevs`.
1621
1639
1622 obsolete => None entries in the mapping indicate nodes with no successor"""
1640 `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
1641 without a successor in destination.
1642 """
1623 obsoletenotrebased = {}
1643 obsoletenotrebased = {}
1644 obsoletewithoutsuccessorindestination = set([])
1624
1645
1625 assert repo.filtername is None
1646 assert repo.filtername is None
1626 cl = repo.changelog
1647 cl = repo.changelog
@@ -1641,8 +1662,15 b' def _computeobsoletenotrebased(repo, reb'
1641 if cl.isancestor(succnode, destnode):
1662 if cl.isancestor(succnode, destnode):
1642 obsoletenotrebased[srcrev] = nodemap[succnode]
1663 obsoletenotrebased[srcrev] = nodemap[succnode]
1643 break
1664 break
1665 else:
1666 # If 'srcrev' has a successor in rebase set but none in
1667 # destination (which would be catched above), we shall skip it
1668 # and its descendants to avoid divergence.
1669 if any(nodemap[s] in destmap
1670 for s in successors if s != srcnode):
1671 obsoletewithoutsuccessorindestination.add(srcrev)
1644
1672
1645 return obsoletenotrebased
1673 return obsoletenotrebased, obsoletewithoutsuccessorindestination
1646
1674
1647 def summaryhook(ui, repo):
1675 def summaryhook(ui, repo):
1648 if not repo.vfs.exists('rebasestate'):
1676 if not repo.vfs.exists('rebasestate'):
@@ -987,6 +987,208 b' Create the changes that we will rebase'
987 rebasing 21:7bdc8a87673d "dummy change" (tip)
987 rebasing 21:7bdc8a87673d "dummy change" (tip)
988 $ cd ..
988 $ cd ..
989
989
990 Divergence cases due to obsolete changesets
991 -------------------------------------------
992
993 We should ignore branches with unstable changesets when they are based on an
994 obsolete changeset which successor is in rebase set.
995
996 $ hg init divergence
997 $ cd divergence
998 $ cat >> .hg/hgrc << EOF
999 > [extensions]
1000 > strip =
1001 > [alias]
1002 > strip = strip --no-backup --quiet
1003 > [templates]
1004 > instabilities = '{rev}:{node|short} {desc|firstline}{if(instabilities," ({instabilities})")}\n'
1005 > EOF
1006
1007 $ hg debugdrawdag <<EOF
1008 > e f
1009 > | |
1010 > d' d # replace: d -> d'
1011 > \ /
1012 > c
1013 > |
1014 > x b
1015 > \|
1016 > a
1017 > EOF
1018 $ hg log -G -r 'a'::
1019 o 7:1143e9adc121 f
1020 |
1021 | o 6:d60ebfa0f1cb e
1022 | |
1023 | o 5:027ad6c5830d d'
1024 | |
1025 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1026 |/
1027 o 3:a82ac2b38757 c
1028 |
1029 | o 2:630d7c95eff7 x
1030 | |
1031 o | 1:488e1b7e7341 b
1032 |/
1033 o 0:b173517d0057 a
1034
1035
1036 Changeset d and its descendants are excluded to avoid divergence of d, which
1037 would occur because the successor of d (d') is also in rebaseset. As a
1038 consequence f (descendant of d) is left behind.
1039
1040 $ hg rebase -b 'e' -d 'x'
1041 rebasing 1:488e1b7e7341 "b" (b)
1042 rebasing 3:a82ac2b38757 "c" (c)
1043 rebasing 5:027ad6c5830d "d'" (d')
1044 rebasing 6:d60ebfa0f1cb "e" (e)
1045 note: not rebasing 4:76be324c128b "d" (d) and its descendants as this would cause divergence
1046 $ hg log -G -r 'a'::
1047 o 11:eb6d63fc4ed5 e
1048 |
1049 o 10:44d8c724a70c d'
1050 |
1051 o 9:d008e6b4d3fd c
1052 |
1053 o 8:67e8f4a16c49 b
1054 |
1055 | o 7:1143e9adc121 f
1056 | |
1057 | | x 6:d60ebfa0f1cb e (rewritten using rebase as 11:eb6d63fc4ed5)
1058 | | |
1059 | | x 5:027ad6c5830d d' (rewritten using rebase as 10:44d8c724a70c)
1060 | | |
1061 | x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1062 | |/
1063 | x 3:a82ac2b38757 c (rewritten using rebase as 9:d008e6b4d3fd)
1064 | |
1065 o | 2:630d7c95eff7 x
1066 | |
1067 | x 1:488e1b7e7341 b (rewritten using rebase as 8:67e8f4a16c49)
1068 |/
1069 o 0:b173517d0057 a
1070
1071 $ hg strip -r 8:
1072
1073 If the rebase set has an obsolete (d) with a successor (d') outside the rebase
1074 set and none in destination, we still get the divergence warning.
1075 By allowing divergence, we can perform the rebase.
1076
1077 $ hg rebase -r 'c'::'f' -d 'x'
1078 abort: this rebase will cause divergences from: 76be324c128b
1079 (to force the rebase please set experimental.evolution.allowdivergence=True)
1080 [255]
1081 $ hg rebase --config experimental.evolution.allowdivergence=true -r 'c'::'f' -d 'x'
1082 rebasing 3:a82ac2b38757 "c" (c)
1083 rebasing 4:76be324c128b "d" (d)
1084 rebasing 7:1143e9adc121 "f" (f tip)
1085 $ hg log -G -r 'a':: -T instabilities
1086 o 10:e1744ea07510 f
1087 |
1088 o 9:e2b36ea9a0a0 d (content-divergent)
1089 |
1090 o 8:6a0376de376e c
1091 |
1092 | x 7:1143e9adc121 f
1093 | |
1094 | | o 6:d60ebfa0f1cb e (orphan)
1095 | | |
1096 | | o 5:027ad6c5830d d' (orphan content-divergent)
1097 | | |
1098 | x | 4:76be324c128b d
1099 | |/
1100 | x 3:a82ac2b38757 c
1101 | |
1102 o | 2:630d7c95eff7 x
1103 | |
1104 | o 1:488e1b7e7341 b
1105 |/
1106 o 0:b173517d0057 a
1107
1108 $ hg strip -r 8:
1109
1110 (Not skipping obsoletes means that divergence is allowed.)
1111
1112 $ hg rebase --config experimental.rebaseskipobsolete=false -r 'c'::'f' -d 'x'
1113 rebasing 3:a82ac2b38757 "c" (c)
1114 rebasing 4:76be324c128b "d" (d)
1115 rebasing 7:1143e9adc121 "f" (f tip)
1116
1117 $ hg strip -r 0:
1118
1119 Similar test on a more complex graph
1120
1121 $ hg debugdrawdag <<EOF
1122 > g
1123 > |
1124 > f e
1125 > | |
1126 > e' d # replace: e -> e'
1127 > \ /
1128 > c
1129 > |
1130 > x b
1131 > \|
1132 > a
1133 > EOF
1134 $ hg log -G -r 'a':
1135 o 8:2876ce66c6eb g
1136 |
1137 | o 7:3ffec603ab53 f
1138 | |
1139 x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1140 | |
1141 | o 5:63324dc512ea e'
1142 | |
1143 o | 4:76be324c128b d
1144 |/
1145 o 3:a82ac2b38757 c
1146 |
1147 | o 2:630d7c95eff7 x
1148 | |
1149 o | 1:488e1b7e7341 b
1150 |/
1151 o 0:b173517d0057 a
1152
1153 $ hg rebase -b 'f' -d 'x'
1154 rebasing 1:488e1b7e7341 "b" (b)
1155 rebasing 3:a82ac2b38757 "c" (c)
1156 rebasing 5:63324dc512ea "e'" (e')
1157 rebasing 7:3ffec603ab53 "f" (f)
1158 rebasing 4:76be324c128b "d" (d)
1159 note: not rebasing 6:e36fae928aec "e" (e) and its descendants as this would cause divergence
1160 $ hg log -G -r 'a':
1161 o 13:a1707a5b7c2c d
1162 |
1163 | o 12:ef6251596616 f
1164 | |
1165 | o 11:b6f172e64af9 e'
1166 |/
1167 o 10:d008e6b4d3fd c
1168 |
1169 o 9:67e8f4a16c49 b
1170 |
1171 | o 8:2876ce66c6eb g
1172 | |
1173 | | x 7:3ffec603ab53 f (rewritten using rebase as 12:ef6251596616)
1174 | | |
1175 | x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1176 | | |
1177 | | x 5:63324dc512ea e' (rewritten using rebase as 11:b6f172e64af9)
1178 | | |
1179 | x | 4:76be324c128b d (rewritten using rebase as 13:a1707a5b7c2c)
1180 | |/
1181 | x 3:a82ac2b38757 c (rewritten using rebase as 10:d008e6b4d3fd)
1182 | |
1183 o | 2:630d7c95eff7 x
1184 | |
1185 | x 1:488e1b7e7341 b (rewritten using rebase as 9:67e8f4a16c49)
1186 |/
1187 o 0:b173517d0057 a
1188
1189
1190 $ cd ..
1191
990 Rebase merge where successor of one parent is equal to destination (issue5198)
1192 Rebase merge where successor of one parent is equal to destination (issue5198)
991
1193
992 $ hg init p1-succ-is-dest
1194 $ hg init p1-succ-is-dest
General Comments 0
You need to be logged in to leave comments. Login now