Show More
@@ -771,131 +771,6 b' def makestore(ui, repo):' | |||||
771 | % len(list(store))) |
|
771 | % len(list(store))) | |
772 | return store |
|
772 | return store | |
773 |
|
773 | |||
774 | def _filterprunes(markers): |
|
|||
775 | """return a set with no prune markers""" |
|
|||
776 | return set(m for m in markers if m[1]) |
|
|||
777 |
|
||||
778 | def exclusivemarkers(repo, nodes): |
|
|||
779 | """set of markers relevant to "nodes" but no other locally-known nodes |
|
|||
780 |
|
||||
781 | This function compute the set of markers "exclusive" to a locally-known |
|
|||
782 | node. This means we walk the markers starting from <nodes> until we reach a |
|
|||
783 | locally-known precursors outside of <nodes>. Element of <nodes> with |
|
|||
784 | locally-known successors outside of <nodes> are ignored (since their |
|
|||
785 | precursors markers are also relevant to these successors). |
|
|||
786 |
|
||||
787 | For example: |
|
|||
788 |
|
||||
789 | # (A0 rewritten as A1) |
|
|||
790 | # |
|
|||
791 | # A0 <-1- A1 # Marker "1" is exclusive to A1 |
|
|||
792 |
|
||||
793 | or |
|
|||
794 |
|
||||
795 | # (A0 rewritten as AX; AX rewritten as A1; AX is unkown locally) |
|
|||
796 | # |
|
|||
797 | # <-1- A0 <-2- AX <-3- A1 # Marker "2,3" are exclusive to A1 |
|
|||
798 |
|
||||
799 | or |
|
|||
800 |
|
||||
801 | # (A0 has unknown precursors, A0 rewritten as A1 and A2 (divergence)) |
|
|||
802 | # |
|
|||
803 | # <-2- A1 # Marker "2" is exclusive to A0,A1 |
|
|||
804 | # / |
|
|||
805 | # <-1- A0 |
|
|||
806 | # \ |
|
|||
807 | # <-3- A2 # Marker "3" is exclusive to A0,A2 |
|
|||
808 | # |
|
|||
809 | # in addition: |
|
|||
810 | # |
|
|||
811 | # Markers "2,3" are exclusive to A1,A2 |
|
|||
812 | # Markers "1,2,3" are exclusive to A0,A1,A2 |
|
|||
813 |
|
||||
814 | See test/test-obsolete-bundle-strip.t for more examples. |
|
|||
815 |
|
||||
816 | An example usage is strip. When stripping a changeset, we also want to |
|
|||
817 | strip the markers exclusive to this changeset. Otherwise we would have |
|
|||
818 | "dangling"" obsolescence markers from its precursors: Obsolescence markers |
|
|||
819 | marking a node as obsolete without any successors available locally. |
|
|||
820 |
|
||||
821 | As for relevant markers, the prune markers for children will be followed. |
|
|||
822 | Of course, they will only be followed if the pruned children is |
|
|||
823 | locally-known. Since the prune markers are relevant to the pruned node. |
|
|||
824 | However, while prune markers are considered relevant to the parent of the |
|
|||
825 | pruned changesets, prune markers for locally-known changeset (with no |
|
|||
826 | successors) are considered exclusive to the pruned nodes. This allows |
|
|||
827 | to strip the prune markers (with the rest of the exclusive chain) alongside |
|
|||
828 | the pruned changesets. |
|
|||
829 | """ |
|
|||
830 | # running on a filtered repository would be dangerous as markers could be |
|
|||
831 | # reported as exclusive when they are relevant for other filtered nodes. |
|
|||
832 | unfi = repo.unfiltered() |
|
|||
833 |
|
||||
834 | # shortcut to various useful item |
|
|||
835 | nm = unfi.changelog.nodemap |
|
|||
836 | precursorsmarkers = unfi.obsstore.precursors |
|
|||
837 | successormarkers = unfi.obsstore.successors |
|
|||
838 | childrenmarkers = unfi.obsstore.children |
|
|||
839 |
|
||||
840 | # exclusive markers (return of the function) |
|
|||
841 | exclmarkers = set() |
|
|||
842 | # we need fast membership testing |
|
|||
843 | nodes = set(nodes) |
|
|||
844 | # looking for head in the obshistory |
|
|||
845 | # |
|
|||
846 | # XXX we are ignoring all issues in regard with cycle for now. |
|
|||
847 | stack = [n for n in nodes if not _filterprunes(successormarkers.get(n, ()))] |
|
|||
848 | stack.sort() |
|
|||
849 | # nodes already stacked |
|
|||
850 | seennodes = set(stack) |
|
|||
851 | while stack: |
|
|||
852 | current = stack.pop() |
|
|||
853 | # fetch precursors markers |
|
|||
854 | markers = list(precursorsmarkers.get(current, ())) |
|
|||
855 | # extend the list with prune markers |
|
|||
856 | for mark in successormarkers.get(current, ()): |
|
|||
857 | if not mark[1]: |
|
|||
858 | markers.append(mark) |
|
|||
859 | # and markers from children (looking for prune) |
|
|||
860 | for mark in childrenmarkers.get(current, ()): |
|
|||
861 | if not mark[1]: |
|
|||
862 | markers.append(mark) |
|
|||
863 | # traverse the markers |
|
|||
864 | for mark in markers: |
|
|||
865 | if mark in exclmarkers: |
|
|||
866 | # markers already selected |
|
|||
867 | continue |
|
|||
868 |
|
||||
869 | # If the markers is about the current node, select it |
|
|||
870 | # |
|
|||
871 | # (this delay the addition of markers from children) |
|
|||
872 | if mark[1] or mark[0] == current: |
|
|||
873 | exclmarkers.add(mark) |
|
|||
874 |
|
||||
875 | # should we keep traversing through the precursors? |
|
|||
876 | prec = mark[0] |
|
|||
877 |
|
||||
878 | # nodes in the stack or already processed |
|
|||
879 | if prec in seennodes: |
|
|||
880 | continue |
|
|||
881 |
|
||||
882 | # is this a locally known node ? |
|
|||
883 | known = prec in nm |
|
|||
884 | # if locally-known and not in the <nodes> set the traversal |
|
|||
885 | # stop here. |
|
|||
886 | if known and prec not in nodes: |
|
|||
887 | continue |
|
|||
888 |
|
||||
889 | # do not keep going if there are unselected markers pointing to this |
|
|||
890 | # nodes. If we end up traversing these unselected markers later the |
|
|||
891 | # node will be taken care of at that point. |
|
|||
892 | precmarkers = _filterprunes(successormarkers.get(prec)) |
|
|||
893 | if precmarkers.issubset(exclmarkers): |
|
|||
894 | seennodes.add(prec) |
|
|||
895 | stack.append(prec) |
|
|||
896 |
|
||||
897 | return exclmarkers |
|
|||
898 |
|
||||
899 | def commonversion(versions): |
|
774 | def commonversion(versions): | |
900 | """Return the newest version listed in both versions and our local formats. |
|
775 | """Return the newest version listed in both versions and our local formats. | |
901 |
|
776 | |||
@@ -971,7 +846,7 b' def getmarkers(repo, nodes=None, exclusi' | |||||
971 | if nodes is None: |
|
846 | if nodes is None: | |
972 | rawmarkers = repo.obsstore |
|
847 | rawmarkers = repo.obsstore | |
973 | elif exclusive: |
|
848 | elif exclusive: | |
974 | rawmarkers = exclusivemarkers(repo, nodes) |
|
849 | rawmarkers = obsutil.exclusivemarkers(repo, nodes) | |
975 | else: |
|
850 | else: | |
976 | rawmarkers = repo.obsstore.relevantmarkers(nodes) |
|
851 | rawmarkers = repo.obsstore.relevantmarkers(nodes) | |
977 |
|
852 | |||
@@ -1063,6 +938,11 b' def foreground(repo, nodes):' | |||||
1063 | foreground = set(repo.set('%ln::', known)) |
|
938 | foreground = set(repo.set('%ln::', known)) | |
1064 | return set(c.node() for c in foreground) |
|
939 | return set(c.node() for c in foreground) | |
1065 |
|
940 | |||
|
941 | def exclusivemarkers(repo, nodes): | |||
|
942 | movemsg = 'obsolete.exclusivemarkers moved to obsutil.exclusivemarkers' | |||
|
943 | repo.ui.deprecwarn(movemsg, '4.3') | |||
|
944 | return obsutil.exclusivemarkers(repo, nodes) | |||
|
945 | ||||
1066 | def successorssets(repo, initialnode, cache=None): |
|
946 | def successorssets(repo, initialnode, cache=None): | |
1067 | movemsg = 'obsolete.successorssets moved to obsutil.successorssets' |
|
947 | movemsg = 'obsolete.successorssets moved to obsutil.successorssets' | |
1068 | repo.ui.deprecwarn(movemsg, '4.3') |
|
948 | repo.ui.deprecwarn(movemsg, '4.3') |
@@ -35,6 +35,131 b' def closestpredecessors(repo, nodeid):' | |||||
35 | else: |
|
35 | else: | |
36 | stack.append(precnodeid) |
|
36 | stack.append(precnodeid) | |
37 |
|
37 | |||
|
38 | def _filterprunes(markers): | |||
|
39 | """return a set with no prune markers""" | |||
|
40 | return set(m for m in markers if m[1]) | |||
|
41 | ||||
|
42 | def exclusivemarkers(repo, nodes): | |||
|
43 | """set of markers relevant to "nodes" but no other locally-known nodes | |||
|
44 | ||||
|
45 | This function compute the set of markers "exclusive" to a locally-known | |||
|
46 | node. This means we walk the markers starting from <nodes> until we reach a | |||
|
47 | locally-known precursors outside of <nodes>. Element of <nodes> with | |||
|
48 | locally-known successors outside of <nodes> are ignored (since their | |||
|
49 | precursors markers are also relevant to these successors). | |||
|
50 | ||||
|
51 | For example: | |||
|
52 | ||||
|
53 | # (A0 rewritten as A1) | |||
|
54 | # | |||
|
55 | # A0 <-1- A1 # Marker "1" is exclusive to A1 | |||
|
56 | ||||
|
57 | or | |||
|
58 | ||||
|
59 | # (A0 rewritten as AX; AX rewritten as A1; AX is unkown locally) | |||
|
60 | # | |||
|
61 | # <-1- A0 <-2- AX <-3- A1 # Marker "2,3" are exclusive to A1 | |||
|
62 | ||||
|
63 | or | |||
|
64 | ||||
|
65 | # (A0 has unknown precursors, A0 rewritten as A1 and A2 (divergence)) | |||
|
66 | # | |||
|
67 | # <-2- A1 # Marker "2" is exclusive to A0,A1 | |||
|
68 | # / | |||
|
69 | # <-1- A0 | |||
|
70 | # \ | |||
|
71 | # <-3- A2 # Marker "3" is exclusive to A0,A2 | |||
|
72 | # | |||
|
73 | # in addition: | |||
|
74 | # | |||
|
75 | # Markers "2,3" are exclusive to A1,A2 | |||
|
76 | # Markers "1,2,3" are exclusive to A0,A1,A2 | |||
|
77 | ||||
|
78 | See test/test-obsolete-bundle-strip.t for more examples. | |||
|
79 | ||||
|
80 | An example usage is strip. When stripping a changeset, we also want to | |||
|
81 | strip the markers exclusive to this changeset. Otherwise we would have | |||
|
82 | "dangling"" obsolescence markers from its precursors: Obsolescence markers | |||
|
83 | marking a node as obsolete without any successors available locally. | |||
|
84 | ||||
|
85 | As for relevant markers, the prune markers for children will be followed. | |||
|
86 | Of course, they will only be followed if the pruned children is | |||
|
87 | locally-known. Since the prune markers are relevant to the pruned node. | |||
|
88 | However, while prune markers are considered relevant to the parent of the | |||
|
89 | pruned changesets, prune markers for locally-known changeset (with no | |||
|
90 | successors) are considered exclusive to the pruned nodes. This allows | |||
|
91 | to strip the prune markers (with the rest of the exclusive chain) alongside | |||
|
92 | the pruned changesets. | |||
|
93 | """ | |||
|
94 | # running on a filtered repository would be dangerous as markers could be | |||
|
95 | # reported as exclusive when they are relevant for other filtered nodes. | |||
|
96 | unfi = repo.unfiltered() | |||
|
97 | ||||
|
98 | # shortcut to various useful item | |||
|
99 | nm = unfi.changelog.nodemap | |||
|
100 | precursorsmarkers = unfi.obsstore.precursors | |||
|
101 | successormarkers = unfi.obsstore.successors | |||
|
102 | childrenmarkers = unfi.obsstore.children | |||
|
103 | ||||
|
104 | # exclusive markers (return of the function) | |||
|
105 | exclmarkers = set() | |||
|
106 | # we need fast membership testing | |||
|
107 | nodes = set(nodes) | |||
|
108 | # looking for head in the obshistory | |||
|
109 | # | |||
|
110 | # XXX we are ignoring all issues in regard with cycle for now. | |||
|
111 | stack = [n for n in nodes if not _filterprunes(successormarkers.get(n, ()))] | |||
|
112 | stack.sort() | |||
|
113 | # nodes already stacked | |||
|
114 | seennodes = set(stack) | |||
|
115 | while stack: | |||
|
116 | current = stack.pop() | |||
|
117 | # fetch precursors markers | |||
|
118 | markers = list(precursorsmarkers.get(current, ())) | |||
|
119 | # extend the list with prune markers | |||
|
120 | for mark in successormarkers.get(current, ()): | |||
|
121 | if not mark[1]: | |||
|
122 | markers.append(mark) | |||
|
123 | # and markers from children (looking for prune) | |||
|
124 | for mark in childrenmarkers.get(current, ()): | |||
|
125 | if not mark[1]: | |||
|
126 | markers.append(mark) | |||
|
127 | # traverse the markers | |||
|
128 | for mark in markers: | |||
|
129 | if mark in exclmarkers: | |||
|
130 | # markers already selected | |||
|
131 | continue | |||
|
132 | ||||
|
133 | # If the markers is about the current node, select it | |||
|
134 | # | |||
|
135 | # (this delay the addition of markers from children) | |||
|
136 | if mark[1] or mark[0] == current: | |||
|
137 | exclmarkers.add(mark) | |||
|
138 | ||||
|
139 | # should we keep traversing through the precursors? | |||
|
140 | prec = mark[0] | |||
|
141 | ||||
|
142 | # nodes in the stack or already processed | |||
|
143 | if prec in seennodes: | |||
|
144 | continue | |||
|
145 | ||||
|
146 | # is this a locally known node ? | |||
|
147 | known = prec in nm | |||
|
148 | # if locally-known and not in the <nodes> set the traversal | |||
|
149 | # stop here. | |||
|
150 | if known and prec not in nodes: | |||
|
151 | continue | |||
|
152 | ||||
|
153 | # do not keep going if there are unselected markers pointing to this | |||
|
154 | # nodes. If we end up traversing these unselected markers later the | |||
|
155 | # node will be taken care of at that point. | |||
|
156 | precmarkers = _filterprunes(successormarkers.get(prec)) | |||
|
157 | if precmarkers.issubset(exclmarkers): | |||
|
158 | seennodes.add(prec) | |||
|
159 | stack.append(prec) | |||
|
160 | ||||
|
161 | return exclmarkers | |||
|
162 | ||||
38 | def successorssets(repo, initialnode, cache=None): |
|
163 | def successorssets(repo, initialnode, cache=None): | |
39 | """Return set of all latest successors of initial nodes |
|
164 | """Return set of all latest successors of initial nodes | |
40 |
|
165 |
@@ -20,6 +20,7 b' from . import (' | |||||
20 | error, |
|
20 | error, | |
21 | exchange, |
|
21 | exchange, | |
22 | obsolete, |
|
22 | obsolete, | |
|
23 | obsutil, | |||
23 | util, |
|
24 | util, | |
24 | ) |
|
25 | ) | |
25 |
|
26 | |||
@@ -132,7 +133,7 b' def strip(ui, repo, nodelist, backup=Tru' | |||||
132 |
|
133 | |||
133 | stripobsidx = obsmarkers = () |
|
134 | stripobsidx = obsmarkers = () | |
134 | if repo.ui.configbool('devel', 'strip-obsmarkers', True): |
|
135 | if repo.ui.configbool('devel', 'strip-obsmarkers', True): | |
135 |
obsmarkers = obs |
|
136 | obsmarkers = obsutil.exclusivemarkers(repo, stripbases) | |
136 | if obsmarkers: |
|
137 | if obsmarkers: | |
137 | stripobsidx = [i for i, m in enumerate(repo.obsstore) |
|
138 | stripobsidx = [i for i, m in enumerate(repo.obsstore) | |
138 | if m in obsmarkers] |
|
139 | if m in obsmarkers] |
General Comments 0
You need to be logged in to leave comments.
Login now