comparison mercurial/cext/parsers.c @ 48138:38488d488ec1

dirstate-item: change the internal storage and constructor value This should be closer to what we do need and what we can actually reliably record. In practice it means that we abandon the prospect of storing much more refined data for now. We don't have the necessary information nor code using it right now. So it seems safer to just use a clearer version of what we had so far. See the documentation changes for details. Differential Revision: https://phab.mercurial-scm.org/D11557
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Fri, 01 Oct 2021 20:35:30 +0200
parents 79bc60ca5946
children fb3b41d583c2
comparison
equal deleted inserted replaced
48137:25836b0029f5 48138:38488d488ec1
50 /* We do all the initialization here and not a tp_init function because 50 /* We do all the initialization here and not a tp_init function because
51 * dirstate_item is immutable. */ 51 * dirstate_item is immutable. */
52 dirstateItemObject *t; 52 dirstateItemObject *t;
53 int wc_tracked; 53 int wc_tracked;
54 int p1_tracked; 54 int p1_tracked;
55 int p2_tracked; 55 int p2_info;
56 int merged; 56 int has_meaningful_data;
57 int clean_p1; 57 int has_meaningful_mtime;
58 int clean_p2; 58 int mode;
59 int possibly_dirty; 59 int size;
60 int mtime;
60 PyObject *parentfiledata; 61 PyObject *parentfiledata;
61 static char *keywords_name[] = { 62 static char *keywords_name[] = {
62 "wc_tracked", "p1_tracked", "p2_tracked", 63 "wc_tracked",
63 "merged", "clean_p1", "clean_p2", 64 "p1_tracked",
64 "possibly_dirty", "parentfiledata", NULL, 65 "p2_info",
66 "has_meaningful_data",
67 "has_meaningful_mtime",
68 "parentfiledata",
69 NULL,
65 }; 70 };
66 wc_tracked = 0; 71 wc_tracked = 0;
67 p1_tracked = 0; 72 p1_tracked = 0;
68 p2_tracked = 0; 73 p2_info = 0;
69 merged = 0; 74 has_meaningful_mtime = 1;
70 clean_p1 = 0; 75 has_meaningful_data = 1;
71 clean_p2 = 0;
72 possibly_dirty = 0;
73 parentfiledata = Py_None; 76 parentfiledata = Py_None;
74 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iiiiiiiO", keywords_name, 77 if (!PyArg_ParseTupleAndKeywords(
75 &wc_tracked, &p1_tracked, &p2_tracked, 78 args, kwds, "|iiiiiO", keywords_name, &wc_tracked, &p1_tracked,
76 &merged, &clean_p1, &clean_p2, 79 &p2_info, &has_meaningful_data, &has_meaningful_mtime,
77 &possibly_dirty, &parentfiledata 80 &parentfiledata)) {
78
79 )) {
80 return NULL;
81 }
82 if (merged && (clean_p1 || clean_p2)) {
83 PyErr_SetString(PyExc_RuntimeError,
84 "`merged` argument incompatible with "
85 "`clean_p1`/`clean_p2`");
86 return NULL; 81 return NULL;
87 } 82 }
88 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1); 83 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
89 if (!t) { 84 if (!t) {
90 return NULL; 85 return NULL;
95 t->flags |= dirstate_flag_wc_tracked; 90 t->flags |= dirstate_flag_wc_tracked;
96 } 91 }
97 if (p1_tracked) { 92 if (p1_tracked) {
98 t->flags |= dirstate_flag_p1_tracked; 93 t->flags |= dirstate_flag_p1_tracked;
99 } 94 }
100 if (p2_tracked) { 95 if (p2_info) {
101 t->flags |= dirstate_flag_p2_tracked; 96 t->flags |= dirstate_flag_p2_info;
102 } 97 }
103 if (possibly_dirty) { 98
104 t->flags |= dirstate_flag_possibly_dirty;
105 }
106 if (merged) {
107 t->flags |= dirstate_flag_merged;
108 }
109 if (clean_p1) {
110 t->flags |= dirstate_flag_clean_p1;
111 }
112 if (clean_p2) {
113 t->flags |= dirstate_flag_clean_p2;
114 }
115 t->mode = 0;
116 t->size = dirstate_v1_nonnormal;
117 t->mtime = ambiguous_time;
118 if (parentfiledata != Py_None) { 99 if (parentfiledata != Py_None) {
119 if (!PyTuple_CheckExact(parentfiledata)) { 100 if (!PyTuple_CheckExact(parentfiledata)) {
120 PyErr_SetString( 101 PyErr_SetString(
121 PyExc_TypeError, 102 PyExc_TypeError,
122 "parentfiledata should be a Tuple or None"); 103 "parentfiledata should be a Tuple or None");
123 return NULL; 104 return NULL;
124 } 105 }
125 t->mode = 106 mode = (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 0));
126 (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 0)); 107 size = (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 1));
127 t->size = 108 mtime = (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 2));
128 (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 1)); 109 } else {
129 t->mtime = 110 has_meaningful_data = 0;
130 (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 2)); 111 has_meaningful_mtime = 0;
112 }
113 if (has_meaningful_data) {
114 t->flags |= dirstate_flag_has_meaningful_data;
115 t->mode = mode;
116 t->size = size;
117 } else {
118 t->mode = 0;
119 t->size = 0;
120 }
121 if (has_meaningful_mtime) {
122 t->flags |= dirstate_flag_has_meaningful_mtime;
123 t->mtime = mtime;
124 } else {
125 t->mtime = 0;
131 } 126 }
132 return (PyObject *)t; 127 return (PyObject *)t;
133 } 128 }
134 129
135 static void dirstate_item_dealloc(PyObject *o) 130 static void dirstate_item_dealloc(PyObject *o)
140 static inline bool dirstate_item_c_tracked(dirstateItemObject *self) 135 static inline bool dirstate_item_c_tracked(dirstateItemObject *self)
141 { 136 {
142 return (self->flags & dirstate_flag_wc_tracked); 137 return (self->flags & dirstate_flag_wc_tracked);
143 } 138 }
144 139
140 static inline bool dirstate_item_c_any_tracked(dirstateItemObject *self)
141 {
142 const unsigned char mask = dirstate_flag_wc_tracked |
143 dirstate_flag_p1_tracked |
144 dirstate_flag_p2_info;
145 return (self->flags & mask);
146 }
147
145 static inline bool dirstate_item_c_added(dirstateItemObject *self) 148 static inline bool dirstate_item_c_added(dirstateItemObject *self)
146 { 149 {
147 unsigned char mask = 150 const unsigned char mask =
148 (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked | 151 (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
149 dirstate_flag_p2_tracked); 152 dirstate_flag_p2_info);
150 unsigned char target = dirstate_flag_wc_tracked; 153 const unsigned char target = dirstate_flag_wc_tracked;
151 return (self->flags & mask) == target; 154 return (self->flags & mask) == target;
152 } 155 }
153 156
154 static inline bool dirstate_item_c_removed(dirstateItemObject *self) 157 static inline bool dirstate_item_c_removed(dirstateItemObject *self)
155 { 158 {
156 if (self->flags & dirstate_flag_wc_tracked) { 159 if (self->flags & dirstate_flag_wc_tracked) {
157 return false; 160 return false;
158 } 161 }
159 return (self->flags & 162 return (self->flags &
160 (dirstate_flag_p1_tracked | dirstate_flag_p2_tracked)); 163 (dirstate_flag_p1_tracked | dirstate_flag_p2_info));
161 } 164 }
162 165
163 static inline bool dirstate_item_c_merged(dirstateItemObject *self) 166 static inline bool dirstate_item_c_merged(dirstateItemObject *self)
164 { 167 {
165 return ((self->flags & dirstate_flag_wc_tracked) && 168 return ((self->flags & dirstate_flag_wc_tracked) &&
166 (self->flags & dirstate_flag_merged)); 169 (self->flags & dirstate_flag_p1_tracked) &&
170 (self->flags & dirstate_flag_p2_info));
167 } 171 }
168 172
169 static inline bool dirstate_item_c_from_p2(dirstateItemObject *self) 173 static inline bool dirstate_item_c_from_p2(dirstateItemObject *self)
170 { 174 {
171 if (!dirstate_item_c_tracked(self)) { 175 return ((self->flags & dirstate_flag_wc_tracked) &&
172 return false; 176 !(self->flags & dirstate_flag_p1_tracked) &&
173 } 177 (self->flags & dirstate_flag_p2_info));
174 return (self->flags & dirstate_flag_clean_p2);
175 } 178 }
176 179
177 static inline char dirstate_item_c_v1_state(dirstateItemObject *self) 180 static inline char dirstate_item_c_v1_state(dirstateItemObject *self)
178 { 181 {
179 if (dirstate_item_c_removed(self)) { 182 if (dirstate_item_c_removed(self)) {
187 } 190 }
188 } 191 }
189 192
190 static inline int dirstate_item_c_v1_mode(dirstateItemObject *self) 193 static inline int dirstate_item_c_v1_mode(dirstateItemObject *self)
191 { 194 {
192 return self->mode; 195 if (self->flags & dirstate_flag_has_meaningful_data) {
196 return self->mode;
197 } else {
198 return 0;
199 }
193 } 200 }
194 201
195 static inline int dirstate_item_c_v1_size(dirstateItemObject *self) 202 static inline int dirstate_item_c_v1_size(dirstateItemObject *self)
196 { 203 {
197 if (dirstate_item_c_removed(self) && 204 if (!(self->flags & dirstate_flag_wc_tracked) &&
198 (self->flags & dirstate_flag_merged)) { 205 (self->flags & dirstate_flag_p2_info)) {
199 return dirstate_v1_nonnormal; 206 if (self->flags & dirstate_flag_p1_tracked) {
200 } else if (dirstate_item_c_removed(self) && 207 return dirstate_v1_nonnormal;
201 (self->flags & dirstate_flag_clean_p2)) { 208 } else {
202 return dirstate_v1_from_p2; 209 return dirstate_v1_from_p2;
210 }
203 } else if (dirstate_item_c_removed(self)) { 211 } else if (dirstate_item_c_removed(self)) {
204 return 0; 212 return 0;
205 } else if (dirstate_item_c_merged(self)) { 213 } else if (self->flags & dirstate_flag_p2_info) {
206 return dirstate_v1_from_p2; 214 return dirstate_v1_from_p2;
207 } else if (dirstate_item_c_added(self)) { 215 } else if (dirstate_item_c_added(self)) {
208 return dirstate_v1_nonnormal; 216 return dirstate_v1_nonnormal;
209 } else if (dirstate_item_c_from_p2(self)) { 217 } else if (self->flags & dirstate_flag_has_meaningful_data) {
210 return dirstate_v1_from_p2;
211 } else if (self->flags & dirstate_flag_possibly_dirty) {
212 return self->size; /* NON NORMAL ? */
213 } else {
214 return self->size; 218 return self->size;
219 } else {
220 return dirstate_v1_nonnormal;
215 } 221 }
216 } 222 }
217 223
218 static inline int dirstate_item_c_v1_mtime(dirstateItemObject *self) 224 static inline int dirstate_item_c_v1_mtime(dirstateItemObject *self)
219 { 225 {
220 if (dirstate_item_c_removed(self)) { 226 if (dirstate_item_c_removed(self)) {
221 return 0; 227 return 0;
222 } else if (self->flags & dirstate_flag_possibly_dirty) { 228 } else if (!(self->flags & dirstate_flag_has_meaningful_mtime) ||
223 return ambiguous_time; 229 !(self->flags & dirstate_flag_p1_tracked) ||
224 } else if (dirstate_item_c_merged(self)) { 230 !(self->flags & dirstate_flag_wc_tracked) ||
225 return ambiguous_time; 231 (self->flags & dirstate_flag_p2_info)) {
226 } else if (dirstate_item_c_added(self)) {
227 return ambiguous_time;
228 } else if (dirstate_item_c_from_p2(self)) {
229 return ambiguous_time; 232 return ambiguous_time;
230 } else { 233 } else {
231 return self->mtime; 234 return self->mtime;
232 } 235 }
233 } 236 }
276 dirstateItemObject *t = 279 dirstateItemObject *t =
277 PyObject_New(dirstateItemObject, &dirstateItemType); 280 PyObject_New(dirstateItemObject, &dirstateItemType);
278 if (!t) { 281 if (!t) {
279 return NULL; 282 return NULL;
280 } 283 }
284 t->flags = 0;
285 t->mode = 0;
286 t->size = 0;
287 t->mtime = 0;
281 288
282 if (state == 'm') { 289 if (state == 'm') {
283 t->flags = 290 t->flags = (dirstate_flag_wc_tracked |
284 (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked | 291 dirstate_flag_p1_tracked | dirstate_flag_p2_info);
285 dirstate_flag_p2_tracked | dirstate_flag_merged);
286 t->mode = 0;
287 t->size = dirstate_v1_from_p2;
288 t->mtime = ambiguous_time;
289 } else if (state == 'a') { 292 } else if (state == 'a') {
290 t->flags = dirstate_flag_wc_tracked; 293 t->flags = dirstate_flag_wc_tracked;
291 t->mode = 0;
292 t->size = dirstate_v1_nonnormal;
293 t->mtime = ambiguous_time;
294 } else if (state == 'r') { 294 } else if (state == 'r') {
295 t->mode = 0;
296 t->size = 0;
297 t->mtime = 0;
298 if (size == dirstate_v1_nonnormal) { 295 if (size == dirstate_v1_nonnormal) {
299 t->flags = 296 t->flags =
300 (dirstate_flag_p1_tracked | 297 dirstate_flag_p1_tracked | dirstate_flag_p2_info;
301 dirstate_flag_p2_tracked | dirstate_flag_merged);
302 } else if (size == dirstate_v1_from_p2) { 298 } else if (size == dirstate_v1_from_p2) {
303 t->flags = 299 t->flags = dirstate_flag_p2_info;
304 (dirstate_flag_p2_tracked | dirstate_flag_clean_p2);
305 } else { 300 } else {
306 t->flags = dirstate_flag_p1_tracked; 301 t->flags = dirstate_flag_p1_tracked;
307 } 302 }
308 } else if (state == 'n') { 303 } else if (state == 'n') {
309 if (size == dirstate_v1_from_p2) { 304 if (size == dirstate_v1_from_p2) {
310 t->flags = 305 t->flags =
311 (dirstate_flag_wc_tracked | 306 dirstate_flag_wc_tracked | dirstate_flag_p2_info;
312 dirstate_flag_p2_tracked | dirstate_flag_clean_p2);
313 t->mode = 0;
314 t->size = dirstate_v1_from_p2;
315 t->mtime = ambiguous_time;
316 } else if (size == dirstate_v1_nonnormal) { 307 } else if (size == dirstate_v1_nonnormal) {
317 t->flags = (dirstate_flag_wc_tracked | 308 t->flags =
318 dirstate_flag_p1_tracked | 309 dirstate_flag_wc_tracked | dirstate_flag_p1_tracked;
319 dirstate_flag_possibly_dirty);
320 t->mode = 0;
321 t->size = dirstate_v1_nonnormal;
322 t->mtime = ambiguous_time;
323 } else if (mtime == ambiguous_time) { 310 } else if (mtime == ambiguous_time) {
324 t->flags = (dirstate_flag_wc_tracked | 311 t->flags = (dirstate_flag_wc_tracked |
325 dirstate_flag_p1_tracked | 312 dirstate_flag_p1_tracked |
326 dirstate_flag_possibly_dirty); 313 dirstate_flag_has_meaningful_data);
327 t->mode = mode; 314 t->mode = mode;
328 t->size = size; 315 t->size = size;
329 t->mtime = 0;
330 } else { 316 } else {
331 t->flags = (dirstate_flag_wc_tracked | 317 t->flags = (dirstate_flag_wc_tracked |
332 dirstate_flag_p1_tracked); 318 dirstate_flag_p1_tracked |
319 dirstate_flag_has_meaningful_data |
320 dirstate_flag_has_meaningful_mtime);
333 t->mode = mode; 321 t->mode = mode;
334 t->size = size; 322 t->size = size;
335 t->mtime = mtime; 323 t->mtime = mtime;
336 } 324 }
337 } else { 325 } else {
369 if (!t) { 357 if (!t) {
370 return NULL; 358 return NULL;
371 } 359 }
372 t->flags = dirstate_flag_wc_tracked; 360 t->flags = dirstate_flag_wc_tracked;
373 t->mode = 0; 361 t->mode = 0;
374 t->size = dirstate_v1_nonnormal; 362 t->size = 0;
375 t->mtime = ambiguous_time; 363 t->mtime = 0;
376 return (PyObject *)t; 364 return (PyObject *)t;
377 }; 365 };
378 366
379 /* constructor to help legacy API to build a new "merged" item 367 /* constructor to help legacy API to build a new "merged" item
380 368
385 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1); 373 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
386 if (!t) { 374 if (!t) {
387 return NULL; 375 return NULL;
388 } 376 }
389 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked | 377 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
390 dirstate_flag_p2_tracked | dirstate_flag_merged); 378 dirstate_flag_p2_info);
391 t->mode = 0; 379 t->mode = 0;
392 t->size = dirstate_v1_from_p2; 380 t->size = 0;
393 t->mtime = ambiguous_time; 381 t->mtime = 0;
394 return (PyObject *)t; 382 return (PyObject *)t;
395 }; 383 };
396 384
397 /* constructor to help legacy API to build a new "from_p2" item 385 /* constructor to help legacy API to build a new "from_p2" item
398 386
404 dirstateItemObject *t; 392 dirstateItemObject *t;
405 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1); 393 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
406 if (!t) { 394 if (!t) {
407 return NULL; 395 return NULL;
408 } 396 }
409 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p2_tracked | 397 t->flags = dirstate_flag_wc_tracked | dirstate_flag_p2_info;
410 dirstate_flag_clean_p2);
411 t->mode = 0; 398 t->mode = 0;
412 t->size = dirstate_v1_from_p2; 399 t->size = 0;
413 t->mtime = ambiguous_time; 400 t->mtime = 0;
414 return (PyObject *)t; 401 return (PyObject *)t;
415 }; 402 };
416 403
417 /* constructor to help legacy API to build a new "possibly" item 404 /* constructor to help legacy API to build a new "possibly" item
418 405
424 dirstateItemObject *t; 411 dirstateItemObject *t;
425 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1); 412 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
426 if (!t) { 413 if (!t) {
427 return NULL; 414 return NULL;
428 } 415 }
429 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked | 416 t->flags = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked;
430 dirstate_flag_possibly_dirty);
431 t->mode = 0; 417 t->mode = 0;
432 t->size = dirstate_v1_nonnormal; 418 t->size = 0;
433 t->mtime = ambiguous_time; 419 t->mtime = 0;
434 return (PyObject *)t; 420 return (PyObject *)t;
435 }; 421 };
436 422
437 /* constructor to help legacy API to build a new "normal" item 423 /* constructor to help legacy API to build a new "normal" item
438 424
460 446
461 /* This means the next status call will have to actually check its content 447 /* This means the next status call will have to actually check its content
462 to make sure it is correct. */ 448 to make sure it is correct. */
463 static PyObject *dirstate_item_set_possibly_dirty(dirstateItemObject *self) 449 static PyObject *dirstate_item_set_possibly_dirty(dirstateItemObject *self)
464 { 450 {
465 self->flags |= dirstate_flag_possibly_dirty; 451 self->flags &= ~dirstate_flag_has_meaningful_mtime;
466 Py_RETURN_NONE; 452 Py_RETURN_NONE;
467 } 453 }
468 454
469 /* See docstring of the python implementation for details */ 455 /* See docstring of the python implementation for details */
470 static PyObject *dirstate_item_set_clean(dirstateItemObject *self, 456 static PyObject *dirstate_item_set_clean(dirstateItemObject *self,
472 { 458 {
473 int size, mode, mtime; 459 int size, mode, mtime;
474 if (!PyArg_ParseTuple(args, "iii", &mode, &size, &mtime)) { 460 if (!PyArg_ParseTuple(args, "iii", &mode, &size, &mtime)) {
475 return NULL; 461 return NULL;
476 } 462 }
477 self->flags = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked; 463 self->flags = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
464 dirstate_flag_has_meaningful_data |
465 dirstate_flag_has_meaningful_mtime;
478 self->mode = mode; 466 self->mode = mode;
479 self->size = size; 467 self->size = size;
480 self->mtime = mtime; 468 self->mtime = mtime;
481 Py_RETURN_NONE; 469 Py_RETURN_NONE;
482 } 470 }
483 471
484 static PyObject *dirstate_item_set_tracked(dirstateItemObject *self) 472 static PyObject *dirstate_item_set_tracked(dirstateItemObject *self)
485 { 473 {
486 self->flags |= dirstate_flag_wc_tracked; 474 self->flags |= dirstate_flag_wc_tracked;
487 self->flags |= dirstate_flag_possibly_dirty; 475 self->flags &= ~dirstate_flag_has_meaningful_mtime;
488 /* size = None on the python size turn into size = NON_NORMAL when
489 * accessed. So the next line is currently required, but a some future
490 * clean up would be welcome. */
491 self->size = dirstate_v1_nonnormal;
492 Py_RETURN_NONE; 476 Py_RETURN_NONE;
493 } 477 }
494 478
495 static PyObject *dirstate_item_set_untracked(dirstateItemObject *self) 479 static PyObject *dirstate_item_set_untracked(dirstateItemObject *self)
496 { 480 {
501 Py_RETURN_NONE; 485 Py_RETURN_NONE;
502 } 486 }
503 487
504 static PyObject *dirstate_item_drop_merge_data(dirstateItemObject *self) 488 static PyObject *dirstate_item_drop_merge_data(dirstateItemObject *self)
505 { 489 {
506 if (dirstate_item_c_merged(self) || dirstate_item_c_from_p2(self)) { 490 if (self->flags & dirstate_flag_p2_info) {
507 if (dirstate_item_c_merged(self)) { 491 self->flags &= ~(dirstate_flag_p2_info |
508 self->flags |= dirstate_flag_p1_tracked; 492 dirstate_flag_has_meaningful_data |
509 } else { 493 dirstate_flag_has_meaningful_mtime);
510 self->flags &= ~dirstate_flag_p1_tracked;
511 }
512 self->flags &=
513 ~(dirstate_flag_merged | dirstate_flag_clean_p1 |
514 dirstate_flag_clean_p2 | dirstate_flag_p2_tracked);
515 self->flags |= dirstate_flag_possibly_dirty;
516 self->mode = 0; 494 self->mode = 0;
517 self->mtime = 0; 495 self->mtime = 0;
518 /* size = None on the python size turn into size = NON_NORMAL 496 self->size = 0;
519 * when accessed. So the next line is currently required, but a
520 * some future clean up would be welcome. */
521 self->size = dirstate_v1_nonnormal;
522 } 497 }
523 Py_RETURN_NONE; 498 Py_RETURN_NONE;
524 } 499 }
525 static PyMethodDef dirstate_item_methods[] = { 500 static PyMethodDef dirstate_item_methods[] = {
526 {"v1_state", (PyCFunction)dirstate_item_v1_state, METH_NOARGS, 501 {"v1_state", (PyCFunction)dirstate_item_v1_state, METH_NOARGS,
622 597
623 static PyObject *dirstate_item_get_maybe_clean(dirstateItemObject *self) 598 static PyObject *dirstate_item_get_maybe_clean(dirstateItemObject *self)
624 { 599 {
625 if (!(self->flags & dirstate_flag_wc_tracked)) { 600 if (!(self->flags & dirstate_flag_wc_tracked)) {
626 Py_RETURN_FALSE; 601 Py_RETURN_FALSE;
627 } else if (dirstate_item_c_added(self)) { 602 } else if (!(self->flags & dirstate_flag_p1_tracked)) {
628 Py_RETURN_FALSE; 603 Py_RETURN_FALSE;
629 } else if (self->flags & dirstate_flag_merged) { 604 } else if (self->flags & dirstate_flag_p2_info) {
630 Py_RETURN_FALSE; 605 Py_RETURN_FALSE;
631 } else if (self->flags & dirstate_flag_clean_p2) {
632 Py_RETURN_FALSE;
633 } else { 606 } else {
634 Py_RETURN_TRUE; 607 Py_RETURN_TRUE;
635 } 608 }
636 }; 609 };
637 610
638 static PyObject *dirstate_item_get_any_tracked(dirstateItemObject *self) 611 static PyObject *dirstate_item_get_any_tracked(dirstateItemObject *self)
639 { 612 {
640 unsigned char mask = dirstate_flag_wc_tracked | 613 if (dirstate_item_c_any_tracked(self)) {
641 dirstate_flag_p1_tracked |
642 dirstate_flag_p2_tracked;
643 if ((self->flags & mask) != 0) {
644 Py_RETURN_TRUE; 614 Py_RETURN_TRUE;
645 } else { 615 } else {
646 Py_RETURN_FALSE; 616 Py_RETURN_FALSE;
647 } 617 }
648 }; 618 };