##// END OF EJS Templates
obsutil: move 'exclusivemarkers' to the new modules...
marmoute -
r33144:d09ae850 default
parent child Browse files
Show More
@@ -771,131 +771,6 def makestore(ui, repo):
771 771 % len(list(store)))
772 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 774 def commonversion(versions):
900 775 """Return the newest version listed in both versions and our local formats.
901 776
@@ -971,7 +846,7 def getmarkers(repo, nodes=None, exclusi
971 846 if nodes is None:
972 847 rawmarkers = repo.obsstore
973 848 elif exclusive:
974 rawmarkers = exclusivemarkers(repo, nodes)
849 rawmarkers = obsutil.exclusivemarkers(repo, nodes)
975 850 else:
976 851 rawmarkers = repo.obsstore.relevantmarkers(nodes)
977 852
@@ -1063,6 +938,11 def foreground(repo, nodes):
1063 938 foreground = set(repo.set('%ln::', known))
1064 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 946 def successorssets(repo, initialnode, cache=None):
1067 947 movemsg = 'obsolete.successorssets moved to obsutil.successorssets'
1068 948 repo.ui.deprecwarn(movemsg, '4.3')
@@ -35,6 +35,131 def closestpredecessors(repo, nodeid):
35 35 else:
36 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 163 def successorssets(repo, initialnode, cache=None):
39 164 """Return set of all latest successors of initial nodes
40 165
@@ -20,6 +20,7 from . import (
20 20 error,
21 21 exchange,
22 22 obsolete,
23 obsutil,
23 24 util,
24 25 )
25 26
@@ -132,7 +133,7 def strip(ui, repo, nodelist, backup=Tru
132 133
133 134 stripobsidx = obsmarkers = ()
134 135 if repo.ui.configbool('devel', 'strip-obsmarkers', True):
135 obsmarkers = obsolete.exclusivemarkers(repo, stripbases)
136 obsmarkers = obsutil.exclusivemarkers(repo, stripbases)
136 137 if obsmarkers:
137 138 stripobsidx = [i for i, m in enumerate(repo.obsstore)
138 139 if m in obsmarkers]
General Comments 0
You need to be logged in to leave comments. Login now