##// END OF EJS Templates
dirstate: fix compilation warnings in `dirstate_item_set_possibly_dirty()`...
Martin von Zweigbergk -
r48790:20187530 default
parent child Browse files
Show More
@@ -1,1321 +1,1320
1 1 /*
2 2 parsers.c - efficient content parsing
3 3
4 4 Copyright 2008 Olivia Mackall <olivia@selenic.com> and others
5 5
6 6 This software may be used and distributed according to the terms of
7 7 the GNU General Public License, incorporated herein by reference.
8 8 */
9 9
10 10 #define PY_SSIZE_T_CLEAN
11 11 #include <Python.h>
12 12 #include <ctype.h>
13 13 #include <stddef.h>
14 14 #include <string.h>
15 15
16 16 #include "bitmanipulation.h"
17 17 #include "charencode.h"
18 18 #include "util.h"
19 19
20 20 #ifdef IS_PY3K
21 21 /* The mapping of Python types is meant to be temporary to get Python
22 22 * 3 to compile. We should remove this once Python 3 support is fully
23 23 * supported and proper types are used in the extensions themselves. */
24 24 #define PyInt_Check PyLong_Check
25 25 #define PyInt_FromLong PyLong_FromLong
26 26 #define PyInt_FromSsize_t PyLong_FromSsize_t
27 27 #define PyInt_AsLong PyLong_AsLong
28 28 #endif
29 29
30 30 static const char *const versionerrortext = "Python minor version mismatch";
31 31
32 32 static const int dirstate_v1_from_p2 = -2;
33 33 static const int dirstate_v1_nonnormal = -1;
34 34 static const int ambiguous_time = -1;
35 35
36 36 static PyObject *dict_new_presized(PyObject *self, PyObject *args)
37 37 {
38 38 Py_ssize_t expected_size;
39 39
40 40 if (!PyArg_ParseTuple(args, "n:make_presized_dict", &expected_size)) {
41 41 return NULL;
42 42 }
43 43
44 44 return _dict_new_presized(expected_size);
45 45 }
46 46
47 47 static PyObject *dirstate_item_new(PyTypeObject *subtype, PyObject *args,
48 48 PyObject *kwds)
49 49 {
50 50 /* We do all the initialization here and not a tp_init function because
51 51 * dirstate_item is immutable. */
52 52 dirstateItemObject *t;
53 53 int wc_tracked;
54 54 int p1_tracked;
55 55 int p2_tracked;
56 56 int merged;
57 57 int clean_p1;
58 58 int clean_p2;
59 59 int possibly_dirty;
60 60 PyObject *parentfiledata;
61 61 static char *keywords_name[] = {
62 62 "wc_tracked", "p1_tracked", "p2_tracked",
63 63 "merged", "clean_p1", "clean_p2",
64 64 "possibly_dirty", "parentfiledata", NULL,
65 65 };
66 66 wc_tracked = 0;
67 67 p1_tracked = 0;
68 68 p2_tracked = 0;
69 69 merged = 0;
70 70 clean_p1 = 0;
71 71 clean_p2 = 0;
72 72 possibly_dirty = 0;
73 73 parentfiledata = Py_None;
74 74 if (!PyArg_ParseTupleAndKeywords(args, kwds, "iiiiiiiO", keywords_name,
75 75 &wc_tracked, &p1_tracked, &p2_tracked,
76 76 &merged, &clean_p1, &clean_p2,
77 77 &possibly_dirty, &parentfiledata
78 78
79 79 )) {
80 80 return NULL;
81 81 }
82 82 if (merged && (clean_p1 || clean_p2)) {
83 83 PyErr_SetString(PyExc_RuntimeError,
84 84 "`merged` argument incompatible with "
85 85 "`clean_p1`/`clean_p2`");
86 86 return NULL;
87 87 }
88 88 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
89 89 if (!t) {
90 90 return NULL;
91 91 }
92 92
93 93 t->flags = 0;
94 94 if (wc_tracked) {
95 95 t->flags |= dirstate_flag_wc_tracked;
96 96 }
97 97 if (p1_tracked) {
98 98 t->flags |= dirstate_flag_p1_tracked;
99 99 }
100 100 if (p2_tracked) {
101 101 t->flags |= dirstate_flag_p2_tracked;
102 102 }
103 103 if (possibly_dirty) {
104 104 t->flags |= dirstate_flag_possibly_dirty;
105 105 }
106 106 if (merged) {
107 107 t->flags |= dirstate_flag_merged;
108 108 }
109 109 if (clean_p1) {
110 110 t->flags |= dirstate_flag_clean_p1;
111 111 }
112 112 if (clean_p2) {
113 113 t->flags |= dirstate_flag_clean_p2;
114 114 }
115 115 t->mode = 0;
116 116 t->size = dirstate_v1_nonnormal;
117 117 t->mtime = ambiguous_time;
118 118 if (parentfiledata != Py_None) {
119 119 if (!PyTuple_CheckExact(parentfiledata)) {
120 120 PyErr_SetString(
121 121 PyExc_TypeError,
122 122 "parentfiledata should be a Tuple or None");
123 123 return NULL;
124 124 }
125 125 t->mode =
126 126 (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 0));
127 127 t->size =
128 128 (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 1));
129 129 t->mtime =
130 130 (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 2));
131 131 }
132 132 return (PyObject *)t;
133 133 }
134 134
135 135 static void dirstate_item_dealloc(PyObject *o)
136 136 {
137 137 PyObject_Del(o);
138 138 }
139 139
140 140 static inline bool dirstate_item_c_tracked(dirstateItemObject *self)
141 141 {
142 142 return (self->flags & dirstate_flag_wc_tracked);
143 143 }
144 144
145 145 static inline bool dirstate_item_c_added(dirstateItemObject *self)
146 146 {
147 147 unsigned char mask =
148 148 (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
149 149 dirstate_flag_p2_tracked);
150 150 unsigned char target = dirstate_flag_wc_tracked;
151 151 return (self->flags & mask) == target;
152 152 }
153 153
154 154 static inline bool dirstate_item_c_removed(dirstateItemObject *self)
155 155 {
156 156 if (self->flags & dirstate_flag_wc_tracked) {
157 157 return false;
158 158 }
159 159 return (self->flags &
160 160 (dirstate_flag_p1_tracked | dirstate_flag_p2_tracked));
161 161 }
162 162
163 163 static inline bool dirstate_item_c_merged(dirstateItemObject *self)
164 164 {
165 165 return ((self->flags & dirstate_flag_wc_tracked) &&
166 166 (self->flags & dirstate_flag_merged));
167 167 }
168 168
169 169 static inline bool dirstate_item_c_merged_removed(dirstateItemObject *self)
170 170 {
171 171 if (!dirstate_item_c_removed(self)) {
172 172 return false;
173 173 }
174 174 return (self->flags & dirstate_flag_merged);
175 175 }
176 176
177 177 static inline bool dirstate_item_c_from_p2(dirstateItemObject *self)
178 178 {
179 179 if (!dirstate_item_c_tracked(self)) {
180 180 return false;
181 181 }
182 182 return (self->flags & dirstate_flag_clean_p2);
183 183 }
184 184
185 185 static inline bool dirstate_item_c_from_p2_removed(dirstateItemObject *self)
186 186 {
187 187 if (!dirstate_item_c_removed(self)) {
188 188 return false;
189 189 }
190 190 return (self->flags & dirstate_flag_clean_p2);
191 191 }
192 192
193 193 static inline char dirstate_item_c_v1_state(dirstateItemObject *self)
194 194 {
195 195 if (self->flags & dirstate_flag_rust_special) {
196 196 return ' ';
197 197 } else if (dirstate_item_c_removed(self)) {
198 198 return 'r';
199 199 } else if (dirstate_item_c_merged(self)) {
200 200 return 'm';
201 201 } else if (dirstate_item_c_added(self)) {
202 202 return 'a';
203 203 } else {
204 204 return 'n';
205 205 }
206 206 }
207 207
208 208 static inline int dirstate_item_c_v1_mode(dirstateItemObject *self)
209 209 {
210 210 return self->mode;
211 211 }
212 212
213 213 static inline int dirstate_item_c_v1_size(dirstateItemObject *self)
214 214 {
215 215 if (self->flags & dirstate_flag_rust_special) {
216 216 return self->size;
217 217 } else if (dirstate_item_c_merged_removed(self)) {
218 218 return dirstate_v1_nonnormal;
219 219 } else if (dirstate_item_c_from_p2_removed(self)) {
220 220 return dirstate_v1_from_p2;
221 221 } else if (dirstate_item_c_removed(self)) {
222 222 return 0;
223 223 } else if (dirstate_item_c_merged(self)) {
224 224 return dirstate_v1_from_p2;
225 225 } else if (dirstate_item_c_added(self)) {
226 226 return dirstate_v1_nonnormal;
227 227 } else if (dirstate_item_c_from_p2(self)) {
228 228 return dirstate_v1_from_p2;
229 229 } else if (self->flags & dirstate_flag_possibly_dirty) {
230 230 return self->size; /* NON NORMAL ? */
231 231 } else {
232 232 return self->size;
233 233 }
234 234 }
235 235
236 236 static inline int dirstate_item_c_v1_mtime(dirstateItemObject *self)
237 237 {
238 238 if (self->flags & dirstate_flag_rust_special) {
239 239 return self->mtime;
240 240 } else if (dirstate_item_c_removed(self)) {
241 241 return 0;
242 242 } else if (self->flags & dirstate_flag_possibly_dirty) {
243 243 return ambiguous_time;
244 244 } else if (dirstate_item_c_merged(self)) {
245 245 return ambiguous_time;
246 246 } else if (dirstate_item_c_added(self)) {
247 247 return ambiguous_time;
248 248 } else if (dirstate_item_c_from_p2(self)) {
249 249 return ambiguous_time;
250 250 } else {
251 251 return self->mtime;
252 252 }
253 253 }
254 254
255 255 static PyObject *dirstate_item_v1_state(dirstateItemObject *self)
256 256 {
257 257 char state = dirstate_item_c_v1_state(self);
258 258 return PyBytes_FromStringAndSize(&state, 1);
259 259 };
260 260
261 261 static PyObject *dirstate_item_v1_mode(dirstateItemObject *self)
262 262 {
263 263 return PyInt_FromLong(dirstate_item_c_v1_mode(self));
264 264 };
265 265
266 266 static PyObject *dirstate_item_v1_size(dirstateItemObject *self)
267 267 {
268 268 return PyInt_FromLong(dirstate_item_c_v1_size(self));
269 269 };
270 270
271 271 static PyObject *dirstate_item_v1_mtime(dirstateItemObject *self)
272 272 {
273 273 return PyInt_FromLong(dirstate_item_c_v1_mtime(self));
274 274 };
275 275
276 276 static PyObject *dirstate_item_need_delay(dirstateItemObject *self,
277 277 PyObject *value)
278 278 {
279 279 long now;
280 280 if (!pylong_to_long(value, &now)) {
281 281 return NULL;
282 282 }
283 283 if (dirstate_item_c_v1_state(self) == 'n' &&
284 284 dirstate_item_c_v1_mtime(self) == now) {
285 285 Py_RETURN_TRUE;
286 286 } else {
287 287 Py_RETURN_FALSE;
288 288 }
289 289 };
290 290
291 291 /* This will never change since it's bound to V1
292 292 */
293 293 static inline dirstateItemObject *
294 294 dirstate_item_from_v1_data(char state, int mode, int size, int mtime)
295 295 {
296 296 dirstateItemObject *t =
297 297 PyObject_New(dirstateItemObject, &dirstateItemType);
298 298 if (!t) {
299 299 return NULL;
300 300 }
301 301
302 302 if (state == 'm') {
303 303 t->flags =
304 304 (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
305 305 dirstate_flag_p2_tracked | dirstate_flag_merged);
306 306 t->mode = 0;
307 307 t->size = dirstate_v1_from_p2;
308 308 t->mtime = ambiguous_time;
309 309 } else if (state == 'a') {
310 310 t->flags = dirstate_flag_wc_tracked;
311 311 t->mode = 0;
312 312 t->size = dirstate_v1_nonnormal;
313 313 t->mtime = ambiguous_time;
314 314 } else if (state == 'r') {
315 315 t->mode = 0;
316 316 t->size = 0;
317 317 t->mtime = 0;
318 318 if (size == dirstate_v1_nonnormal) {
319 319 t->flags =
320 320 (dirstate_flag_p1_tracked |
321 321 dirstate_flag_p2_tracked | dirstate_flag_merged);
322 322 } else if (size == dirstate_v1_from_p2) {
323 323 t->flags =
324 324 (dirstate_flag_p2_tracked | dirstate_flag_clean_p2);
325 325 } else {
326 326 t->flags = dirstate_flag_p1_tracked;
327 327 }
328 328 } else if (state == 'n') {
329 329 if (size == dirstate_v1_from_p2) {
330 330 t->flags =
331 331 (dirstate_flag_wc_tracked |
332 332 dirstate_flag_p2_tracked | dirstate_flag_clean_p2);
333 333 t->mode = 0;
334 334 t->size = dirstate_v1_from_p2;
335 335 t->mtime = ambiguous_time;
336 336 } else if (size == dirstate_v1_nonnormal) {
337 337 t->flags = (dirstate_flag_wc_tracked |
338 338 dirstate_flag_p1_tracked |
339 339 dirstate_flag_possibly_dirty);
340 340 t->mode = 0;
341 341 t->size = dirstate_v1_nonnormal;
342 342 t->mtime = ambiguous_time;
343 343 } else if (mtime == ambiguous_time) {
344 344 t->flags = (dirstate_flag_wc_tracked |
345 345 dirstate_flag_p1_tracked |
346 346 dirstate_flag_possibly_dirty);
347 347 t->mode = mode;
348 348 t->size = size;
349 349 t->mtime = 0;
350 350 } else {
351 351 t->flags = (dirstate_flag_wc_tracked |
352 352 dirstate_flag_p1_tracked);
353 353 t->mode = mode;
354 354 t->size = size;
355 355 t->mtime = mtime;
356 356 }
357 357 } else if (state == ' ') {
358 358 /* XXX Rust is using this special case, it should be clean up
359 359 * later. */
360 360 t->flags = dirstate_flag_rust_special;
361 361 t->mode = mode;
362 362 t->size = size;
363 363 t->mtime = mtime;
364 364 } else {
365 365 PyErr_Format(PyExc_RuntimeError,
366 366 "unknown state: `%c` (%d, %d, %d)", state, mode,
367 367 size, mtime, NULL);
368 368 return NULL;
369 369 }
370 370
371 371 return t;
372 372 }
373 373
374 374 /* This will never change since it's bound to V1, unlike `dirstate_item_new` */
375 375 static PyObject *dirstate_item_from_v1_meth(PyTypeObject *subtype,
376 376 PyObject *args)
377 377 {
378 378 /* We do all the initialization here and not a tp_init function because
379 379 * dirstate_item is immutable. */
380 380 char state;
381 381 int size, mode, mtime;
382 382 if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime)) {
383 383 return NULL;
384 384 }
385 385 return (PyObject *)dirstate_item_from_v1_data(state, mode, size, mtime);
386 386 };
387 387
388 388 /* constructor to help legacy API to build a new "added" item
389 389
390 390 Should eventually be removed */
391 391 static PyObject *dirstate_item_new_added(PyTypeObject *subtype)
392 392 {
393 393 dirstateItemObject *t;
394 394 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
395 395 if (!t) {
396 396 return NULL;
397 397 }
398 398 t->flags = dirstate_flag_wc_tracked;
399 399 t->mode = 0;
400 400 t->size = dirstate_v1_nonnormal;
401 401 t->mtime = ambiguous_time;
402 402 return (PyObject *)t;
403 403 };
404 404
405 405 /* constructor to help legacy API to build a new "merged" item
406 406
407 407 Should eventually be removed */
408 408 static PyObject *dirstate_item_new_merged(PyTypeObject *subtype)
409 409 {
410 410 dirstateItemObject *t;
411 411 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
412 412 if (!t) {
413 413 return NULL;
414 414 }
415 415 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
416 416 dirstate_flag_p2_tracked | dirstate_flag_merged);
417 417 t->mode = 0;
418 418 t->size = dirstate_v1_from_p2;
419 419 t->mtime = ambiguous_time;
420 420 return (PyObject *)t;
421 421 };
422 422
423 423 /* constructor to help legacy API to build a new "from_p2" item
424 424
425 425 Should eventually be removed */
426 426 static PyObject *dirstate_item_new_from_p2(PyTypeObject *subtype)
427 427 {
428 428 /* We do all the initialization here and not a tp_init function because
429 429 * dirstate_item is immutable. */
430 430 dirstateItemObject *t;
431 431 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
432 432 if (!t) {
433 433 return NULL;
434 434 }
435 435 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p2_tracked |
436 436 dirstate_flag_clean_p2);
437 437 t->mode = 0;
438 438 t->size = dirstate_v1_from_p2;
439 439 t->mtime = ambiguous_time;
440 440 return (PyObject *)t;
441 441 };
442 442
443 443 /* constructor to help legacy API to build a new "possibly" item
444 444
445 445 Should eventually be removed */
446 446 static PyObject *dirstate_item_new_possibly_dirty(PyTypeObject *subtype)
447 447 {
448 448 /* We do all the initialization here and not a tp_init function because
449 449 * dirstate_item is immutable. */
450 450 dirstateItemObject *t;
451 451 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
452 452 if (!t) {
453 453 return NULL;
454 454 }
455 455 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
456 456 dirstate_flag_possibly_dirty);
457 457 t->mode = 0;
458 458 t->size = dirstate_v1_nonnormal;
459 459 t->mtime = ambiguous_time;
460 460 return (PyObject *)t;
461 461 };
462 462
463 463 /* constructor to help legacy API to build a new "normal" item
464 464
465 465 Should eventually be removed */
466 466 static PyObject *dirstate_item_new_normal(PyTypeObject *subtype, PyObject *args)
467 467 {
468 468 /* We do all the initialization here and not a tp_init function because
469 469 * dirstate_item is immutable. */
470 470 dirstateItemObject *t;
471 471 int size, mode, mtime;
472 472 if (!PyArg_ParseTuple(args, "iii", &mode, &size, &mtime)) {
473 473 return NULL;
474 474 }
475 475
476 476 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
477 477 if (!t) {
478 478 return NULL;
479 479 }
480 480 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked);
481 481 t->mode = mode;
482 482 t->size = size;
483 483 t->mtime = mtime;
484 484 return (PyObject *)t;
485 485 };
486 486
487 487 /* This means the next status call will have to actually check its content
488 488 to make sure it is correct. */
489 489 static PyObject *dirstate_item_set_possibly_dirty(dirstateItemObject *self)
490 490 {
491 if (self->flags |= dirstate_flag_possibly_dirty) {
492 Py_RETURN_NONE;
493 }
491 self->flags |= dirstate_flag_possibly_dirty;
492 Py_RETURN_NONE;
494 493 }
495 494
496 495 /* See docstring of the python implementation for details */
497 496 static PyObject *dirstate_item_set_clean(dirstateItemObject *self,
498 497 PyObject *args)
499 498 {
500 499 int size, mode, mtime;
501 500 if (!PyArg_ParseTuple(args, "iii", &mode, &size, &mtime)) {
502 501 return NULL;
503 502 }
504 503 self->flags = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked;
505 504 self->mode = mode;
506 505 self->size = size;
507 506 self->mtime = mtime;
508 507 Py_RETURN_NONE;
509 508 }
510 509
511 510 static PyObject *dirstate_item_set_untracked(dirstateItemObject *self)
512 511 {
513 512 self->flags &= ~dirstate_flag_wc_tracked;
514 513 self->mode = 0;
515 514 self->mtime = 0;
516 515 self->size = 0;
517 516 Py_RETURN_NONE;
518 517 }
519 518
520 519 static PyMethodDef dirstate_item_methods[] = {
521 520 {"v1_state", (PyCFunction)dirstate_item_v1_state, METH_NOARGS,
522 521 "return a \"state\" suitable for v1 serialization"},
523 522 {"v1_mode", (PyCFunction)dirstate_item_v1_mode, METH_NOARGS,
524 523 "return a \"mode\" suitable for v1 serialization"},
525 524 {"v1_size", (PyCFunction)dirstate_item_v1_size, METH_NOARGS,
526 525 "return a \"size\" suitable for v1 serialization"},
527 526 {"v1_mtime", (PyCFunction)dirstate_item_v1_mtime, METH_NOARGS,
528 527 "return a \"mtime\" suitable for v1 serialization"},
529 528 {"need_delay", (PyCFunction)dirstate_item_need_delay, METH_O,
530 529 "True if the stored mtime would be ambiguous with the current time"},
531 530 {"from_v1_data", (PyCFunction)dirstate_item_from_v1_meth,
532 531 METH_VARARGS | METH_CLASS, "build a new DirstateItem object from V1 data"},
533 532 {"new_added", (PyCFunction)dirstate_item_new_added,
534 533 METH_NOARGS | METH_CLASS,
535 534 "constructor to help legacy API to build a new \"added\" item"},
536 535 {"new_merged", (PyCFunction)dirstate_item_new_merged,
537 536 METH_NOARGS | METH_CLASS,
538 537 "constructor to help legacy API to build a new \"merged\" item"},
539 538 {"new_from_p2", (PyCFunction)dirstate_item_new_from_p2,
540 539 METH_NOARGS | METH_CLASS,
541 540 "constructor to help legacy API to build a new \"from_p2\" item"},
542 541 {"new_possibly_dirty", (PyCFunction)dirstate_item_new_possibly_dirty,
543 542 METH_NOARGS | METH_CLASS,
544 543 "constructor to help legacy API to build a new \"possibly_dirty\" item"},
545 544 {"new_normal", (PyCFunction)dirstate_item_new_normal,
546 545 METH_VARARGS | METH_CLASS,
547 546 "constructor to help legacy API to build a new \"normal\" item"},
548 547 {"set_possibly_dirty", (PyCFunction)dirstate_item_set_possibly_dirty,
549 548 METH_NOARGS, "mark a file as \"possibly dirty\""},
550 549 {"set_clean", (PyCFunction)dirstate_item_set_clean, METH_VARARGS,
551 550 "mark a file as \"clean\""},
552 551 {"set_untracked", (PyCFunction)dirstate_item_set_untracked, METH_NOARGS,
553 552 "mark a file as \"untracked\""},
554 553 {NULL} /* Sentinel */
555 554 };
556 555
557 556 static PyObject *dirstate_item_get_mode(dirstateItemObject *self)
558 557 {
559 558 return PyInt_FromLong(dirstate_item_c_v1_mode(self));
560 559 };
561 560
562 561 static PyObject *dirstate_item_get_size(dirstateItemObject *self)
563 562 {
564 563 return PyInt_FromLong(dirstate_item_c_v1_size(self));
565 564 };
566 565
567 566 static PyObject *dirstate_item_get_mtime(dirstateItemObject *self)
568 567 {
569 568 return PyInt_FromLong(dirstate_item_c_v1_mtime(self));
570 569 };
571 570
572 571 static PyObject *dirstate_item_get_state(dirstateItemObject *self)
573 572 {
574 573 char state = dirstate_item_c_v1_state(self);
575 574 return PyBytes_FromStringAndSize(&state, 1);
576 575 };
577 576
578 577 static PyObject *dirstate_item_get_tracked(dirstateItemObject *self)
579 578 {
580 579 if (dirstate_item_c_tracked(self)) {
581 580 Py_RETURN_TRUE;
582 581 } else {
583 582 Py_RETURN_FALSE;
584 583 }
585 584 };
586 585
587 586 static PyObject *dirstate_item_get_added(dirstateItemObject *self)
588 587 {
589 588 if (dirstate_item_c_added(self)) {
590 589 Py_RETURN_TRUE;
591 590 } else {
592 591 Py_RETURN_FALSE;
593 592 }
594 593 };
595 594
596 595 static PyObject *dirstate_item_get_merged(dirstateItemObject *self)
597 596 {
598 597 if (dirstate_item_c_merged(self)) {
599 598 Py_RETURN_TRUE;
600 599 } else {
601 600 Py_RETURN_FALSE;
602 601 }
603 602 };
604 603
605 604 static PyObject *dirstate_item_get_merged_removed(dirstateItemObject *self)
606 605 {
607 606 if (dirstate_item_c_merged_removed(self)) {
608 607 Py_RETURN_TRUE;
609 608 } else {
610 609 Py_RETURN_FALSE;
611 610 }
612 611 };
613 612
614 613 static PyObject *dirstate_item_get_from_p2(dirstateItemObject *self)
615 614 {
616 615 if (dirstate_item_c_from_p2(self)) {
617 616 Py_RETURN_TRUE;
618 617 } else {
619 618 Py_RETURN_FALSE;
620 619 }
621 620 };
622 621
623 622 static PyObject *dirstate_item_get_from_p2_removed(dirstateItemObject *self)
624 623 {
625 624 if (dirstate_item_c_from_p2_removed(self)) {
626 625 Py_RETURN_TRUE;
627 626 } else {
628 627 Py_RETURN_FALSE;
629 628 }
630 629 };
631 630
632 631 static PyObject *dirstate_item_get_removed(dirstateItemObject *self)
633 632 {
634 633 if (dirstate_item_c_removed(self)) {
635 634 Py_RETURN_TRUE;
636 635 } else {
637 636 Py_RETURN_FALSE;
638 637 }
639 638 };
640 639
641 640 static PyObject *dm_nonnormal(dirstateItemObject *self)
642 641 {
643 642 if ((dirstate_item_c_v1_state(self) != 'n') ||
644 643 (dirstate_item_c_v1_mtime(self) == ambiguous_time)) {
645 644 Py_RETURN_TRUE;
646 645 } else {
647 646 Py_RETURN_FALSE;
648 647 }
649 648 };
650 649 static PyObject *dm_otherparent(dirstateItemObject *self)
651 650 {
652 651 if (dirstate_item_c_v1_mtime(self) == dirstate_v1_from_p2) {
653 652 Py_RETURN_TRUE;
654 653 } else {
655 654 Py_RETURN_FALSE;
656 655 }
657 656 };
658 657
659 658 static PyGetSetDef dirstate_item_getset[] = {
660 659 {"mode", (getter)dirstate_item_get_mode, NULL, "mode", NULL},
661 660 {"size", (getter)dirstate_item_get_size, NULL, "size", NULL},
662 661 {"mtime", (getter)dirstate_item_get_mtime, NULL, "mtime", NULL},
663 662 {"state", (getter)dirstate_item_get_state, NULL, "state", NULL},
664 663 {"tracked", (getter)dirstate_item_get_tracked, NULL, "tracked", NULL},
665 664 {"added", (getter)dirstate_item_get_added, NULL, "added", NULL},
666 665 {"merged_removed", (getter)dirstate_item_get_merged_removed, NULL,
667 666 "merged_removed", NULL},
668 667 {"merged", (getter)dirstate_item_get_merged, NULL, "merged", NULL},
669 668 {"from_p2_removed", (getter)dirstate_item_get_from_p2_removed, NULL,
670 669 "from_p2_removed", NULL},
671 670 {"from_p2", (getter)dirstate_item_get_from_p2, NULL, "from_p2", NULL},
672 671 {"removed", (getter)dirstate_item_get_removed, NULL, "removed", NULL},
673 672 {"dm_nonnormal", (getter)dm_nonnormal, NULL, "dm_nonnormal", NULL},
674 673 {"dm_otherparent", (getter)dm_otherparent, NULL, "dm_otherparent", NULL},
675 674 {NULL} /* Sentinel */
676 675 };
677 676
678 677 PyTypeObject dirstateItemType = {
679 678 PyVarObject_HEAD_INIT(NULL, 0) /* header */
680 679 "dirstate_tuple", /* tp_name */
681 680 sizeof(dirstateItemObject), /* tp_basicsize */
682 681 0, /* tp_itemsize */
683 682 (destructor)dirstate_item_dealloc, /* tp_dealloc */
684 683 0, /* tp_print */
685 684 0, /* tp_getattr */
686 685 0, /* tp_setattr */
687 686 0, /* tp_compare */
688 687 0, /* tp_repr */
689 688 0, /* tp_as_number */
690 689 0, /* tp_as_sequence */
691 690 0, /* tp_as_mapping */
692 691 0, /* tp_hash */
693 692 0, /* tp_call */
694 693 0, /* tp_str */
695 694 0, /* tp_getattro */
696 695 0, /* tp_setattro */
697 696 0, /* tp_as_buffer */
698 697 Py_TPFLAGS_DEFAULT, /* tp_flags */
699 698 "dirstate tuple", /* tp_doc */
700 699 0, /* tp_traverse */
701 700 0, /* tp_clear */
702 701 0, /* tp_richcompare */
703 702 0, /* tp_weaklistoffset */
704 703 0, /* tp_iter */
705 704 0, /* tp_iternext */
706 705 dirstate_item_methods, /* tp_methods */
707 706 0, /* tp_members */
708 707 dirstate_item_getset, /* tp_getset */
709 708 0, /* tp_base */
710 709 0, /* tp_dict */
711 710 0, /* tp_descr_get */
712 711 0, /* tp_descr_set */
713 712 0, /* tp_dictoffset */
714 713 0, /* tp_init */
715 714 0, /* tp_alloc */
716 715 dirstate_item_new, /* tp_new */
717 716 };
718 717
719 718 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
720 719 {
721 720 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
722 721 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
723 722 char state, *cur, *str, *cpos;
724 723 int mode, size, mtime;
725 724 unsigned int flen, pos = 40;
726 725 Py_ssize_t len = 40;
727 726 Py_ssize_t readlen;
728 727
729 728 if (!PyArg_ParseTuple(
730 729 args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"),
731 730 &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen)) {
732 731 goto quit;
733 732 }
734 733
735 734 len = readlen;
736 735
737 736 /* read parents */
738 737 if (len < 40) {
739 738 PyErr_SetString(PyExc_ValueError,
740 739 "too little data for parents");
741 740 goto quit;
742 741 }
743 742
744 743 parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, (Py_ssize_t)20,
745 744 str + 20, (Py_ssize_t)20);
746 745 if (!parents) {
747 746 goto quit;
748 747 }
749 748
750 749 /* read filenames */
751 750 while (pos >= 40 && pos < len) {
752 751 if (pos + 17 > len) {
753 752 PyErr_SetString(PyExc_ValueError,
754 753 "overflow in dirstate");
755 754 goto quit;
756 755 }
757 756 cur = str + pos;
758 757 /* unpack header */
759 758 state = *cur;
760 759 mode = getbe32(cur + 1);
761 760 size = getbe32(cur + 5);
762 761 mtime = getbe32(cur + 9);
763 762 flen = getbe32(cur + 13);
764 763 pos += 17;
765 764 cur += 17;
766 765 if (flen > len - pos) {
767 766 PyErr_SetString(PyExc_ValueError,
768 767 "overflow in dirstate");
769 768 goto quit;
770 769 }
771 770
772 771 entry = (PyObject *)dirstate_item_from_v1_data(state, mode,
773 772 size, mtime);
774 773 cpos = memchr(cur, 0, flen);
775 774 if (cpos) {
776 775 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
777 776 cname = PyBytes_FromStringAndSize(
778 777 cpos + 1, flen - (cpos - cur) - 1);
779 778 if (!fname || !cname ||
780 779 PyDict_SetItem(cmap, fname, cname) == -1 ||
781 780 PyDict_SetItem(dmap, fname, entry) == -1) {
782 781 goto quit;
783 782 }
784 783 Py_DECREF(cname);
785 784 } else {
786 785 fname = PyBytes_FromStringAndSize(cur, flen);
787 786 if (!fname ||
788 787 PyDict_SetItem(dmap, fname, entry) == -1) {
789 788 goto quit;
790 789 }
791 790 }
792 791 Py_DECREF(fname);
793 792 Py_DECREF(entry);
794 793 fname = cname = entry = NULL;
795 794 pos += flen;
796 795 }
797 796
798 797 ret = parents;
799 798 Py_INCREF(ret);
800 799 quit:
801 800 Py_XDECREF(fname);
802 801 Py_XDECREF(cname);
803 802 Py_XDECREF(entry);
804 803 Py_XDECREF(parents);
805 804 return ret;
806 805 }
807 806
808 807 /*
809 808 * Build a set of non-normal and other parent entries from the dirstate dmap
810 809 */
811 810 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args)
812 811 {
813 812 PyObject *dmap, *fname, *v;
814 813 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
815 814 Py_ssize_t pos;
816 815
817 816 if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type,
818 817 &dmap)) {
819 818 goto bail;
820 819 }
821 820
822 821 nonnset = PySet_New(NULL);
823 822 if (nonnset == NULL) {
824 823 goto bail;
825 824 }
826 825
827 826 otherpset = PySet_New(NULL);
828 827 if (otherpset == NULL) {
829 828 goto bail;
830 829 }
831 830
832 831 pos = 0;
833 832 while (PyDict_Next(dmap, &pos, &fname, &v)) {
834 833 dirstateItemObject *t;
835 834 if (!dirstate_tuple_check(v)) {
836 835 PyErr_SetString(PyExc_TypeError,
837 836 "expected a dirstate tuple");
838 837 goto bail;
839 838 }
840 839 t = (dirstateItemObject *)v;
841 840
842 841 if (dirstate_item_c_from_p2(t)) {
843 842 if (PySet_Add(otherpset, fname) == -1) {
844 843 goto bail;
845 844 }
846 845 }
847 846 if (!(t->flags & dirstate_flag_wc_tracked) ||
848 847 !(t->flags &
849 848 (dirstate_flag_p1_tracked | dirstate_flag_p2_tracked)) ||
850 849 (t->flags &
851 850 (dirstate_flag_possibly_dirty | dirstate_flag_merged))) {
852 851 if (PySet_Add(nonnset, fname) == -1) {
853 852 goto bail;
854 853 }
855 854 }
856 855 }
857 856
858 857 result = Py_BuildValue("(OO)", nonnset, otherpset);
859 858 if (result == NULL) {
860 859 goto bail;
861 860 }
862 861 Py_DECREF(nonnset);
863 862 Py_DECREF(otherpset);
864 863 return result;
865 864 bail:
866 865 Py_XDECREF(nonnset);
867 866 Py_XDECREF(otherpset);
868 867 Py_XDECREF(result);
869 868 return NULL;
870 869 }
871 870
872 871 /*
873 872 * Efficiently pack a dirstate object into its on-disk format.
874 873 */
875 874 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
876 875 {
877 876 PyObject *packobj = NULL;
878 877 PyObject *map, *copymap, *pl, *mtime_unset = NULL;
879 878 Py_ssize_t nbytes, pos, l;
880 879 PyObject *k, *v = NULL, *pn;
881 880 char *p, *s;
882 881 int now;
883 882
884 883 if (!PyArg_ParseTuple(args, "O!O!O!i:pack_dirstate", &PyDict_Type, &map,
885 884 &PyDict_Type, &copymap, &PyTuple_Type, &pl,
886 885 &now)) {
887 886 return NULL;
888 887 }
889 888
890 889 if (PyTuple_Size(pl) != 2) {
891 890 PyErr_SetString(PyExc_TypeError, "expected 2-element tuple");
892 891 return NULL;
893 892 }
894 893
895 894 /* Figure out how much we need to allocate. */
896 895 for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
897 896 PyObject *c;
898 897 if (!PyBytes_Check(k)) {
899 898 PyErr_SetString(PyExc_TypeError, "expected string key");
900 899 goto bail;
901 900 }
902 901 nbytes += PyBytes_GET_SIZE(k) + 17;
903 902 c = PyDict_GetItem(copymap, k);
904 903 if (c) {
905 904 if (!PyBytes_Check(c)) {
906 905 PyErr_SetString(PyExc_TypeError,
907 906 "expected string key");
908 907 goto bail;
909 908 }
910 909 nbytes += PyBytes_GET_SIZE(c) + 1;
911 910 }
912 911 }
913 912
914 913 packobj = PyBytes_FromStringAndSize(NULL, nbytes);
915 914 if (packobj == NULL) {
916 915 goto bail;
917 916 }
918 917
919 918 p = PyBytes_AS_STRING(packobj);
920 919
921 920 pn = PyTuple_GET_ITEM(pl, 0);
922 921 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
923 922 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
924 923 goto bail;
925 924 }
926 925 memcpy(p, s, l);
927 926 p += 20;
928 927 pn = PyTuple_GET_ITEM(pl, 1);
929 928 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
930 929 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
931 930 goto bail;
932 931 }
933 932 memcpy(p, s, l);
934 933 p += 20;
935 934
936 935 for (pos = 0; PyDict_Next(map, &pos, &k, &v);) {
937 936 dirstateItemObject *tuple;
938 937 char state;
939 938 int mode, size, mtime;
940 939 Py_ssize_t len, l;
941 940 PyObject *o;
942 941 char *t;
943 942
944 943 if (!dirstate_tuple_check(v)) {
945 944 PyErr_SetString(PyExc_TypeError,
946 945 "expected a dirstate tuple");
947 946 goto bail;
948 947 }
949 948 tuple = (dirstateItemObject *)v;
950 949
951 950 state = dirstate_item_c_v1_state(tuple);
952 951 mode = dirstate_item_c_v1_mode(tuple);
953 952 size = dirstate_item_c_v1_size(tuple);
954 953 mtime = dirstate_item_c_v1_mtime(tuple);
955 954 if (state == 'n' && mtime == now) {
956 955 /* See pure/parsers.py:pack_dirstate for why we do
957 956 * this. */
958 957 mtime = -1;
959 958 mtime_unset = (PyObject *)dirstate_item_from_v1_data(
960 959 state, mode, size, mtime);
961 960 if (!mtime_unset) {
962 961 goto bail;
963 962 }
964 963 if (PyDict_SetItem(map, k, mtime_unset) == -1) {
965 964 goto bail;
966 965 }
967 966 Py_DECREF(mtime_unset);
968 967 mtime_unset = NULL;
969 968 }
970 969 *p++ = state;
971 970 putbe32((uint32_t)mode, p);
972 971 putbe32((uint32_t)size, p + 4);
973 972 putbe32((uint32_t)mtime, p + 8);
974 973 t = p + 12;
975 974 p += 16;
976 975 len = PyBytes_GET_SIZE(k);
977 976 memcpy(p, PyBytes_AS_STRING(k), len);
978 977 p += len;
979 978 o = PyDict_GetItem(copymap, k);
980 979 if (o) {
981 980 *p++ = '\0';
982 981 l = PyBytes_GET_SIZE(o);
983 982 memcpy(p, PyBytes_AS_STRING(o), l);
984 983 p += l;
985 984 len += l + 1;
986 985 }
987 986 putbe32((uint32_t)len, t);
988 987 }
989 988
990 989 pos = p - PyBytes_AS_STRING(packobj);
991 990 if (pos != nbytes) {
992 991 PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
993 992 (long)pos, (long)nbytes);
994 993 goto bail;
995 994 }
996 995
997 996 return packobj;
998 997 bail:
999 998 Py_XDECREF(mtime_unset);
1000 999 Py_XDECREF(packobj);
1001 1000 Py_XDECREF(v);
1002 1001 return NULL;
1003 1002 }
1004 1003
1005 1004 #define BUMPED_FIX 1
1006 1005 #define USING_SHA_256 2
1007 1006 #define FM1_HEADER_SIZE (4 + 8 + 2 + 2 + 1 + 1 + 1)
1008 1007
1009 1008 static PyObject *readshas(const char *source, unsigned char num,
1010 1009 Py_ssize_t hashwidth)
1011 1010 {
1012 1011 int i;
1013 1012 PyObject *list = PyTuple_New(num);
1014 1013 if (list == NULL) {
1015 1014 return NULL;
1016 1015 }
1017 1016 for (i = 0; i < num; i++) {
1018 1017 PyObject *hash = PyBytes_FromStringAndSize(source, hashwidth);
1019 1018 if (hash == NULL) {
1020 1019 Py_DECREF(list);
1021 1020 return NULL;
1022 1021 }
1023 1022 PyTuple_SET_ITEM(list, i, hash);
1024 1023 source += hashwidth;
1025 1024 }
1026 1025 return list;
1027 1026 }
1028 1027
1029 1028 static PyObject *fm1readmarker(const char *databegin, const char *dataend,
1030 1029 uint32_t *msize)
1031 1030 {
1032 1031 const char *data = databegin;
1033 1032 const char *meta;
1034 1033
1035 1034 double mtime;
1036 1035 int16_t tz;
1037 1036 uint16_t flags;
1038 1037 unsigned char nsuccs, nparents, nmetadata;
1039 1038 Py_ssize_t hashwidth = 20;
1040 1039
1041 1040 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
1042 1041 PyObject *metadata = NULL, *ret = NULL;
1043 1042 int i;
1044 1043
1045 1044 if (data + FM1_HEADER_SIZE > dataend) {
1046 1045 goto overflow;
1047 1046 }
1048 1047
1049 1048 *msize = getbe32(data);
1050 1049 data += 4;
1051 1050 mtime = getbefloat64(data);
1052 1051 data += 8;
1053 1052 tz = getbeint16(data);
1054 1053 data += 2;
1055 1054 flags = getbeuint16(data);
1056 1055 data += 2;
1057 1056
1058 1057 if (flags & USING_SHA_256) {
1059 1058 hashwidth = 32;
1060 1059 }
1061 1060
1062 1061 nsuccs = (unsigned char)(*data++);
1063 1062 nparents = (unsigned char)(*data++);
1064 1063 nmetadata = (unsigned char)(*data++);
1065 1064
1066 1065 if (databegin + *msize > dataend) {
1067 1066 goto overflow;
1068 1067 }
1069 1068 dataend = databegin + *msize; /* narrow down to marker size */
1070 1069
1071 1070 if (data + hashwidth > dataend) {
1072 1071 goto overflow;
1073 1072 }
1074 1073 prec = PyBytes_FromStringAndSize(data, hashwidth);
1075 1074 data += hashwidth;
1076 1075 if (prec == NULL) {
1077 1076 goto bail;
1078 1077 }
1079 1078
1080 1079 if (data + nsuccs * hashwidth > dataend) {
1081 1080 goto overflow;
1082 1081 }
1083 1082 succs = readshas(data, nsuccs, hashwidth);
1084 1083 if (succs == NULL) {
1085 1084 goto bail;
1086 1085 }
1087 1086 data += nsuccs * hashwidth;
1088 1087
1089 1088 if (nparents == 1 || nparents == 2) {
1090 1089 if (data + nparents * hashwidth > dataend) {
1091 1090 goto overflow;
1092 1091 }
1093 1092 parents = readshas(data, nparents, hashwidth);
1094 1093 if (parents == NULL) {
1095 1094 goto bail;
1096 1095 }
1097 1096 data += nparents * hashwidth;
1098 1097 } else {
1099 1098 parents = Py_None;
1100 1099 Py_INCREF(parents);
1101 1100 }
1102 1101
1103 1102 if (data + 2 * nmetadata > dataend) {
1104 1103 goto overflow;
1105 1104 }
1106 1105 meta = data + (2 * nmetadata);
1107 1106 metadata = PyTuple_New(nmetadata);
1108 1107 if (metadata == NULL) {
1109 1108 goto bail;
1110 1109 }
1111 1110 for (i = 0; i < nmetadata; i++) {
1112 1111 PyObject *tmp, *left = NULL, *right = NULL;
1113 1112 Py_ssize_t leftsize = (unsigned char)(*data++);
1114 1113 Py_ssize_t rightsize = (unsigned char)(*data++);
1115 1114 if (meta + leftsize + rightsize > dataend) {
1116 1115 goto overflow;
1117 1116 }
1118 1117 left = PyBytes_FromStringAndSize(meta, leftsize);
1119 1118 meta += leftsize;
1120 1119 right = PyBytes_FromStringAndSize(meta, rightsize);
1121 1120 meta += rightsize;
1122 1121 tmp = PyTuple_New(2);
1123 1122 if (!left || !right || !tmp) {
1124 1123 Py_XDECREF(left);
1125 1124 Py_XDECREF(right);
1126 1125 Py_XDECREF(tmp);
1127 1126 goto bail;
1128 1127 }
1129 1128 PyTuple_SET_ITEM(tmp, 0, left);
1130 1129 PyTuple_SET_ITEM(tmp, 1, right);
1131 1130 PyTuple_SET_ITEM(metadata, i, tmp);
1132 1131 }
1133 1132 ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags, metadata, mtime,
1134 1133 (int)tz * 60, parents);
1135 1134 goto bail; /* return successfully */
1136 1135
1137 1136 overflow:
1138 1137 PyErr_SetString(PyExc_ValueError, "overflow in obsstore");
1139 1138 bail:
1140 1139 Py_XDECREF(prec);
1141 1140 Py_XDECREF(succs);
1142 1141 Py_XDECREF(metadata);
1143 1142 Py_XDECREF(parents);
1144 1143 return ret;
1145 1144 }
1146 1145
1147 1146 static PyObject *fm1readmarkers(PyObject *self, PyObject *args)
1148 1147 {
1149 1148 const char *data, *dataend;
1150 1149 Py_ssize_t datalen, offset, stop;
1151 1150 PyObject *markers = NULL;
1152 1151
1153 1152 if (!PyArg_ParseTuple(args, PY23("s#nn", "y#nn"), &data, &datalen,
1154 1153 &offset, &stop)) {
1155 1154 return NULL;
1156 1155 }
1157 1156 if (offset < 0) {
1158 1157 PyErr_SetString(PyExc_ValueError,
1159 1158 "invalid negative offset in fm1readmarkers");
1160 1159 return NULL;
1161 1160 }
1162 1161 if (stop > datalen) {
1163 1162 PyErr_SetString(
1164 1163 PyExc_ValueError,
1165 1164 "stop longer than data length in fm1readmarkers");
1166 1165 return NULL;
1167 1166 }
1168 1167 dataend = data + datalen;
1169 1168 data += offset;
1170 1169 markers = PyList_New(0);
1171 1170 if (!markers) {
1172 1171 return NULL;
1173 1172 }
1174 1173 while (offset < stop) {
1175 1174 uint32_t msize;
1176 1175 int error;
1177 1176 PyObject *record = fm1readmarker(data, dataend, &msize);
1178 1177 if (!record) {
1179 1178 goto bail;
1180 1179 }
1181 1180 error = PyList_Append(markers, record);
1182 1181 Py_DECREF(record);
1183 1182 if (error) {
1184 1183 goto bail;
1185 1184 }
1186 1185 data += msize;
1187 1186 offset += msize;
1188 1187 }
1189 1188 return markers;
1190 1189 bail:
1191 1190 Py_DECREF(markers);
1192 1191 return NULL;
1193 1192 }
1194 1193
1195 1194 static char parsers_doc[] = "Efficient content parsing.";
1196 1195
1197 1196 PyObject *encodedir(PyObject *self, PyObject *args);
1198 1197 PyObject *pathencode(PyObject *self, PyObject *args);
1199 1198 PyObject *lowerencode(PyObject *self, PyObject *args);
1200 1199 PyObject *parse_index2(PyObject *self, PyObject *args, PyObject *kwargs);
1201 1200
1202 1201 static PyMethodDef methods[] = {
1203 1202 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
1204 1203 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
1205 1204 "create a set containing non-normal and other parent entries of given "
1206 1205 "dirstate\n"},
1207 1206 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
1208 1207 {"parse_index2", (PyCFunction)parse_index2, METH_VARARGS | METH_KEYWORDS,
1209 1208 "parse a revlog index\n"},
1210 1209 {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"},
1211 1210 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
1212 1211 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},
1213 1212 {"dict_new_presized", dict_new_presized, METH_VARARGS,
1214 1213 "construct a dict with an expected size\n"},
1215 1214 {"make_file_foldmap", make_file_foldmap, METH_VARARGS,
1216 1215 "make file foldmap\n"},
1217 1216 {"jsonescapeu8fast", jsonescapeu8fast, METH_VARARGS,
1218 1217 "escape a UTF-8 byte string to JSON (fast path)\n"},
1219 1218 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
1220 1219 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
1221 1220 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
1222 1221 {"fm1readmarkers", fm1readmarkers, METH_VARARGS,
1223 1222 "parse v1 obsolete markers\n"},
1224 1223 {NULL, NULL}};
1225 1224
1226 1225 void dirs_module_init(PyObject *mod);
1227 1226 void manifest_module_init(PyObject *mod);
1228 1227 void revlog_module_init(PyObject *mod);
1229 1228
1230 1229 static const int version = 20;
1231 1230
1232 1231 static void module_init(PyObject *mod)
1233 1232 {
1234 1233 PyObject *capsule = NULL;
1235 1234 PyModule_AddIntConstant(mod, "version", version);
1236 1235
1237 1236 /* This module constant has two purposes. First, it lets us unit test
1238 1237 * the ImportError raised without hard-coding any error text. This
1239 1238 * means we can change the text in the future without breaking tests,
1240 1239 * even across changesets without a recompile. Second, its presence
1241 1240 * can be used to determine whether the version-checking logic is
1242 1241 * present, which also helps in testing across changesets without a
1243 1242 * recompile. Note that this means the pure-Python version of parsers
1244 1243 * should not have this module constant. */
1245 1244 PyModule_AddStringConstant(mod, "versionerrortext", versionerrortext);
1246 1245
1247 1246 dirs_module_init(mod);
1248 1247 manifest_module_init(mod);
1249 1248 revlog_module_init(mod);
1250 1249
1251 1250 capsule = PyCapsule_New(
1252 1251 dirstate_item_from_v1_data,
1253 1252 "mercurial.cext.parsers.make_dirstate_item_CAPI", NULL);
1254 1253 if (capsule != NULL)
1255 1254 PyModule_AddObject(mod, "make_dirstate_item_CAPI", capsule);
1256 1255
1257 1256 if (PyType_Ready(&dirstateItemType) < 0) {
1258 1257 return;
1259 1258 }
1260 1259 Py_INCREF(&dirstateItemType);
1261 1260 PyModule_AddObject(mod, "DirstateItem", (PyObject *)&dirstateItemType);
1262 1261 }
1263 1262
1264 1263 static int check_python_version(void)
1265 1264 {
1266 1265 PyObject *sys = PyImport_ImportModule("sys"), *ver;
1267 1266 long hexversion;
1268 1267 if (!sys) {
1269 1268 return -1;
1270 1269 }
1271 1270 ver = PyObject_GetAttrString(sys, "hexversion");
1272 1271 Py_DECREF(sys);
1273 1272 if (!ver) {
1274 1273 return -1;
1275 1274 }
1276 1275 hexversion = PyInt_AsLong(ver);
1277 1276 Py_DECREF(ver);
1278 1277 /* sys.hexversion is a 32-bit number by default, so the -1 case
1279 1278 * should only occur in unusual circumstances (e.g. if sys.hexversion
1280 1279 * is manually set to an invalid value). */
1281 1280 if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
1282 1281 PyErr_Format(PyExc_ImportError,
1283 1282 "%s: The Mercurial extension "
1284 1283 "modules were compiled with Python " PY_VERSION
1285 1284 ", but "
1286 1285 "Mercurial is currently using Python with "
1287 1286 "sys.hexversion=%ld: "
1288 1287 "Python %s\n at: %s",
1289 1288 versionerrortext, hexversion, Py_GetVersion(),
1290 1289 Py_GetProgramFullPath());
1291 1290 return -1;
1292 1291 }
1293 1292 return 0;
1294 1293 }
1295 1294
1296 1295 #ifdef IS_PY3K
1297 1296 static struct PyModuleDef parsers_module = {PyModuleDef_HEAD_INIT, "parsers",
1298 1297 parsers_doc, -1, methods};
1299 1298
1300 1299 PyMODINIT_FUNC PyInit_parsers(void)
1301 1300 {
1302 1301 PyObject *mod;
1303 1302
1304 1303 if (check_python_version() == -1)
1305 1304 return NULL;
1306 1305 mod = PyModule_Create(&parsers_module);
1307 1306 module_init(mod);
1308 1307 return mod;
1309 1308 }
1310 1309 #else
1311 1310 PyMODINIT_FUNC initparsers(void)
1312 1311 {
1313 1312 PyObject *mod;
1314 1313
1315 1314 if (check_python_version() == -1) {
1316 1315 return;
1317 1316 }
1318 1317 mod = Py_InitModule3("parsers", methods, parsers_doc);
1319 1318 module_init(mod);
1320 1319 }
1321 1320 #endif
General Comments 0
You need to be logged in to leave comments. Login now