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