Show More
@@ -26,6 +26,7 b' import os, errno' | |||||
26 | revtodo = -1 |
|
26 | revtodo = -1 | |
27 | nullmerge = -2 |
|
27 | nullmerge = -2 | |
28 | revignored = -3 |
|
28 | revignored = -3 | |
|
29 | revprecursor = -4 | |||
29 |
|
30 | |||
30 | cmdtable = {} |
|
31 | cmdtable = {} | |
31 | command = cmdutil.command(cmdtable) |
|
32 | command = cmdutil.command(cmdtable) | |
@@ -333,7 +334,20 b' def rebase(ui, repo, **opts):' | |||||
333 | " unrebased descendants"), |
|
334 | " unrebased descendants"), | |
334 | hint=_('use --keep to keep original changesets')) |
|
335 | hint=_('use --keep to keep original changesets')) | |
335 |
|
336 | |||
336 | result = buildstate(repo, dest, rebaseset, collapsef) |
|
337 | obsoletenotrebased = {} | |
|
338 | if ui.configbool('experimental', 'rebaseskipobsolete'): | |||
|
339 | rebasesetrevs = set(rebaseset) | |||
|
340 | obsoletenotrebased = _computeobsoletenotrebased(repo, | |||
|
341 | rebasesetrevs, | |||
|
342 | dest) | |||
|
343 | ||||
|
344 | # - plain prune (no successor) changesets are rebased | |||
|
345 | # - split changesets are not rebased if at least one of the | |||
|
346 | # changeset resulting from the split is an ancestor of dest | |||
|
347 | rebaseset = rebasesetrevs - set(obsoletenotrebased) | |||
|
348 | result = buildstate(repo, dest, rebaseset, collapsef, | |||
|
349 | obsoletenotrebased) | |||
|
350 | ||||
337 | if not result: |
|
351 | if not result: | |
338 | # Empty state built, nothing to rebase |
|
352 | # Empty state built, nothing to rebase | |
339 | ui.status(_('nothing to rebase\n')) |
|
353 | ui.status(_('nothing to rebase\n')) | |
@@ -439,6 +453,12 b' def rebase(ui, repo, **opts):' | |||||
439 | ui.debug('ignoring null merge rebase of %s\n' % rev) |
|
453 | ui.debug('ignoring null merge rebase of %s\n' % rev) | |
440 | elif state[rev] == revignored: |
|
454 | elif state[rev] == revignored: | |
441 | ui.status(_('not rebasing ignored %s\n') % desc) |
|
455 | ui.status(_('not rebasing ignored %s\n') % desc) | |
|
456 | elif state[rev] == revprecursor: | |||
|
457 | targetctx = repo[obsoletenotrebased[rev]] | |||
|
458 | desctarget = '%d:%s "%s"' % (targetctx.rev(), targetctx, | |||
|
459 | targetctx.description().split('\n', 1)[0]) | |||
|
460 | msg = _('note: not rebasing %s, already in destination as %s\n') | |||
|
461 | ui.status(msg % (desc, desctarget)) | |||
442 | else: |
|
462 | else: | |
443 | ui.status(_('already rebased %s as %s\n') % |
|
463 | ui.status(_('already rebased %s as %s\n') % | |
444 | (desc, repo[state[rev]])) |
|
464 | (desc, repo[state[rev]])) | |
@@ -620,7 +640,7 b' def defineparents(repo, rev, target, sta' | |||||
620 | elif p1n in state: |
|
640 | elif p1n in state: | |
621 | if state[p1n] == nullmerge: |
|
641 | if state[p1n] == nullmerge: | |
622 | p1 = target |
|
642 | p1 = target | |
623 |
elif state[p1n] |
|
643 | elif state[p1n] in (revignored, revprecursor): | |
624 | p1 = nearestrebased(repo, p1n, state) |
|
644 | p1 = nearestrebased(repo, p1n, state) | |
625 | if p1 is None: |
|
645 | if p1 is None: | |
626 | p1 = target |
|
646 | p1 = target | |
@@ -636,7 +656,7 b' def defineparents(repo, rev, target, sta' | |||||
636 | if p2n in state: |
|
656 | if p2n in state: | |
637 | if p1 == target: # p1n in targetancestors or external |
|
657 | if p1 == target: # p1n in targetancestors or external | |
638 | p1 = state[p2n] |
|
658 | p1 = state[p2n] | |
639 |
elif state[p2n] |
|
659 | elif state[p2n] in (revignored, revprecursor): | |
640 | p2 = nearestrebased(repo, p2n, state) |
|
660 | p2 = nearestrebased(repo, p2n, state) | |
641 | if p2 is None: |
|
661 | if p2 is None: | |
642 | # no ancestors rebased yet, detach |
|
662 | # no ancestors rebased yet, detach | |
@@ -824,7 +844,8 b' def restorestatus(repo):' | |||||
824 | activebookmark = l |
|
844 | activebookmark = l | |
825 | else: |
|
845 | else: | |
826 | oldrev, newrev = l.split(':') |
|
846 | oldrev, newrev = l.split(':') | |
827 |
if newrev in (str(nullmerge), str(revignored) |
|
847 | if newrev in (str(nullmerge), str(revignored), | |
|
848 | str(revprecursor)): | |||
828 | state[repo[oldrev].rev()] = int(newrev) |
|
849 | state[repo[oldrev].rev()] = int(newrev) | |
829 | elif newrev == nullid: |
|
850 | elif newrev == nullid: | |
830 | state[repo[oldrev].rev()] = revtodo |
|
851 | state[repo[oldrev].rev()] = revtodo | |
@@ -912,7 +933,7 b' def abort(repo, originalwd, target, stat' | |||||
912 | repo.ui.warn(_('rebase aborted\n')) |
|
933 | repo.ui.warn(_('rebase aborted\n')) | |
913 | return 0 |
|
934 | return 0 | |
914 |
|
935 | |||
915 | def buildstate(repo, dest, rebaseset, collapse): |
|
936 | def buildstate(repo, dest, rebaseset, collapse, obsoletenotrebased): | |
916 | '''Define which revisions are going to be rebased and where |
|
937 | '''Define which revisions are going to be rebased and where | |
917 |
|
938 | |||
918 | repo: repo |
|
939 | repo: repo | |
@@ -999,6 +1020,8 b' def buildstate(repo, dest, rebaseset, co' | |||||
999 | rebasedomain = set(repo.revs('%ld::%ld', rebaseset, rebaseset)) |
|
1020 | rebasedomain = set(repo.revs('%ld::%ld', rebaseset, rebaseset)) | |
1000 | for ignored in set(rebasedomain) - set(rebaseset): |
|
1021 | for ignored in set(rebasedomain) - set(rebaseset): | |
1001 | state[ignored] = revignored |
|
1022 | state[ignored] = revignored | |
|
1023 | for r in obsoletenotrebased: | |||
|
1024 | state[r] = revprecursor | |||
1002 | return repo['.'].rev(), dest.rev(), state |
|
1025 | return repo['.'].rev(), dest.rev(), state | |
1003 |
|
1026 | |||
1004 | def clearrebased(ui, repo, state, skipped, collapsedas=None): |
|
1027 | def clearrebased(ui, repo, state, skipped, collapsedas=None): | |
@@ -1107,6 +1130,32 b' def _rebasedvisible(orig, repo):' | |||||
1107 | blockers.update(getattr(repo, '_rebaseset', ())) |
|
1130 | blockers.update(getattr(repo, '_rebaseset', ())) | |
1108 | return blockers |
|
1131 | return blockers | |
1109 |
|
1132 | |||
|
1133 | def _computeobsoletenotrebased(repo, rebasesetrevs, dest): | |||
|
1134 | """return a mapping obsolete => successor for all obsolete nodes to be | |||
|
1135 | rebased that have a successors in the destination""" | |||
|
1136 | obsoletenotrebased = {} | |||
|
1137 | ||||
|
1138 | # Build a mapping succesor => obsolete nodes for the obsolete | |||
|
1139 | # nodes to be rebased | |||
|
1140 | allsuccessors = {} | |||
|
1141 | for r in rebasesetrevs: | |||
|
1142 | n = repo[r] | |||
|
1143 | if n.obsolete(): | |||
|
1144 | node = repo.changelog.node(r) | |||
|
1145 | for s in obsolete.allsuccessors(repo.obsstore, [node]): | |||
|
1146 | allsuccessors[repo.changelog.rev(s)] = repo.changelog.rev(node) | |||
|
1147 | ||||
|
1148 | if allsuccessors: | |||
|
1149 | # Look for successors of obsolete nodes to be rebased among | |||
|
1150 | # the ancestors of dest | |||
|
1151 | ancs = repo.changelog.ancestors([repo[dest].rev()], | |||
|
1152 | stoprev=min(allsuccessors), | |||
|
1153 | inclusive=True) | |||
|
1154 | for s in allsuccessors: | |||
|
1155 | if s in ancs: | |||
|
1156 | obsoletenotrebased[allsuccessors[s]] = s | |||
|
1157 | return obsoletenotrebased | |||
|
1158 | ||||
1110 | def summaryhook(ui, repo): |
|
1159 | def summaryhook(ui, repo): | |
1111 | if not os.path.exists(repo.join('rebasestate')): |
|
1160 | if not os.path.exists(repo.join('rebasestate')): | |
1112 | return |
|
1161 | return |
@@ -203,10 +203,9 b' More complex case were part of the rebas' | |||||
203 | |/ |
|
203 | |/ | |
204 | o 0:cd010b8cd998 A |
|
204 | o 0:cd010b8cd998 A | |
205 |
|
205 | |||
206 | $ hg rebase --source 'desc(B)' --dest 'tip' |
|
206 | $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True | |
207 | rebasing 8:8877864f1edb "B" |
|
207 | rebasing 8:8877864f1edb "B" | |
208 | rebasing 9:08483444fef9 "D" |
|
208 | note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 "D" | |
209 | note: rebase of 9:08483444fef9 created no changes to commit |
|
|||
210 | rebasing 10:5ae4c968c6ac "C" |
|
209 | rebasing 10:5ae4c968c6ac "C" | |
211 | $ hg debugobsolete |
|
210 | $ hg debugobsolete | |
212 | 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob) |
|
211 | 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (*) {'user': 'test'} (glob) | |
@@ -214,7 +213,6 b' More complex case were part of the rebas' | |||||
214 | 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (*) {'user': 'test'} (glob) |
|
213 | 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (*) {'user': 'test'} (glob) | |
215 | 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (*) {'user': 'test'} (glob) |
|
214 | 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (*) {'user': 'test'} (glob) | |
216 | 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 (*) {'user': 'test'} (glob) |
|
215 | 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 (*) {'user': 'test'} (glob) | |
217 | 08483444fef91d6224f6655ee586a65d263ad34c 0 {8877864f1edb05d0e07dc4ba77b67a80a7b86672} (*) {'user': 'test'} (glob) |
|
|||
218 | 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 (*) {'user': 'test'} (glob) |
|
216 | 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 (*) {'user': 'test'} (glob) | |
219 | $ hg log --rev 'divergent()' |
|
217 | $ hg log --rev 'divergent()' | |
220 | $ hg log -G |
|
218 | $ hg log -G | |
@@ -540,3 +538,55 b' Test hidden changesets in the rebase set' | |||||
540 | |/ |
|
538 | |/ | |
541 | o 0:cd010b8cd998 A |
|
539 | o 0:cd010b8cd998 A | |
542 |
|
540 | |||
|
541 | $ hg up 14 -C | |||
|
542 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved | |||
|
543 | $ echo "K" > K | |||
|
544 | $ hg add K | |||
|
545 | $ hg commit --amend -m "K" | |||
|
546 | $ echo "L" > L | |||
|
547 | $ hg add L | |||
|
548 | $ hg commit -m "L" | |||
|
549 | $ hg up '.^' | |||
|
550 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved | |||
|
551 | $ echo "M" > M | |||
|
552 | $ hg add M | |||
|
553 | $ hg commit --amend -m "M" | |||
|
554 | $ hg log -G | |||
|
555 | @ 20:bfaedf8eb73b M | |||
|
556 | | | |||
|
557 | | o 18:97219452e4bd L | |||
|
558 | | | | |||
|
559 | | x 17:fc37a630c901 K | |||
|
560 | |/ | |||
|
561 | | o 15:5ae8a643467b J | |||
|
562 | | | | |||
|
563 | | x 14:9ad579b4a5de I | |||
|
564 | |/ | |||
|
565 | | o 12:acd174b7ab39 I | |||
|
566 | | | | |||
|
567 | | o 11:6c11a6218c97 H | |||
|
568 | | | | |||
|
569 | o | 10:b5313c85b22e D | |||
|
570 | |/ | |||
|
571 | | o 8:53a6a128b2b7 M | |||
|
572 | | |\ | |||
|
573 | | | x 7:02de42196ebe H | |||
|
574 | | | | | |||
|
575 | o---+ 6:eea13746799a G | |||
|
576 | | | | | |||
|
577 | | | o 5:24b6387c8c8c F | |||
|
578 | | | | | |||
|
579 | o---+ 4:9520eea781bc E | |||
|
580 | / / | |||
|
581 | x | 3:32af7686d403 D | |||
|
582 | | | | |||
|
583 | o | 2:5fddd98957c8 C | |||
|
584 | | | | |||
|
585 | o | 1:42ccdea3bb16 B | |||
|
586 | |/ | |||
|
587 | o 0:cd010b8cd998 A | |||
|
588 | ||||
|
589 | $ hg rebase -s 14 -d 18 --config experimental.rebaseskipobsolete=True | |||
|
590 | note: not rebasing 14:9ad579b4a5de "I", already in destination as 17:fc37a630c901 "K" | |||
|
591 | rebasing 15:5ae8a643467b "J" | |||
|
592 |
General Comments 0
You need to be logged in to leave comments.
Login now