##// END OF EJS Templates
reachableroots: use internal "revstates" array to test if rev is a root...
Yuya Nishihara -
r26053:b68c9d23 default
parent child Browse files
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 is a list */
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 Py_DECREF(val);
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 = set(roots)
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], set([0])))
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], set([0]))
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], set([0]), False)),
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