Show More
@@ -187,7 +187,7 b' class changelog(revlog.revlog):' | |||
|
187 | 187 | |
|
188 | 188 | def reachableroots(self, minroot, heads, roots, includepath=False): |
|
189 | 189 | return revset.baseset(sorted( |
|
190 | self.index.reachableroots(minroot, heads, roots, includepath))) | |
|
190 | self.index.reachableroots2(minroot, heads, roots, includepath))) | |
|
191 | 191 | |
|
192 | 192 | def headrevs(self): |
|
193 | 193 | if self.filteredrevs: |
@@ -1108,16 +1108,15 b' static inline void set_phase_from_parent' | |||
|
1108 | 1108 | phases[i] = phases[parent_2]; |
|
1109 | 1109 | } |
|
1110 | 1110 | |
|
1111 | static PyObject *reachableroots(indexObject *self, PyObject *args) | |
|
1111 | static PyObject *reachableroots2(indexObject *self, PyObject *args) | |
|
1112 | 1112 | { |
|
1113 | 1113 | |
|
1114 | 1114 | /* Input */ |
|
1115 | 1115 | long minroot; |
|
1116 | 1116 | PyObject *includepatharg = NULL; |
|
1117 | 1117 | int includepath = 0; |
|
1118 |
/* heads |
|
|
1118 | /* heads and roots are lists */ | |
|
1119 | 1119 | PyObject *heads = NULL; |
|
1120 | /* roots is a set */ | |
|
1121 | 1120 | PyObject *roots = NULL; |
|
1122 | 1121 | PyObject *reachable = NULL; |
|
1123 | 1122 | |
@@ -1136,12 +1135,13 b' static PyObject *reachableroots(indexObj' | |||
|
1136 | 1135 | * revstates: array of length len+1 (all revs + nullrev) */ |
|
1137 | 1136 | int *tovisit = NULL; |
|
1138 | 1137 | long lentovisit = 0; |
|
1139 | enum { RS_SEEN = 1 }; | |
|
1138 | enum { RS_SEEN = 1, RS_ROOT = 2 }; | |
|
1140 | 1139 | char *revstates = NULL; |
|
1141 | 1140 | |
|
1142 | 1141 | /* Get arguments */ |
|
1143 | 1142 | if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads, |
|
1144 | &PySet_Type, &roots, &PyBool_Type, &includepatharg)) | |
|
1143 | &PyList_Type, &roots, | |
|
1144 | &PyBool_Type, &includepatharg)) | |
|
1145 | 1145 | goto bail; |
|
1146 | 1146 | |
|
1147 | 1147 | if (includepatharg == Py_True) |
@@ -1167,6 +1167,18 b' static PyObject *reachableroots(indexObj' | |||
|
1167 | 1167 | goto bail; |
|
1168 | 1168 | } |
|
1169 | 1169 | |
|
1170 | l = PyList_GET_SIZE(roots); | |
|
1171 | for (i = 0; i < l; i++) { | |
|
1172 | revnum = PyInt_AsLong(PyList_GET_ITEM(roots, i)); | |
|
1173 | if (revnum == -1 && PyErr_Occurred()) | |
|
1174 | goto bail; | |
|
1175 | /* If root is out of range, e.g. wdir(), it must be unreachable | |
|
1176 | * from heads. So we can just ignore it. */ | |
|
1177 | if (revnum + 1 < 0 || revnum + 1 >= len + 1) | |
|
1178 | continue; | |
|
1179 | revstates[revnum + 1] |= RS_ROOT; | |
|
1180 | } | |
|
1181 | ||
|
1170 | 1182 | /* Populate tovisit with all the heads */ |
|
1171 | 1183 | l = PyList_GET_SIZE(heads); |
|
1172 | 1184 | for (i = 0; i < l; i++) { |
@@ -1188,17 +1200,15 b' static PyObject *reachableroots(indexObj' | |||
|
1188 | 1200 | while (k < lentovisit) { |
|
1189 | 1201 | /* Add the node to reachable if it is a root*/ |
|
1190 | 1202 | revnum = tovisit[k++]; |
|
1203 | if (revstates[revnum + 1] & RS_ROOT) { | |
|
1191 | 1204 | val = PyInt_FromLong(revnum); |
|
1192 | 1205 | if (val == NULL) |
|
1193 | 1206 | goto bail; |
|
1194 | if (PySet_Contains(roots, val) == 1) { | |
|
1195 | 1207 | PySet_Add(reachable, val); |
|
1196 | if (includepath == 0) { | |
|
1197 | 1208 |
|
|
1209 | if (includepath == 0) | |
|
1198 | 1210 | continue; |
|
1199 | 1211 |
|
|
1200 | } | |
|
1201 | Py_DECREF(val); | |
|
1202 | 1212 | |
|
1203 | 1213 | /* Add its parents to the list of nodes to visit */ |
|
1204 | 1214 | if (revnum == -1) |
@@ -2434,7 +2444,7 b' static PyMethodDef index_methods[] = {' | |||
|
2434 | 2444 | "get an index entry"}, |
|
2435 | 2445 | {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, |
|
2436 | 2446 | METH_VARARGS, "compute phases"}, |
|
2437 | {"reachableroots", (PyCFunction)reachableroots, METH_VARARGS, | |
|
2447 | {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS, | |
|
2438 | 2448 | "reachableroots"}, |
|
2439 | 2449 | {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS, |
|
2440 | 2450 | "get head revisions"}, /* Can do filtering since 3.2 */ |
@@ -94,6 +94,7 b' def reachablerootspure(repo, minroot, ro' | |||
|
94 | 94 | if not roots: |
|
95 | 95 | return baseset() |
|
96 | 96 | parentrevs = repo.changelog.parentrevs |
|
97 | roots = set(roots) | |
|
97 | 98 | visit = list(heads) |
|
98 | 99 | reachable = set() |
|
99 | 100 | seen = {} |
@@ -133,7 +134,7 b' def reachableroots(repo, roots, heads, i' | |||
|
133 | 134 | # XXX this should be 'parentset.min()' assuming 'parentset' is a smartset |
|
134 | 135 | # (and if it is not, it should.) |
|
135 | 136 | minroot = min(roots) |
|
136 |
roots = s |
|
|
137 | roots = list(roots) | |
|
137 | 138 | heads = list(heads) |
|
138 | 139 | try: |
|
139 | 140 | return repo.changelog.reachableroots(minroot, heads, roots, includepath) |
@@ -69,28 +69,53 b' Test SEGV caused by bad revision passed ' | |||
|
69 | 69 | $ python <<EOF |
|
70 | 70 | > from mercurial import changelog, scmutil |
|
71 | 71 | > cl = changelog.changelog(scmutil.vfs('.hg/store')) |
|
72 | > print 'goods:' | |
|
72 | > print 'good heads:' | |
|
73 | 73 | > for head in [0, len(cl) - 1, -1]: |
|
74 |
> print'%s: %r' % (head, cl.reachableroots(0, [head], |
|
|
75 | > print 'bads:' | |
|
74 | > print'%s: %r' % (head, cl.reachableroots(0, [head], [0])) | |
|
75 | > print 'bad heads:' | |
|
76 | 76 | > for head in [len(cl), 10000, -2, -10000, None]: |
|
77 | 77 | > print '%s:' % head, |
|
78 | 78 | > try: |
|
79 |
> cl.reachableroots(0, [head], |
|
|
79 | > cl.reachableroots(0, [head], [0]) | |
|
80 | 80 | > print 'uncaught buffer overflow?' |
|
81 | 81 | > except (IndexError, TypeError) as inst: |
|
82 | 82 | > print inst |
|
83 | > print 'good roots:' | |
|
84 | > for root in [0, len(cl) - 1, -1]: | |
|
85 | > print '%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root])) | |
|
86 | > print 'out-of-range roots are ignored:' | |
|
87 | > for root in [len(cl), 10000, -2, -10000]: | |
|
88 | > print '%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root])) | |
|
89 | > print 'bad roots:' | |
|
90 | > for root in [None]: | |
|
91 | > print '%s:' % root, | |
|
92 | > try: | |
|
93 | > cl.reachableroots(root, [len(cl) - 1], [root]) | |
|
94 | > print 'uncaught error?' | |
|
95 | > except TypeError as inst: | |
|
96 | > print inst | |
|
83 | 97 | > EOF |
|
84 | goods: | |
|
98 | good heads: | |
|
85 | 99 | 0: <baseset [0]> |
|
86 | 100 | 1: <baseset [0]> |
|
87 | 101 | -1: <baseset []> |
|
88 | bads: | |
|
102 | bad heads: | |
|
89 | 103 | 2: head out of range |
|
90 | 104 | 10000: head out of range |
|
91 | 105 | -2: head out of range |
|
92 | 106 | -10000: head out of range |
|
93 | 107 | None: an integer is required |
|
108 | good roots: | |
|
109 | 0: <baseset [0]> | |
|
110 | 1: <baseset [1]> | |
|
111 | -1: <baseset [-1]> | |
|
112 | out-of-range roots are ignored: | |
|
113 | 2: <baseset []> | |
|
114 | 10000: <baseset []> | |
|
115 | -2: <baseset []> | |
|
116 | -10000: <baseset []> | |
|
117 | bad roots: | |
|
118 | None: an integer is required | |
|
94 | 119 | |
|
95 | 120 | $ cd .. |
|
96 | 121 | |
@@ -127,7 +152,7 b' Test corrupted p1/p2 fields that could c' | |||
|
127 | 152 | > n0, n1 = cl.node(0), cl.node(1) |
|
128 | 153 | > ops = [ |
|
129 | 154 | > ('reachableroots', |
|
130 |
> lambda: cl.index.reachableroots(0, [1], |
|
|
155 | > lambda: cl.index.reachableroots2(0, [1], [0], False)), | |
|
131 | 156 | > ('compute_phases_map_sets', lambda: cl.computephases([[0], []])), |
|
132 | 157 | > ('index_headrevs', lambda: cl.headrevs()), |
|
133 | 158 | > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)), |
General Comments 0
You need to be logged in to leave comments.
Login now