Show More
@@ -16,6 +16,8 b' import socket' | |||||
16 |
|
16 | |||
17 | from .i18n import _ |
|
17 | from .i18n import _ | |
18 | from .node import ( |
|
18 | from .node import ( | |
|
19 | hex, | |||
|
20 | nullid, | |||
19 | wdirid, |
|
21 | wdirid, | |
20 | wdirrev, |
|
22 | wdirrev, | |
21 | ) |
|
23 | ) | |
@@ -24,6 +26,7 b' from . import (' | |||||
24 | encoding, |
|
26 | encoding, | |
25 | error, |
|
27 | error, | |
26 | match as matchmod, |
|
28 | match as matchmod, | |
|
29 | obsolete, | |||
27 | pathutil, |
|
30 | pathutil, | |
28 | phases, |
|
31 | phases, | |
29 | pycompat, |
|
32 | pycompat, | |
@@ -561,6 +564,68 b' def origpath(ui, repo, filepath):' | |||||
561 |
|
564 | |||
562 | return fullorigpath + ".orig" |
|
565 | return fullorigpath + ".orig" | |
563 |
|
566 | |||
|
567 | def cleanupnodes(repo, mapping, operation): | |||
|
568 | """do common cleanups when old nodes are replaced by new nodes | |||
|
569 | ||||
|
570 | That includes writing obsmarkers or stripping nodes, and moving bookmarks. | |||
|
571 | (we might also want to move working directory parent in the future) | |||
|
572 | ||||
|
573 | mapping is {oldnode: [newnode]} or a iterable of nodes if they do not have | |||
|
574 | replacements. operation is a string, like "rebase". | |||
|
575 | """ | |||
|
576 | if not util.safehasattr(mapping, 'items'): | |||
|
577 | mapping = {n: () for n in mapping} | |||
|
578 | ||||
|
579 | with repo.transaction('cleanup') as tr: | |||
|
580 | # Move bookmarks | |||
|
581 | bmarks = repo._bookmarks | |||
|
582 | bmarkchanged = False | |||
|
583 | for oldnode, newnodes in mapping.items(): | |||
|
584 | oldbmarks = repo.nodebookmarks(oldnode) | |||
|
585 | if not oldbmarks: | |||
|
586 | continue | |||
|
587 | bmarkchanged = True | |||
|
588 | if len(newnodes) > 1: | |||
|
589 | heads = list(repo.set('heads(%ln)', newnodes)) | |||
|
590 | if len(heads) != 1: | |||
|
591 | raise error.ProgrammingError( | |||
|
592 | 'cannot figure out bookmark movement') | |||
|
593 | newnode = heads[0].node() | |||
|
594 | elif len(newnodes) == 0: | |||
|
595 | # move bookmark backwards | |||
|
596 | roots = list(repo.set('max((::%n) - %ln)', oldnode, | |||
|
597 | list(mapping))) | |||
|
598 | if roots: | |||
|
599 | newnode = roots[0].node() | |||
|
600 | else: | |||
|
601 | newnode = nullid | |||
|
602 | else: | |||
|
603 | newnode = newnodes[0] | |||
|
604 | repo.ui.debug('moving bookmarks %r from %s to %s\n' % | |||
|
605 | (oldbmarks, hex(oldnode), hex(newnode))) | |||
|
606 | for name in oldbmarks: | |||
|
607 | bmarks[name] = newnode | |||
|
608 | if bmarkchanged: | |||
|
609 | bmarks.recordchange(tr) | |||
|
610 | ||||
|
611 | # Obsolete or strip nodes | |||
|
612 | if obsolete.isenabled(repo, obsolete.createmarkersopt): | |||
|
613 | # If a node is already obsoleted, and we want to obsolete it | |||
|
614 | # without a successor, skip that obssolete request since it's | |||
|
615 | # unnecessary. That's the "if s or not isobs(n)" check below. | |||
|
616 | # Also sort the node in topology order, that might be useful for | |||
|
617 | # some obsstore logic. | |||
|
618 | # NOTE: the filtering and sorting might belong to createmarkers. | |||
|
619 | isobs = repo.obsstore.successors.__contains__ | |||
|
620 | sortfunc = lambda ns: repo.changelog.rev(ns[0]) | |||
|
621 | rels = [(repo[n], (repo[m] for m in s)) | |||
|
622 | for n, s in sorted(mapping.items(), key=sortfunc) | |||
|
623 | if s or not isobs(n)] | |||
|
624 | obsolete.createmarkers(repo, rels, operation=operation) | |||
|
625 | else: | |||
|
626 | from . import repair # avoid import cycle | |||
|
627 | repair.delayedstrip(repo.ui, repo, list(mapping), operation) | |||
|
628 | ||||
564 | def addremove(repo, matcher, prefix, opts=None, dry_run=None, similarity=None): |
|
629 | def addremove(repo, matcher, prefix, opts=None, dry_run=None, similarity=None): | |
565 | if opts is None: |
|
630 | if opts is None: | |
566 | opts = {} |
|
631 | opts = {} |
@@ -955,6 +955,7 b' Use delayedstrip to strip inside a trans' | |||||
955 | > \|/ |
|
955 | > \|/ | |
956 | > A Z |
|
956 | > A Z | |
957 | > EOS |
|
957 | > EOS | |
|
958 | $ cp -R . ../scmutilcleanup | |||
958 |
|
959 | |||
959 | $ hg up -C I |
|
960 | $ hg up -C I | |
960 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
961 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
@@ -990,3 +991,104 b' Use delayedstrip to strip inside a trans' | |||||
990 | |/ |
|
991 | |/ | |
991 | o 0:426bada5c675 A |
|
992 | o 0:426bada5c675 A | |
992 |
|
993 | |||
|
994 | Test high-level scmutil.cleanupnodes API | |||
|
995 | ||||
|
996 | $ cd $TESTTMP/scmutilcleanup | |||
|
997 | $ hg debugdrawdag <<'EOS' | |||
|
998 | > D2 F2 G2 # D2, F2, G2 are replacements for D, F, G | |||
|
999 | > | | | | |||
|
1000 | > C H G | |||
|
1001 | > EOS | |||
|
1002 | $ for i in B C D F G I Z; do | |||
|
1003 | > hg bookmark -i -r $i b-$i | |||
|
1004 | > done | |||
|
1005 | $ cp -R . ../scmutilcleanup.obsstore | |||
|
1006 | ||||
|
1007 | $ cat > $TESTTMP/scmutilcleanup.py <<EOF | |||
|
1008 | > from mercurial import scmutil | |||
|
1009 | > def reposetup(ui, repo): | |||
|
1010 | > def nodes(expr): | |||
|
1011 | > return [repo.changelog.node(r) for r in repo.revs(expr)] | |||
|
1012 | > def node(expr): | |||
|
1013 | > return nodes(expr)[0] | |||
|
1014 | > with repo.wlock(): | |||
|
1015 | > with repo.lock(): | |||
|
1016 | > with repo.transaction('delayedstrip'): | |||
|
1017 | > mapping = {node('F'): [node('F2')], | |||
|
1018 | > node('D'): [node('D2')], | |||
|
1019 | > node('G'): [node('G2')]} | |||
|
1020 | > scmutil.cleanupnodes(repo, mapping, 'replace') | |||
|
1021 | > scmutil.cleanupnodes(repo, nodes('((B::)+I+Z)-D2'), 'replace') | |||
|
1022 | > EOF | |||
|
1023 | $ hg log -r . -T '\n' --config extensions.t=$TESTTMP/scmutilcleanup.py | |||
|
1024 | warning: orphaned descendants detected, not stripping 112478962961, 1fc8102cda62, 26805aba1e60 | |||
|
1025 | saved backup bundle to $TESTTMP/scmutilcleanup/.hg/strip-backup/f585351a92f8-73fb7c03-replace.hg (glob) | |||
|
1026 | ||||
|
1027 | $ hg log -G -T '{rev}:{node|short} {desc} {bookmarks}' -r 'sort(all(), topo)' | |||
|
1028 | o 8:1473d4b996d1 G2 b-G | |||
|
1029 | | | |||
|
1030 | | o 7:d94e89b773b6 F2 b-F | |||
|
1031 | | | | |||
|
1032 | | o 5:7fe5bac4c918 H | |||
|
1033 | |/| | |||
|
1034 | | o 3:7fb047a69f22 E | |||
|
1035 | | | | |||
|
1036 | | | o 6:7c78f703e465 D2 b-D | |||
|
1037 | | | | | |||
|
1038 | | | o 4:26805aba1e60 C | |||
|
1039 | | | | | |||
|
1040 | | | o 2:112478962961 B | |||
|
1041 | | |/ | |||
|
1042 | o | 1:1fc8102cda62 G | |||
|
1043 | / | |||
|
1044 | o 0:426bada5c675 A b-B b-C b-I | |||
|
1045 | ||||
|
1046 | $ hg bookmark | |||
|
1047 | b-B 0:426bada5c675 | |||
|
1048 | b-C 0:426bada5c675 | |||
|
1049 | b-D 6:7c78f703e465 | |||
|
1050 | b-F 7:d94e89b773b6 | |||
|
1051 | b-G 8:1473d4b996d1 | |||
|
1052 | b-I 0:426bada5c675 | |||
|
1053 | b-Z -1:000000000000 | |||
|
1054 | ||||
|
1055 | Test the above using obsstore "by the way". Not directly related to strip, but | |||
|
1056 | we have reusable code here | |||
|
1057 | ||||
|
1058 | $ cd $TESTTMP/scmutilcleanup.obsstore | |||
|
1059 | $ cat >> .hg/hgrc <<EOF | |||
|
1060 | > [experimental] | |||
|
1061 | > evolution=all | |||
|
1062 | > evolution.track-operation=1 | |||
|
1063 | > EOF | |||
|
1064 | ||||
|
1065 | $ hg log -r . -T '\n' --config extensions.t=$TESTTMP/scmutilcleanup.py | |||
|
1066 | ||||
|
1067 | $ rm .hg/localtags | |||
|
1068 | $ hg log -G -T '{rev}:{node|short} {desc} {bookmarks}' -r 'sort(all(), topo)' | |||
|
1069 | o 12:1473d4b996d1 G2 b-G | |||
|
1070 | | | |||
|
1071 | | o 11:d94e89b773b6 F2 b-F | |||
|
1072 | | | | |||
|
1073 | | o 8:7fe5bac4c918 H | |||
|
1074 | |/| | |||
|
1075 | | o 4:7fb047a69f22 E | |||
|
1076 | | | | |||
|
1077 | | | o 10:7c78f703e465 D2 b-D | |||
|
1078 | | | | | |||
|
1079 | | | x 6:26805aba1e60 C | |||
|
1080 | | | | | |||
|
1081 | | | x 3:112478962961 B | |||
|
1082 | | |/ | |||
|
1083 | x | 1:1fc8102cda62 G | |||
|
1084 | / | |||
|
1085 | o 0:426bada5c675 A b-B b-C b-I | |||
|
1086 | ||||
|
1087 | $ hg debugobsolete | |||
|
1088 | 1fc8102cda6204549f031015641606ccf5513ec3 1473d4b996d1d1b121de6b39fab6a04fbf9d873e 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'replace', 'user': 'test'} | |||
|
1089 | 64a8289d249234b9886244d379f15e6b650b28e3 d94e89b773b67e72642a931159ada8d1a9246998 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'replace', 'user': 'test'} | |||
|
1090 | f585351a92f85104bff7c284233c338b10eb1df7 7c78f703e465d73102cc8780667ce269c5208a40 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'replace', 'user': 'test'} | |||
|
1091 | 48b9aae0607f43ff110d84e6883c151942add5ab 0 {0000000000000000000000000000000000000000} (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'replace', 'user': 'test'} | |||
|
1092 | 112478962961147124edd43549aedd1a335e44bf 0 {426bada5c67598ca65036d57d9e4b64b0c1ce7a0} (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'replace', 'user': 'test'} | |||
|
1093 | 08ebfeb61bac6e3f12079de774d285a0d6689eba 0 {426bada5c67598ca65036d57d9e4b64b0c1ce7a0} (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'replace', 'user': 'test'} | |||
|
1094 | 26805aba1e600a82e93661149f2313866a221a7b 0 {112478962961147124edd43549aedd1a335e44bf} (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'replace', 'user': 'test'} |
General Comments 0
You need to be logged in to leave comments.
Login now