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