##// END OF EJS Templates
rebase: move working parent and bookmark for obsoleted revs (BC)...
Jun Wu -
r34010:9422107a default
parent child Browse files
Show More
@@ -327,11 +327,7 b' class rebaseruntime(object):'
327 " unrebased descendants"),
327 " unrebased descendants"),
328 hint=_('use --keep to keep original changesets'))
328 hint=_('use --keep to keep original changesets'))
329
329
330 obsrevs = _filterobsoleterevs(self.repo, rebaseset)
330 result = buildstate(self.repo, destmap, self.collapsef)
331 self._handleskippingobsolete(obsrevs, destmap)
332
333 result = buildstate(self.repo, destmap, self.collapsef,
334 self.obsoletenotrebased)
335
331
336 if not result:
332 if not result:
337 # Empty state built, nothing to rebase
333 # Empty state built, nothing to rebase
@@ -375,6 +371,10 b' class rebaseruntime(object):'
375 raise error.Abort(_('cannot collapse multiple named '
371 raise error.Abort(_('cannot collapse multiple named '
376 'branches'))
372 'branches'))
377
373
374 # Calculate self.obsoletenotrebased
375 obsrevs = _filterobsoleterevs(self.repo, self.state)
376 self._handleskippingobsolete(obsrevs, self.destmap)
377
378 # Keep track of the active bookmarks in order to reset them later
378 # Keep track of the active bookmarks in order to reset them later
379 self.activebookmark = self.activebookmark or repo._activebookmark
379 self.activebookmark = self.activebookmark or repo._activebookmark
380 if self.activebookmark:
380 if self.activebookmark:
@@ -401,13 +401,34 b' class rebaseruntime(object):'
401 desc = _ctxdesc(ctx)
401 desc = _ctxdesc(ctx)
402 if self.state[rev] == rev:
402 if self.state[rev] == rev:
403 ui.status(_('already rebased %s\n') % desc)
403 ui.status(_('already rebased %s\n') % desc)
404 elif rev in self.obsoletenotrebased:
405 succ = self.obsoletenotrebased[rev]
406 if succ is None:
407 msg = _('note: not rebasing %s, it has no '
408 'successor\n') % desc
409 else:
410 succctx = repo[succ]
411 succdesc = '%d:%s "%s"' % (
412 succctx.rev(), succctx,
413 succctx.description().split('\n', 1)[0])
414 msg = (_('note: not rebasing %s, already in '
415 'destination as %s\n') % (desc, succdesc))
416 repo.ui.status(msg)
417 # Make clearrebased aware state[rev] is not a true successor
418 self.skipped.add(rev)
419 # Record rev as moved to its desired destination in self.state.
420 # This helps bookmark and working parent movement.
421 dest = max(adjustdest(repo, rev, self.destmap, self.state,
422 self.skipped))
423 self.state[rev] = dest
404 elif self.state[rev] == revtodo:
424 elif self.state[rev] == revtodo:
405 pos += 1
425 pos += 1
406 ui.status(_('rebasing %s\n') % desc)
426 ui.status(_('rebasing %s\n') % desc)
407 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
427 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
408 _('changesets'), total)
428 _('changesets'), total)
409 p1, p2, base = defineparents(repo, rev, self.destmap,
429 p1, p2, base = defineparents(repo, rev, self.destmap,
410 self.state)
430 self.state, self.skipped,
431 self.obsoletenotrebased)
411 self.storestatus(tr=tr)
432 self.storestatus(tr=tr)
412 storecollapsemsg(repo, self.collapsemsg)
433 storecollapsemsg(repo, self.collapsemsg)
413 if len(repo[None].parents()) == 2:
434 if len(repo[None].parents()) == 2:
@@ -462,7 +483,8 b' class rebaseruntime(object):'
462 repo, ui, opts = self.repo, self.ui, self.opts
483 repo, ui, opts = self.repo, self.ui, self.opts
463 if self.collapsef and not self.keepopen:
484 if self.collapsef and not self.keepopen:
464 p1, p2, _base = defineparents(repo, min(self.state), self.destmap,
485 p1, p2, _base = defineparents(repo, min(self.state), self.destmap,
465 self.state)
486 self.state, self.skipped,
487 self.obsoletenotrebased)
466 editopt = opts.get('edit')
488 editopt = opts.get('edit')
467 editform = 'rebase.collapse'
489 editform = 'rebase.collapse'
468 if self.collapsemsg:
490 if self.collapsemsg:
@@ -935,7 +957,7 b' def rebasenode(repo, rev, p1, base, stat'
935 copies.duplicatecopies(repo, rev, p1rev, skiprev=dest)
957 copies.duplicatecopies(repo, rev, p1rev, skiprev=dest)
936 return stats
958 return stats
937
959
938 def adjustdest(repo, rev, destmap, state):
960 def adjustdest(repo, rev, destmap, state, skipped):
939 """adjust rebase destination given the current rebase state
961 """adjust rebase destination given the current rebase state
940
962
941 rev is what is being rebased. Return a list of two revs, which are the
963 rev is what is being rebased. Return a list of two revs, which are the
@@ -989,7 +1011,8 b' def adjustdest(repo, rev, destmap, state'
989 """
1011 """
990 # pick already rebased revs with same dest from state as interesting source
1012 # pick already rebased revs with same dest from state as interesting source
991 dest = destmap[rev]
1013 dest = destmap[rev]
992 source = [s for s, d in state.items() if d > 0 and destmap[s] == dest]
1014 source = [s for s, d in state.items()
1015 if d > 0 and destmap[s] == dest and s not in skipped]
993
1016
994 result = []
1017 result = []
995 for prev in repo.changelog.parentrevs(rev):
1018 for prev in repo.changelog.parentrevs(rev):
@@ -1037,7 +1060,7 b' def successorrevs(repo, rev):'
1037 if s in nodemap:
1060 if s in nodemap:
1038 yield nodemap[s]
1061 yield nodemap[s]
1039
1062
1040 def defineparents(repo, rev, destmap, state):
1063 def defineparents(repo, rev, destmap, state, skipped, obsskipped):
1041 """Return new parents and optionally a merge base for rev being rebased
1064 """Return new parents and optionally a merge base for rev being rebased
1042
1065
1043 The destination specified by "dest" cannot always be used directly because
1066 The destination specified by "dest" cannot always be used directly because
@@ -1064,7 +1087,7 b' def defineparents(repo, rev, destmap, st'
1064 dest = destmap[rev]
1087 dest = destmap[rev]
1065 oldps = repo.changelog.parentrevs(rev) # old parents
1088 oldps = repo.changelog.parentrevs(rev) # old parents
1066 newps = [nullrev, nullrev] # new parents
1089 newps = [nullrev, nullrev] # new parents
1067 dests = adjustdest(repo, rev, destmap, state) # adjusted destinations
1090 dests = adjustdest(repo, rev, destmap, state, skipped)
1068 bases = list(oldps) # merge base candidates, initially just old parents
1091 bases = list(oldps) # merge base candidates, initially just old parents
1069
1092
1070 if all(r == nullrev for r in oldps[1:]):
1093 if all(r == nullrev for r in oldps[1:]):
@@ -1191,7 +1214,8 b' def defineparents(repo, rev, destmap, st'
1191 # If those revisions are covered by rebaseset, the result is good.
1214 # If those revisions are covered by rebaseset, the result is good.
1192 # A merge in rebaseset would be considered to cover its ancestors.
1215 # A merge in rebaseset would be considered to cover its ancestors.
1193 if siderevs:
1216 if siderevs:
1194 rebaseset = [r for r, d in state.items() if d > 0]
1217 rebaseset = [r for r, d in state.items()
1218 if d > 0 and r not in obsskipped]
1195 merges = [r for r in rebaseset
1219 merges = [r for r in rebaseset
1196 if cl.parentrevs(r)[1] != nullrev]
1220 if cl.parentrevs(r)[1] != nullrev]
1197 unwanted[i] = list(repo.revs('%ld - (::%ld) - %ld',
1221 unwanted[i] = list(repo.revs('%ld - (::%ld) - %ld',
@@ -1408,7 +1432,7 b' def sortsource(destmap):'
1408 srcset -= set(result)
1432 srcset -= set(result)
1409 yield result
1433 yield result
1410
1434
1411 def buildstate(repo, destmap, collapse, obsoletenotrebased):
1435 def buildstate(repo, destmap, collapse):
1412 '''Define which revisions are going to be rebased and where
1436 '''Define which revisions are going to be rebased and where
1413
1437
1414 repo: repo
1438 repo: repo
@@ -1469,23 +1493,6 b' def buildstate(repo, destmap, collapse, '
1469 # if all parents of this revision are done, then so is this revision
1493 # if all parents of this revision are done, then so is this revision
1470 if parents and all((state.get(p) == p for p in parents)):
1494 if parents and all((state.get(p) == p for p in parents)):
1471 state[rev] = rev
1495 state[rev] = rev
1472 unfi = repo.unfiltered()
1473 for r in obsoletenotrebased:
1474 desc = _ctxdesc(unfi[r])
1475 succ = obsoletenotrebased[r]
1476 if succ is None:
1477 msg = _('note: not rebasing %s, it has no successor\n') % desc
1478 del state[r]
1479 del destmap[r]
1480 else:
1481 destctx = unfi[succ]
1482 destdesc = '%d:%s "%s"' % (destctx.rev(), destctx,
1483 destctx.description().split('\n', 1)[0])
1484 msg = (_('note: not rebasing %s, already in destination as %s\n')
1485 % (desc, destdesc))
1486 del state[r]
1487 del destmap[r]
1488 repo.ui.status(msg)
1489 return originalwd, destmap, state
1496 return originalwd, destmap, state
1490
1497
1491 def clearrebased(ui, repo, destmap, state, skipped, collapsedas=None):
1498 def clearrebased(ui, repo, destmap, state, skipped, collapsedas=None):
@@ -205,8 +205,8 b' More complex case where part of the reba'
205 o 0:cd010b8cd998 A
205 o 0:cd010b8cd998 A
206
206
207 $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True
207 $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True
208 rebasing 8:8877864f1edb "B"
208 note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 "D"
209 note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 "D"
209 rebasing 8:8877864f1edb "B"
210 rebasing 10:5ae4c968c6ac "C"
210 rebasing 10:5ae4c968c6ac "C"
211 $ hg debugobsolete
211 $ hg debugobsolete
212 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob)
212 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob)
@@ -736,8 +736,8 b' Even when the chain include missing node'
736 $ hg debugobsolete `hg log -r 7 -T '{node}\n'` --config experimental.stabilization=all
736 $ hg debugobsolete `hg log -r 7 -T '{node}\n'` --config experimental.stabilization=all
737 obsoleted 1 changesets
737 obsoleted 1 changesets
738 $ hg rebase -d 6 -r "4::"
738 $ hg rebase -d 6 -r "4::"
739 rebasing 4:ff2c4d47b71d "C"
739 note: not rebasing 7:360bbaa7d3ce "O", it has no successor
740 note: not rebasing 7:360bbaa7d3ce "O", it has no successor
740 rebasing 4:ff2c4d47b71d "C"
741 rebasing 8:8d47583e023f "P" (tip)
741 rebasing 8:8d47583e023f "P" (tip)
742
742
743 If all the changeset to be rebased are obsolete and present in the destination, we
743 If all the changeset to be rebased are obsolete and present in the destination, we
@@ -769,10 +769,8 b' should display a friendly error message'
769 If a rebase is going to create divergence, it should abort
769 If a rebase is going to create divergence, it should abort
770
770
771 $ hg log -G
771 $ hg log -G
772 @ 11:f44da1f4954c nonrelevant
772 @ 10:121d9e3bc4c6 P
773 |
773 |
774 | o 10:121d9e3bc4c6 P
775 |/
776 o 9:4be60e099a77 C
774 o 9:4be60e099a77 C
777 |
775 |
778 o 6:9c48361117de D
776 o 6:9c48361117de D
@@ -904,7 +902,6 b' Create the changes that we will rebase'
904 |
902 |
905 ~
903 ~
906 $ hg rebase -r ".^^ + .^ + ." -d 19
904 $ hg rebase -r ".^^ + .^ + ." -d 19
907 note: not rebasing 21:8b31da3c4919 "dummy change", already in destination as 19:601db7a18f51 "dummy change successor"
908 rebasing 20:b82fb57ea638 "willconflict second version"
905 rebasing 20:b82fb57ea638 "willconflict second version"
909 merging willconflict
906 merging willconflict
910 warning: conflicts while merging willconflict! (edit, then use 'hg resolve --mark')
907 warning: conflicts while merging willconflict! (edit, then use 'hg resolve --mark')
@@ -916,6 +913,7 b' Create the changes that we will rebase'
916 continue: hg rebase --continue
913 continue: hg rebase --continue
917 $ hg rebase --continue
914 $ hg rebase --continue
918 rebasing 20:b82fb57ea638 "willconflict second version"
915 rebasing 20:b82fb57ea638 "willconflict second version"
916 note: not rebasing 21:8b31da3c4919 "dummy change", already in destination as 19:601db7a18f51 "dummy change successor"
919 rebasing 22:7bdc8a87673d "dummy change" (tip)
917 rebasing 22:7bdc8a87673d "dummy change" (tip)
920 $ cd ..
918 $ cd ..
921
919
@@ -1062,8 +1060,8 b' Rebase merge where successor of one pare'
1062 > EOF
1060 > EOF
1063
1061
1064 $ hg rebase -d C -b F
1062 $ hg rebase -d C -b F
1063 rebasing 2:b18e25de2cf5 "D" (D)
1065 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B"
1064 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B"
1066 rebasing 2:b18e25de2cf5 "D" (D)
1067 rebasing 5:66f1a38021c9 "F" (F tip)
1065 rebasing 5:66f1a38021c9 "F" (F tip)
1068 note: rebase of 5:66f1a38021c9 created no changes to commit
1066 note: rebase of 5:66f1a38021c9 created no changes to commit
1069 $ hg log -G
1067 $ hg log -G
@@ -1179,8 +1177,8 b' parent moves as requested.'
1179 > A B C # D/D = D
1177 > A B C # D/D = D
1180 > EOS
1178 > EOS
1181 $ hg rebase -r B+A+D -d Z
1179 $ hg rebase -r B+A+D -d Z
1180 rebasing 0:426bada5c675 "A" (A)
1182 note: not rebasing 1:fc2b737bb2e5 "B" (B), already in destination as 2:96cc3511f894 "C"
1181 note: not rebasing 1:fc2b737bb2e5 "B" (B), already in destination as 2:96cc3511f894 "C"
1183 rebasing 0:426bada5c675 "A" (A)
1184 rebasing 3:b8ed089c80ad "D" (D)
1182 rebasing 3:b8ed089c80ad "D" (D)
1185
1183
1186 $ rm .hg/localtags
1184 $ rm .hg/localtags
@@ -1226,17 +1224,46 b' equivalents in destination'
1226 2:1e9a3c00cbe9 b (no-eol)
1224 2:1e9a3c00cbe9 b (no-eol)
1227 $ hg rebase -r 2 -d 3 --config experimental.stabilization.track-operation=1
1225 $ hg rebase -r 2 -d 3 --config experimental.stabilization.track-operation=1
1228 note: not rebasing 2:1e9a3c00cbe9 "b" (mybook), already in destination as 3:be1832deae9a "b"
1226 note: not rebasing 2:1e9a3c00cbe9 "b" (mybook), already in destination as 3:be1832deae9a "b"
1229 Check that working directory was not updated to rev 3 because rev 2 was skipped
1227 Check that working directory and bookmark was updated to rev 3 although rev 2
1230 during the rebase operation
1228 was skipped
1231 $ hg log -r .
1229 $ hg log -r .
1232 2:1e9a3c00cbe9 b (no-eol)
1230 3:be1832deae9a b (no-eol)
1233
1234 Check that bookmark was not moved to rev 3 if rev 2 was skipped during the
1235 rebase operation. This makes sense because if rev 2 has a successor, the
1236 operation generating that successor (ex. rebase) should be responsible for
1237 moving bookmarks. If the bookmark is on a precursor, like rev 2, that means the
1238 user manually moved it back. In that case we should not move it again.
1239 $ hg bookmarks
1231 $ hg bookmarks
1240 mybook 2:1e9a3c00cbe9
1232 mybook 3:be1832deae9a
1241 $ hg debugobsolete --rev tip
1233 $ hg debugobsolete --rev tip
1242 1e9a3c00cbe90d236ac05ef61efcc5e40b7412bc be1832deae9ac531caa7438b8dcf6055a122cd8e 0 (*) {'user': 'test'} (glob)
1234 1e9a3c00cbe90d236ac05ef61efcc5e40b7412bc be1832deae9ac531caa7438b8dcf6055a122cd8e 0 (*) {'user': 'test'} (glob)
1235
1236 Obsoleted working parent and bookmark could be moved if an ancestor of working
1237 parent gets moved:
1238
1239 $ hg init $TESTTMP/ancestor-wd-move
1240 $ cd $TESTTMP/ancestor-wd-move
1241 $ hg debugdrawdag <<'EOS'
1242 > E D1 # rebase: D1 -> D2
1243 > | |
1244 > | C
1245 > D2 |
1246 > | B
1247 > |/
1248 > A
1249 > EOS
1250 $ hg update D1 -q
1251 $ hg bookmark book -i
1252 $ hg rebase -r B+D1 -d E
1253 rebasing 1:112478962961 "B" (B)
1254 note: not rebasing 5:15ecf15e0114 "D1" (D1 tip book), already in destination as 2:0807738e0be9 "D2"
1255 $ hg log -G -T '{desc} {bookmarks}'
1256 @ B book
1257 |
1258 | x D1
1259 | |
1260 o | E
1261 | |
1262 | o C
1263 | |
1264 o | D2
1265 | |
1266 | x B
1267 |/
1268 o A
1269
General Comments 0
You need to be logged in to leave comments. Login now