##// END OF EJS Templates
dirstate-item: change the internal storage and constructor value...
marmoute -
r48950:38488d48 default
parent child Browse files
Show More
@@ -52,37 +52,32 b' static PyObject *dirstate_item_new(PyTyp'
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);
@@ -97,24 +92,10 b' static PyObject *dirstate_item_new(PyTyp'
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 }
103 if (possibly_dirty) {
104 t->flags |= dirstate_flag_possibly_dirty;
105 }
106 if (merged) {
107 t->flags |= dirstate_flag_merged;
108 }
97 }
109 if (clean_p1) {
98
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(
@@ -122,12 +103,26 b' static PyObject *dirstate_item_new(PyTyp'
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 }
@@ -142,12 +137,20 b' static inline bool dirstate_item_c_track'
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
@@ -157,21 +160,21 b' static inline bool dirstate_item_c_remov'
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)
@@ -189,29 +192,32 b' static inline char dirstate_item_c_v1_st'
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;
218 return self->size;
211 } else if (self->flags & dirstate_flag_possibly_dirty) {
212 return self->size; /* NON NORMAL ? */
213 } else {
219 } else {
214 return self->size;
220 return dirstate_v1_nonnormal;
215 }
221 }
216 }
222 }
217
223
@@ -219,13 +225,10 b' static inline int dirstate_item_c_v1_mti'
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;
@@ -278,58 +281,43 b' dirstate_item_from_v1_data(char state, i'
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;
@@ -371,8 +359,8 b' static PyObject *dirstate_item_new_added'
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
@@ -387,10 +375,10 b' static PyObject *dirstate_item_new_merge'
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
@@ -406,11 +394,10 b' static PyObject *dirstate_item_new_from_'
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
@@ -426,11 +413,10 b' static PyObject *dirstate_item_new_possi'
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
@@ -462,7 +448,7 b' static PyObject *dirstate_item_new_norma'
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
@@ -474,7 +460,9 b' static PyObject *dirstate_item_set_clean'
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;
@@ -484,11 +472,7 b' static PyObject *dirstate_item_set_clean'
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
@@ -503,22 +487,13 b' static PyObject *dirstate_item_set_untra'
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 }
@@ -624,11 +599,9 b' static PyObject *dirstate_item_get_maybe'
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;
631 } else if (self->flags & dirstate_flag_clean_p2) {
632 Py_RETURN_FALSE;
605 Py_RETURN_FALSE;
633 } else {
606 } else {
634 Py_RETURN_TRUE;
607 Py_RETURN_TRUE;
@@ -637,10 +610,7 b' static PyObject *dirstate_item_get_maybe'
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;
@@ -33,11 +33,9 b' typedef struct {'
33
33
34 static const unsigned char dirstate_flag_wc_tracked = 1;
34 static const unsigned char dirstate_flag_wc_tracked = 1;
35 static const unsigned char dirstate_flag_p1_tracked = 1 << 1;
35 static const unsigned char dirstate_flag_p1_tracked = 1 << 1;
36 static const unsigned char dirstate_flag_p2_tracked = 1 << 2;
36 static const unsigned char dirstate_flag_p2_info = 1 << 2;
37 static const unsigned char dirstate_flag_possibly_dirty = 1 << 3;
37 static const unsigned char dirstate_flag_has_meaningful_data = 1 << 3;
38 static const unsigned char dirstate_flag_merged = 1 << 4;
38 static const unsigned char dirstate_flag_has_meaningful_mtime = 1 << 4;
39 static const unsigned char dirstate_flag_clean_p1 = 1 << 5;
40 static const unsigned char dirstate_flag_clean_p2 = 1 << 6;
41
39
42 extern PyTypeObject dirstateItemType;
40 extern PyTypeObject dirstateItemType;
43 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType)
41 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType)
@@ -137,14 +137,7 b' class _dirstatemapcommon(object):'
137 if entry is None:
137 if entry is None:
138 self._dirs_incr(filename)
138 self._dirs_incr(filename)
139 entry = DirstateItem(
139 entry = DirstateItem(
140 p1_tracked=False,
141 p2_tracked=False,
142 wc_tracked=True,
140 wc_tracked=True,
143 merged=False,
144 clean_p1=False,
145 clean_p2=False,
146 possibly_dirty=False,
147 parentfiledata=None,
148 )
141 )
149
142
150 self._insert_entry(filename, entry)
143 self._insert_entry(filename, entry)
@@ -208,37 +201,20 b' class _dirstatemapcommon(object):'
208 self._drop_entry(filename)
201 self._drop_entry(filename)
209 self._dirs_decr(filename, old_entry=old_entry)
202 self._dirs_decr(filename, old_entry=old_entry)
210 return
203 return
211 elif merged:
204
212 pass
205 p2_info = merged or clean_p2
213 elif not (p1_tracked or p2_tracked) and wc_tracked:
206 if merged:
214 pass # file is added, nothing special to adjust
207 assert p1_tracked
215 elif (p1_tracked or p2_tracked) and not wc_tracked:
208
216 pass
209 has_meaningful_mtime = not possibly_dirty
217 elif clean_p2 and wc_tracked:
218 pass
219 elif not p1_tracked and p2_tracked and wc_tracked:
220 clean_p2 = True
221 elif possibly_dirty:
222 pass
223 elif wc_tracked:
224 # this is a "normal" file
225 if parentfiledata is None:
226 msg = b'failed to pass parentfiledata for a normal file: %s'
227 msg %= filename
228 raise error.ProgrammingError(msg)
229 else:
230 assert False, 'unreachable'
231
210
232 old_entry = self._map.get(filename)
211 old_entry = self._map.get(filename)
233 self._dirs_incr(filename, old_entry)
212 self._dirs_incr(filename, old_entry)
234 entry = DirstateItem(
213 entry = DirstateItem(
235 wc_tracked=wc_tracked,
214 wc_tracked=wc_tracked,
236 p1_tracked=p1_tracked,
215 p1_tracked=p1_tracked,
237 p2_tracked=p2_tracked,
216 p2_info=p2_info,
238 merged=merged,
217 has_meaningful_mtime=has_meaningful_mtime,
239 clean_p1=clean_p1,
240 clean_p2=clean_p2,
241 possibly_dirty=possibly_dirty,
242 parentfiledata=parentfiledata,
218 parentfiledata=parentfiledata,
243 )
219 )
244 self._insert_entry(filename, entry)
220 self._insert_entry(filename, entry)
@@ -53,36 +53,32 b' class DirstateItem(object):'
53 # about file tracking
53 # about file tracking
54 - wc_tracked: is the file tracked by the working copy
54 - wc_tracked: is the file tracked by the working copy
55 - p1_tracked: is the file tracked in working copy first parent
55 - p1_tracked: is the file tracked in working copy first parent
56 - p2_tracked: is the file tracked in working copy second parent
56 - p2_info: the file has been involved in some merge operation. Either
57
57 because it was actually merged, or because the p2 version was
58 # about what possible merge action related to this file
58 ahead, or because some renamed moved it there. In either case
59 - clean_p1: merge picked the file content from p1
59 `hg status` will want it displayed as modified.
60 - clean_p2: merge picked the file content from p2
61 - merged: file gather changes from both side.
62
60
63 # about the file state expected from p1 manifest:
61 # about the file state expected from p1 manifest:
64 - mode: the file mode in p1
62 - mode: the file mode in p1
65 - size: the file size in p1
63 - size: the file size in p1
66
64
65 These value can be set to None, which mean we don't have a meaningful value
66 to compare with. Either because we don't really care about them as there
67 `status` is known without having to look at the disk or because we don't
68 know these right now and a full comparison will be needed to find out if
69 the file is clean.
70
67 # about the file state on disk last time we saw it:
71 # about the file state on disk last time we saw it:
68 - mtime: the last known clean mtime for the file.
72 - mtime: the last known clean mtime for the file.
69
73
70 The last three item (mode, size and mtime) can be None if no meaningful (or
74 This value can be set to None if no cachable state exist. Either because we
71 trusted) value exists.
75 do not care (see previous section) or because we could not cache something
72
76 yet.
73 """
77 """
74
78
75 _wc_tracked = attr.ib()
79 _wc_tracked = attr.ib()
76 _p1_tracked = attr.ib()
80 _p1_tracked = attr.ib()
77 _p2_tracked = attr.ib()
81 _p2_info = attr.ib()
78 # the three item above should probably be combined
79 #
80 # However it is unclear if they properly cover some of the most advanced
81 # merge case. So we should probably wait on this to be settled.
82 _merged = attr.ib()
83 _clean_p1 = attr.ib()
84 _clean_p2 = attr.ib()
85 _possibly_dirty = attr.ib()
86 _mode = attr.ib()
82 _mode = attr.ib()
87 _size = attr.ib()
83 _size = attr.ib()
88 _mtime = attr.ib()
84 _mtime = attr.ib()
@@ -91,32 +87,25 b' class DirstateItem(object):'
91 self,
87 self,
92 wc_tracked=False,
88 wc_tracked=False,
93 p1_tracked=False,
89 p1_tracked=False,
94 p2_tracked=False,
90 p2_info=False,
95 merged=False,
91 has_meaningful_data=True,
96 clean_p1=False,
92 has_meaningful_mtime=True,
97 clean_p2=False,
98 possibly_dirty=False,
99 parentfiledata=None,
93 parentfiledata=None,
100 ):
94 ):
101 if merged and (clean_p1 or clean_p2):
102 msg = b'`merged` argument incompatible with `clean_p1`/`clean_p2`'
103 raise error.ProgrammingError(msg)
104
105 assert not (merged and not p1_tracked)
106 self._wc_tracked = wc_tracked
95 self._wc_tracked = wc_tracked
107 self._p1_tracked = p1_tracked
96 self._p1_tracked = p1_tracked
108 self._p2_tracked = p2_tracked
97 self._p2_info = p2_info
109 self._merged = merged
98
110 self._clean_p1 = clean_p1
99 self._mode = None
111 self._clean_p2 = clean_p2
100 self._size = None
112 self._possibly_dirty = possibly_dirty
101 self._mtime = None
113 if parentfiledata is None:
102 if parentfiledata is None:
114 self._mode = None
103 has_meaningful_mtime = False
115 self._size = None
104 has_meaningful_data = False
116 self._mtime = None
105 if has_meaningful_data:
117 else:
118 self._mode = parentfiledata[0]
106 self._mode = parentfiledata[0]
119 self._size = parentfiledata[1]
107 self._size = parentfiledata[1]
108 if has_meaningful_mtime:
120 self._mtime = parentfiledata[2]
109 self._mtime = parentfiledata[2]
121
110
122 @classmethod
111 @classmethod
@@ -125,11 +114,7 b' class DirstateItem(object):'
125
114
126 Should eventually be removed
115 Should eventually be removed
127 """
116 """
128 instance = cls()
117 return cls(wc_tracked=True)
129 instance._wc_tracked = True
130 instance._p1_tracked = False
131 instance._p2_tracked = False
132 return instance
133
118
134 @classmethod
119 @classmethod
135 def new_merged(cls):
120 def new_merged(cls):
@@ -137,12 +122,7 b' class DirstateItem(object):'
137
122
138 Should eventually be removed
123 Should eventually be removed
139 """
124 """
140 instance = cls()
125 return cls(wc_tracked=True, p1_tracked=True, p2_info=True)
141 instance._wc_tracked = True
142 instance._p1_tracked = True # might not be True because of rename ?
143 instance._p2_tracked = True # might not be True because of rename ?
144 instance._merged = True
145 return instance
146
126
147 @classmethod
127 @classmethod
148 def new_from_p2(cls):
128 def new_from_p2(cls):
@@ -150,12 +130,7 b' class DirstateItem(object):'
150
130
151 Should eventually be removed
131 Should eventually be removed
152 """
132 """
153 instance = cls()
133 return cls(wc_tracked=True, p2_info=True)
154 instance._wc_tracked = True
155 instance._p1_tracked = False # might actually be True
156 instance._p2_tracked = True
157 instance._clean_p2 = True
158 return instance
159
134
160 @classmethod
135 @classmethod
161 def new_possibly_dirty(cls):
136 def new_possibly_dirty(cls):
@@ -163,11 +138,7 b' class DirstateItem(object):'
163
138
164 Should eventually be removed
139 Should eventually be removed
165 """
140 """
166 instance = cls()
141 return cls(wc_tracked=True, p1_tracked=True)
167 instance._wc_tracked = True
168 instance._p1_tracked = True
169 instance._possibly_dirty = True
170 return instance
171
142
172 @classmethod
143 @classmethod
173 def new_normal(cls, mode, size, mtime):
144 def new_normal(cls, mode, size, mtime):
@@ -177,13 +148,11 b' class DirstateItem(object):'
177 """
148 """
178 assert size != FROM_P2
149 assert size != FROM_P2
179 assert size != NONNORMAL
150 assert size != NONNORMAL
180 instance = cls()
151 return cls(
181 instance._wc_tracked = True
152 wc_tracked=True,
182 instance._p1_tracked = True
153 p1_tracked=True,
183 instance._mode = mode
154 parentfiledata=(mode, size, mtime),
184 instance._size = size
155 )
185 instance._mtime = mtime
186 return instance
187
156
188 @classmethod
157 @classmethod
189 def from_v1_data(cls, state, mode, size, mtime):
158 def from_v1_data(cls, state, mode, size, mtime):
@@ -197,25 +166,16 b' class DirstateItem(object):'
197 elif state == b'a':
166 elif state == b'a':
198 return cls.new_added()
167 return cls.new_added()
199 elif state == b'r':
168 elif state == b'r':
200 instance = cls()
201 instance._wc_tracked = False
202 if size == NONNORMAL:
169 if size == NONNORMAL:
203 instance._merged = True
170 p1_tracked = True
204 instance._p1_tracked = (
171 p2_info = True
205 True # might not be True because of rename ?
206 )
207 instance._p2_tracked = (
208 True # might not be True because of rename ?
209 )
210 elif size == FROM_P2:
172 elif size == FROM_P2:
211 instance._clean_p2 = True
173 p1_tracked = False
212 instance._p1_tracked = (
174 p2_info = True
213 False # We actually don't know (file history)
214 )
215 instance._p2_tracked = True
216 else:
175 else:
217 instance._p1_tracked = True
176 p1_tracked = True
218 return instance
177 p2_info = False
178 return cls(p1_tracked=p1_tracked, p2_info=p2_info)
219 elif state == b'n':
179 elif state == b'n':
220 if size == FROM_P2:
180 if size == FROM_P2:
221 return cls.new_from_p2()
181 return cls.new_from_p2()
@@ -224,7 +184,6 b' class DirstateItem(object):'
224 elif mtime == AMBIGUOUS_TIME:
184 elif mtime == AMBIGUOUS_TIME:
225 instance = cls.new_normal(mode, size, 42)
185 instance = cls.new_normal(mode, size, 42)
226 instance._mtime = None
186 instance._mtime = None
227 instance._possibly_dirty = True
228 return instance
187 return instance
229 else:
188 else:
230 return cls.new_normal(mode, size, mtime)
189 return cls.new_normal(mode, size, mtime)
@@ -237,7 +196,7 b' class DirstateItem(object):'
237 This means the next status call will have to actually check its content
196 This means the next status call will have to actually check its content
238 to make sure it is correct.
197 to make sure it is correct.
239 """
198 """
240 self._possibly_dirty = True
199 self._mtime = None
241
200
242 def set_clean(self, mode, size, mtime):
201 def set_clean(self, mode, size, mtime):
243 """mark a file as "clean" cancelling potential "possibly dirty call"
202 """mark a file as "clean" cancelling potential "possibly dirty call"
@@ -249,10 +208,6 b' class DirstateItem(object):'
249 """
208 """
250 self._wc_tracked = True
209 self._wc_tracked = True
251 self._p1_tracked = True
210 self._p1_tracked = True
252 self._p2_tracked = False # this might be wrong
253 self._merged = False
254 self._clean_p2 = False
255 self._possibly_dirty = False
256 self._mode = mode
211 self._mode = mode
257 self._size = size
212 self._size = size
258 self._mtime = mtime
213 self._mtime = mtime
@@ -263,11 +218,11 b' class DirstateItem(object):'
263 This will ultimately be called by command like `hg add`.
218 This will ultimately be called by command like `hg add`.
264 """
219 """
265 self._wc_tracked = True
220 self._wc_tracked = True
266 # `set_tracked` is replacing various `normallookup` call. So we set
221 # `set_tracked` is replacing various `normallookup` call. So we mark
267 # "possibly dirty" to stay on the safe side.
222 # the files as needing lookup
268 #
223 #
269 # Consider dropping this in the future in favor of something less broad.
224 # Consider dropping this in the future in favor of something less broad.
270 self._possibly_dirty = True
225 self._mtime = None
271
226
272 def set_untracked(self):
227 def set_untracked(self):
273 """mark a file as untracked in the working copy
228 """mark a file as untracked in the working copy
@@ -284,18 +239,11 b' class DirstateItem(object):'
284
239
285 This is to be call by the dirstatemap code when the second parent is dropped
240 This is to be call by the dirstatemap code when the second parent is dropped
286 """
241 """
287 if not (self.merged or self.from_p2):
242 if self._p2_info:
288 return
243 self._p2_info = False
289 self._p1_tracked = self.merged # why is this not already properly set ?
244 self._mode = None
290
245 self._size = None
291 self._merged = False
246 self._mtime = None
292 self._clean_p1 = False
293 self._clean_p2 = False
294 self._p2_tracked = False
295 self._possibly_dirty = True
296 self._mode = None
297 self._size = None
298 self._mtime = None
299
247
300 @property
248 @property
301 def mode(self):
249 def mode(self):
@@ -334,23 +282,21 b' class DirstateItem(object):'
334 @property
282 @property
335 def any_tracked(self):
283 def any_tracked(self):
336 """True is the file is tracked anywhere (wc or parents)"""
284 """True is the file is tracked anywhere (wc or parents)"""
337 return self._wc_tracked or self._p1_tracked or self._p2_tracked
285 return self._wc_tracked or self._p1_tracked or self._p2_info
338
286
339 @property
287 @property
340 def added(self):
288 def added(self):
341 """True if the file has been added"""
289 """True if the file has been added"""
342 return self._wc_tracked and not (self._p1_tracked or self._p2_tracked)
290 return self._wc_tracked and not (self._p1_tracked or self._p2_info)
343
291
344 @property
292 @property
345 def maybe_clean(self):
293 def maybe_clean(self):
346 """True if the file has a chance to be in the "clean" state"""
294 """True if the file has a chance to be in the "clean" state"""
347 if not self._wc_tracked:
295 if not self._wc_tracked:
348 return False
296 return False
349 elif self.added:
297 elif not self._p1_tracked:
350 return False
298 return False
351 elif self._merged:
299 elif self._p2_info:
352 return False
353 elif self._clean_p2:
354 return False
300 return False
355 return True
301 return True
356
302
@@ -360,7 +306,7 b' class DirstateItem(object):'
360
306
361 Should only be set if a merge is in progress in the dirstate
307 Should only be set if a merge is in progress in the dirstate
362 """
308 """
363 return self._wc_tracked and self._merged
309 return self._wc_tracked and self._p1_tracked and self._p2_info
364
310
365 @property
311 @property
366 def from_p2(self):
312 def from_p2(self):
@@ -370,18 +316,16 b' class DirstateItem(object):'
370
316
371 Should only be set if a merge is in progress in the dirstate
317 Should only be set if a merge is in progress in the dirstate
372 """
318 """
373 if not self._wc_tracked:
319 return self._wc_tracked and (not self._p1_tracked) and self._p2_info
374 return False
375 return self._clean_p2
376
320
377 @property
321 @property
378 def removed(self):
322 def removed(self):
379 """True if the file has been removed"""
323 """True if the file has been removed"""
380 return not self._wc_tracked and (self._p1_tracked or self._p2_tracked)
324 return not self._wc_tracked and (self._p1_tracked or self._p2_info)
381
325
382 def v1_state(self):
326 def v1_state(self):
383 """return a "state" suitable for v1 serialization"""
327 """return a "state" suitable for v1 serialization"""
384 if not (self._p1_tracked or self._p2_tracked or self._wc_tracked):
328 if not self.any_tracked:
385 # the object has no state to record, this is -currently-
329 # the object has no state to record, this is -currently-
386 # unsupported
330 # unsupported
387 raise RuntimeError('untracked item')
331 raise RuntimeError('untracked item')
@@ -404,9 +348,9 b' class DirstateItem(object):'
404 # the object has no state to record, this is -currently-
348 # the object has no state to record, this is -currently-
405 # unsupported
349 # unsupported
406 raise RuntimeError('untracked item')
350 raise RuntimeError('untracked item')
407 elif self.removed and self._merged:
351 elif self.removed and self._p1_tracked and self._p2_info:
408 return NONNORMAL
352 return NONNORMAL
409 elif self.removed and self._clean_p2:
353 elif self.removed and self._p2_info:
410 return FROM_P2
354 return FROM_P2
411 elif self.removed:
355 elif self.removed:
412 return 0
356 return 0
@@ -416,8 +360,8 b' class DirstateItem(object):'
416 return NONNORMAL
360 return NONNORMAL
417 elif self.from_p2:
361 elif self.from_p2:
418 return FROM_P2
362 return FROM_P2
419 elif self._possibly_dirty:
363 elif self._size is None:
420 return self._size if self._size is not None else NONNORMAL
364 return NONNORMAL
421 else:
365 else:
422 return self._size
366 return self._size
423
367
@@ -429,16 +373,14 b' class DirstateItem(object):'
429 raise RuntimeError('untracked item')
373 raise RuntimeError('untracked item')
430 elif self.removed:
374 elif self.removed:
431 return 0
375 return 0
432 elif self._possibly_dirty:
376 elif self._mtime is None:
433 return AMBIGUOUS_TIME
434 elif self.merged:
435 return AMBIGUOUS_TIME
377 return AMBIGUOUS_TIME
436 elif self.added:
378 elif self._p2_info:
437 return AMBIGUOUS_TIME
379 return AMBIGUOUS_TIME
438 elif self.from_p2:
380 elif not self._p1_tracked:
439 return AMBIGUOUS_TIME
381 return AMBIGUOUS_TIME
440 else:
382 else:
441 return self._mtime if self._mtime is not None else 0
383 return self._mtime
442
384
443 def need_delay(self, now):
385 def need_delay(self, now):
444 """True if the stored mtime would be ambiguous with the current time"""
386 """True if the stored mtime would be ambiguous with the current time"""
@@ -16,21 +16,15 b' pub enum EntryState {'
16 #[derive(Debug, PartialEq, Copy, Clone)]
16 #[derive(Debug, PartialEq, Copy, Clone)]
17 pub struct DirstateEntry {
17 pub struct DirstateEntry {
18 flags: Flags,
18 flags: Flags,
19 mode: i32,
19 mode_size: Option<(i32, i32)>,
20 size: i32,
20 mtime: Option<i32>,
21 mtime: i32,
22 }
21 }
23
22
24 bitflags! {
23 bitflags! {
25 pub struct Flags: u8 {
24 struct Flags: u8 {
26 const WDIR_TRACKED = 1 << 0;
25 const WDIR_TRACKED = 1 << 0;
27 const P1_TRACKED = 1 << 1;
26 const P1_TRACKED = 1 << 1;
28 const P2_TRACKED = 1 << 2;
27 const P2_INFO = 1 << 2;
29 const POSSIBLY_DIRTY = 1 << 3;
30 const MERGED = 1 << 4;
31 const CLEAN_P1 = 1 << 5;
32 const CLEAN_P2 = 1 << 6;
33 const ENTRYLESS_TREE_NODE = 1 << 7;
34 }
28 }
35 }
29 }
36
30
@@ -48,15 +42,19 b' pub const SIZE_NON_NORMAL: i32 = -1;'
48
42
49 impl DirstateEntry {
43 impl DirstateEntry {
50 pub fn new(
44 pub fn new(
51 flags: Flags,
45 wdir_tracked: bool,
52 mode_size_mtime: Option<(i32, i32, i32)>,
46 p1_tracked: bool,
47 p2_info: bool,
48 mode_size: Option<(i32, i32)>,
49 mtime: Option<i32>,
53 ) -> Self {
50 ) -> Self {
54 let (mode, size, mtime) =
51 let mut flags = Flags::empty();
55 mode_size_mtime.unwrap_or((0, SIZE_NON_NORMAL, MTIME_UNSET));
52 flags.set(Flags::WDIR_TRACKED, wdir_tracked);
53 flags.set(Flags::P1_TRACKED, p1_tracked);
54 flags.set(Flags::P2_INFO, p2_info);
56 Self {
55 Self {
57 flags,
56 flags,
58 mode,
57 mode_size,
59 size,
60 mtime,
58 mtime,
61 }
59 }
62 }
60 }
@@ -75,12 +73,9 b' impl DirstateEntry {'
75 Self::new_possibly_dirty()
73 Self::new_possibly_dirty()
76 } else if mtime == MTIME_UNSET {
74 } else if mtime == MTIME_UNSET {
77 Self {
75 Self {
78 flags: Flags::WDIR_TRACKED
76 flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED,
79 | Flags::P1_TRACKED
77 mode_size: Some((mode, size)),
80 | Flags::POSSIBLY_DIRTY,
78 mtime: None,
81 mode,
82 size,
83 mtime: 0,
84 }
79 }
85 } else {
80 } else {
86 Self::new_normal(mode, size, mtime)
81 Self::new_normal(mode, size, mtime)
@@ -89,18 +84,15 b' impl DirstateEntry {'
89 EntryState::Added => Self::new_added(),
84 EntryState::Added => Self::new_added(),
90 EntryState::Removed => Self {
85 EntryState::Removed => Self {
91 flags: if size == SIZE_NON_NORMAL {
86 flags: if size == SIZE_NON_NORMAL {
92 Flags::P1_TRACKED // might not be true because of rename ?
87 Flags::P1_TRACKED | Flags::P2_INFO
93 | Flags::P2_TRACKED // might not be true because of rename ?
94 | Flags::MERGED
95 } else if size == SIZE_FROM_OTHER_PARENT {
88 } else if size == SIZE_FROM_OTHER_PARENT {
96 // We don’t know if P1_TRACKED should be set (file history)
89 // We don’t know if P1_TRACKED should be set (file history)
97 Flags::P2_TRACKED | Flags::CLEAN_P2
90 Flags::P2_INFO
98 } else {
91 } else {
99 Flags::P1_TRACKED
92 Flags::P1_TRACKED
100 },
93 },
101 mode: 0,
94 mode_size: None,
102 size: 0,
95 mtime: None,
103 mtime: 0,
104 },
96 },
105 EntryState::Merged => Self::new_merged(),
97 EntryState::Merged => Self::new_merged(),
106 }
98 }
@@ -109,30 +101,25 b' impl DirstateEntry {'
109 pub fn new_from_p2() -> Self {
101 pub fn new_from_p2() -> Self {
110 Self {
102 Self {
111 // might be missing P1_TRACKED
103 // might be missing P1_TRACKED
112 flags: Flags::WDIR_TRACKED | Flags::P2_TRACKED | Flags::CLEAN_P2,
104 flags: Flags::WDIR_TRACKED | Flags::P2_INFO,
113 mode: 0,
105 mode_size: None,
114 size: SIZE_FROM_OTHER_PARENT,
106 mtime: None,
115 mtime: MTIME_UNSET,
116 }
107 }
117 }
108 }
118
109
119 pub fn new_possibly_dirty() -> Self {
110 pub fn new_possibly_dirty() -> Self {
120 Self {
111 Self {
121 flags: Flags::WDIR_TRACKED
112 flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED,
122 | Flags::P1_TRACKED
113 mode_size: None,
123 | Flags::POSSIBLY_DIRTY,
114 mtime: None,
124 mode: 0,
125 size: SIZE_NON_NORMAL,
126 mtime: MTIME_UNSET,
127 }
115 }
128 }
116 }
129
117
130 pub fn new_added() -> Self {
118 pub fn new_added() -> Self {
131 Self {
119 Self {
132 flags: Flags::WDIR_TRACKED,
120 flags: Flags::WDIR_TRACKED,
133 mode: 0,
121 mode_size: None,
134 size: SIZE_NON_NORMAL,
122 mtime: None,
135 mtime: MTIME_UNSET,
136 }
123 }
137 }
124 }
138
125
@@ -140,20 +127,17 b' impl DirstateEntry {'
140 Self {
127 Self {
141 flags: Flags::WDIR_TRACKED
128 flags: Flags::WDIR_TRACKED
142 | Flags::P1_TRACKED // might not be true because of rename ?
129 | Flags::P1_TRACKED // might not be true because of rename ?
143 | Flags::P2_TRACKED // might not be true because of rename ?
130 | Flags::P2_INFO, // might not be true because of rename ?
144 | Flags::MERGED,
131 mode_size: None,
145 mode: 0,
132 mtime: None,
146 size: SIZE_NON_NORMAL,
147 mtime: MTIME_UNSET,
148 }
133 }
149 }
134 }
150
135
151 pub fn new_normal(mode: i32, size: i32, mtime: i32) -> Self {
136 pub fn new_normal(mode: i32, size: i32, mtime: i32) -> Self {
152 Self {
137 Self {
153 flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED,
138 flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED,
154 mode,
139 mode_size: Some((mode, size)),
155 size,
140 mtime: Some(mtime),
156 mtime,
157 }
141 }
158 }
142 }
159
143
@@ -169,36 +153,34 b' impl DirstateEntry {'
169 self.flags.contains(Flags::WDIR_TRACKED)
153 self.flags.contains(Flags::WDIR_TRACKED)
170 }
154 }
171
155
172 fn tracked_in_any_parent(&self) -> bool {
156 fn in_either_parent(&self) -> bool {
173 self.flags.intersects(Flags::P1_TRACKED | Flags::P2_TRACKED)
157 self.flags.intersects(Flags::P1_TRACKED | Flags::P2_INFO)
174 }
158 }
175
159
176 pub fn removed(&self) -> bool {
160 pub fn removed(&self) -> bool {
177 self.tracked_in_any_parent()
161 self.in_either_parent() && !self.flags.contains(Flags::WDIR_TRACKED)
178 && !self.flags.contains(Flags::WDIR_TRACKED)
179 }
162 }
180
163
181 pub fn merged(&self) -> bool {
164 pub fn merged(&self) -> bool {
182 self.flags.contains(Flags::WDIR_TRACKED | Flags::MERGED)
165 self.flags
166 .contains(Flags::WDIR_TRACKED | Flags::P1_TRACKED | Flags::P2_INFO)
183 }
167 }
184
168
185 pub fn added(&self) -> bool {
169 pub fn added(&self) -> bool {
186 self.flags.contains(Flags::WDIR_TRACKED)
170 self.flags.contains(Flags::WDIR_TRACKED) && !self.in_either_parent()
187 && !self.tracked_in_any_parent()
188 }
171 }
189
172
190 pub fn from_p2(&self) -> bool {
173 pub fn from_p2(&self) -> bool {
191 self.flags.contains(Flags::WDIR_TRACKED | Flags::CLEAN_P2)
174 self.flags.contains(Flags::WDIR_TRACKED | Flags::P2_INFO)
175 && !self.flags.contains(Flags::P1_TRACKED)
192 }
176 }
193
177
194 pub fn maybe_clean(&self) -> bool {
178 pub fn maybe_clean(&self) -> bool {
195 if !self.flags.contains(Flags::WDIR_TRACKED) {
179 if !self.flags.contains(Flags::WDIR_TRACKED) {
196 false
180 false
197 } else if self.added() {
181 } else if !self.flags.contains(Flags::P1_TRACKED) {
198 false
182 false
199 } else if self.flags.contains(Flags::MERGED) {
183 } else if self.flags.contains(Flags::P2_INFO) {
200 false
201 } else if self.flags.contains(Flags::CLEAN_P2) {
202 false
184 false
203 } else {
185 } else {
204 true
186 true
@@ -207,11 +189,15 b' impl DirstateEntry {'
207
189
208 pub fn any_tracked(&self) -> bool {
190 pub fn any_tracked(&self) -> bool {
209 self.flags.intersects(
191 self.flags.intersects(
210 Flags::WDIR_TRACKED | Flags::P1_TRACKED | Flags::P2_TRACKED,
192 Flags::WDIR_TRACKED | Flags::P1_TRACKED | Flags::P2_INFO,
211 )
193 )
212 }
194 }
213
195
214 pub fn state(&self) -> EntryState {
196 fn v1_state(&self) -> EntryState {
197 if !self.any_tracked() {
198 // TODO: return an Option instead?
199 panic!("Accessing v1_state of an untracked DirstateEntry")
200 }
215 if self.removed() {
201 if self.removed() {
216 EntryState::Removed
202 EntryState::Removed
217 } else if self.merged() {
203 } else if self.merged() {
@@ -223,14 +209,24 b' impl DirstateEntry {'
223 }
209 }
224 }
210 }
225
211
226 pub fn mode(&self) -> i32 {
212 fn v1_mode(&self) -> i32 {
227 self.mode
213 if let Some((mode, _size)) = self.mode_size {
214 mode
215 } else {
216 0
217 }
228 }
218 }
229
219
230 pub fn size(&self) -> i32 {
220 fn v1_size(&self) -> i32 {
231 if self.removed() && self.flags.contains(Flags::MERGED) {
221 if !self.any_tracked() {
222 // TODO: return an Option instead?
223 panic!("Accessing v1_size of an untracked DirstateEntry")
224 }
225 if self.removed()
226 && self.flags.contains(Flags::P1_TRACKED | Flags::P2_INFO)
227 {
232 SIZE_NON_NORMAL
228 SIZE_NON_NORMAL
233 } else if self.removed() && self.flags.contains(Flags::CLEAN_P2) {
229 } else if self.removed() && self.flags.contains(Flags::P2_INFO) {
234 SIZE_FROM_OTHER_PARENT
230 SIZE_FROM_OTHER_PARENT
235 } else if self.removed() {
231 } else if self.removed() {
236 0
232 0
@@ -240,87 +236,81 b' impl DirstateEntry {'
240 SIZE_NON_NORMAL
236 SIZE_NON_NORMAL
241 } else if self.from_p2() {
237 } else if self.from_p2() {
242 SIZE_FROM_OTHER_PARENT
238 SIZE_FROM_OTHER_PARENT
243 } else if self.flags.contains(Flags::POSSIBLY_DIRTY) {
239 } else if let Some((_mode, size)) = self.mode_size {
244 self.size // TODO: SIZE_NON_NORMAL ?
240 size
245 } else {
241 } else {
246 self.size
242 SIZE_NON_NORMAL
247 }
243 }
248 }
244 }
249
245
250 pub fn mtime(&self) -> i32 {
246 fn v1_mtime(&self) -> i32 {
247 if !self.any_tracked() {
248 // TODO: return an Option instead?
249 panic!("Accessing v1_mtime of an untracked DirstateEntry")
250 }
251 if self.removed() {
251 if self.removed() {
252 0
252 0
253 } else if self.flags.contains(Flags::POSSIBLY_DIRTY) {
253 } else if self.flags.contains(Flags::P2_INFO) {
254 MTIME_UNSET
255 } else if self.merged() {
256 MTIME_UNSET
254 MTIME_UNSET
257 } else if self.added() {
255 } else if !self.flags.contains(Flags::P1_TRACKED) {
258 MTIME_UNSET
259 } else if self.from_p2() {
260 MTIME_UNSET
256 MTIME_UNSET
261 } else {
257 } else {
262 self.mtime
258 self.mtime.unwrap_or(MTIME_UNSET)
263 }
259 }
264 }
260 }
265
261
262 // TODO: return `Option<EntryState>`? None when `!self.any_tracked`
263 pub fn state(&self) -> EntryState {
264 self.v1_state()
265 }
266
267 // TODO: return Option?
268 pub fn mode(&self) -> i32 {
269 self.v1_mode()
270 }
271
272 // TODO: return Option?
273 pub fn size(&self) -> i32 {
274 self.v1_size()
275 }
276
277 // TODO: return Option?
278 pub fn mtime(&self) -> i32 {
279 self.v1_mtime()
280 }
281
266 pub fn drop_merge_data(&mut self) {
282 pub fn drop_merge_data(&mut self) {
267 if self.flags.contains(Flags::CLEAN_P1)
283 if self.flags.contains(Flags::P2_INFO) {
268 || self.flags.contains(Flags::CLEAN_P2)
284 self.flags.remove(Flags::P2_INFO);
269 || self.flags.contains(Flags::MERGED)
285 self.mode_size = None;
270 || self.flags.contains(Flags::P2_TRACKED)
286 self.mtime = None;
271 {
272 if self.flags.contains(Flags::MERGED) {
273 self.flags.insert(Flags::P1_TRACKED);
274 } else {
275 self.flags.remove(Flags::P1_TRACKED);
276 }
277 self.flags.remove(
278 Flags::MERGED
279 | Flags::CLEAN_P1
280 | Flags::CLEAN_P2
281 | Flags::P2_TRACKED,
282 );
283 self.flags.insert(Flags::POSSIBLY_DIRTY);
284 self.mode = 0;
285 self.mtime = 0;
286 // size = None on the python size turn into size = NON_NORMAL when
287 // accessed. So the next line is currently required, but a some
288 // future clean up would be welcome.
289 self.size = SIZE_NON_NORMAL;
290 }
287 }
291 }
288 }
292
289
293 pub fn set_possibly_dirty(&mut self) {
290 pub fn set_possibly_dirty(&mut self) {
294 self.flags.insert(Flags::POSSIBLY_DIRTY)
291 self.mtime = None
295 }
292 }
296
293
297 pub fn set_clean(&mut self, mode: i32, size: i32, mtime: i32) {
294 pub fn set_clean(&mut self, mode: i32, size: i32, mtime: i32) {
298 self.flags.insert(Flags::WDIR_TRACKED | Flags::P1_TRACKED);
295 self.flags.insert(Flags::WDIR_TRACKED | Flags::P1_TRACKED);
299 self.flags.remove(
296 self.mode_size = Some((mode, size));
300 Flags::P2_TRACKED // This might be wrong
297 self.mtime = Some(mtime);
301 | Flags::MERGED
302 | Flags::CLEAN_P2
303 | Flags::POSSIBLY_DIRTY,
304 );
305 self.mode = mode;
306 self.size = size;
307 self.mtime = mtime;
308 }
298 }
309
299
310 pub fn set_tracked(&mut self) {
300 pub fn set_tracked(&mut self) {
311 self.flags
301 self.flags.insert(Flags::WDIR_TRACKED);
312 .insert(Flags::WDIR_TRACKED | Flags::POSSIBLY_DIRTY);
302 // `set_tracked` is replacing various `normallookup` call. So we mark
313 // size = None on the python size turn into size = NON_NORMAL when
303 // the files as needing lookup
314 // accessed. So the next line is currently required, but a some future
304 //
315 // clean up would be welcome.
305 // Consider dropping this in the future in favor of something less
316 self.size = SIZE_NON_NORMAL;
306 // broad.
307 self.mtime = None;
317 }
308 }
318
309
319 pub fn set_untracked(&mut self) {
310 pub fn set_untracked(&mut self) {
320 self.flags.remove(Flags::WDIR_TRACKED);
311 self.flags.remove(Flags::WDIR_TRACKED);
321 self.mode = 0;
312 self.mode_size = None;
322 self.size = 0;
313 self.mtime = None;
323 self.mtime = 0;
324 }
314 }
325
315
326 /// Returns `(state, mode, size, mtime)` for the puprose of serialization
316 /// Returns `(state, mode, size, mtime)` for the puprose of serialization
@@ -330,7 +320,12 b' impl DirstateEntry {'
330 /// want to not represent these cases that way in memory, but serialization
320 /// want to not represent these cases that way in memory, but serialization
331 /// will need to keep the same format.
321 /// will need to keep the same format.
332 pub fn v1_data(&self) -> (u8, i32, i32, i32) {
322 pub fn v1_data(&self) -> (u8, i32, i32, i32) {
333 (self.state().into(), self.mode(), self.size(), self.mtime())
323 (
324 self.v1_state().into(),
325 self.v1_mode(),
326 self.v1_size(),
327 self.v1_mtime(),
328 )
334 }
329 }
335
330
336 pub(crate) fn is_from_other_parent(&self) -> bool {
331 pub(crate) fn is_from_other_parent(&self) -> bool {
@@ -354,12 +349,7 b' impl DirstateEntry {'
354 /// Returns a `(state, mode, size, mtime)` tuple as for
349 /// Returns a `(state, mode, size, mtime)` tuple as for
355 /// `DirstateMapMethods::debug_iter`.
350 /// `DirstateMapMethods::debug_iter`.
356 pub fn debug_tuple(&self) -> (u8, i32, i32, i32) {
351 pub fn debug_tuple(&self) -> (u8, i32, i32, i32) {
357 let state = if self.flags.contains(Flags::ENTRYLESS_TREE_NODE) {
352 (self.state().into(), self.mode(), self.size(), self.mtime())
358 b' '
359 } else {
360 self.state().into()
361 };
362 (state, self.mode(), self.size(), self.mtime())
363 }
353 }
364
354
365 pub fn mtime_is_ambiguous(&self, now: i32) -> bool {
355 pub fn mtime_is_ambiguous(&self, now: i32) -> bool {
@@ -378,14 +368,10 b' impl DirstateEntry {'
378 // dirstate, forcing future 'status' calls to compare the
368 // dirstate, forcing future 'status' calls to compare the
379 // contents of the file if the size is the same. This prevents
369 // contents of the file if the size is the same. This prevents
380 // mistakenly treating such files as clean.
370 // mistakenly treating such files as clean.
381 self.clear_mtime()
371 self.set_possibly_dirty()
382 }
372 }
383 ambiguous
373 ambiguous
384 }
374 }
385
386 pub fn clear_mtime(&mut self) {
387 self.mtime = -1;
388 }
389 }
375 }
390
376
391 impl EntryState {
377 impl EntryState {
@@ -695,7 +695,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
695 path.as_ref(),
695 path.as_ref(),
696 )? {
696 )? {
697 if let NodeData::Entry(entry) = &mut node.data {
697 if let NodeData::Entry(entry) = &mut node.data {
698 entry.clear_mtime();
698 entry.set_possibly_dirty();
699 }
699 }
700 }
700 }
701 }
701 }
@@ -6,7 +6,6 b' use cpython::PyObject;'
6 use cpython::PyResult;
6 use cpython::PyResult;
7 use cpython::Python;
7 use cpython::Python;
8 use cpython::PythonObject;
8 use cpython::PythonObject;
9 use hg::dirstate::entry::Flags;
10 use hg::dirstate::DirstateEntry;
9 use hg::dirstate::DirstateEntry;
11 use hg::dirstate::EntryState;
10 use hg::dirstate::EntryState;
12 use std::cell::Cell;
11 use std::cell::Cell;
@@ -19,23 +18,25 b' py_class!(pub class DirstateItem |py| {'
19 _cls,
18 _cls,
20 wc_tracked: bool = false,
19 wc_tracked: bool = false,
21 p1_tracked: bool = false,
20 p1_tracked: bool = false,
22 p2_tracked: bool = false,
21 p2_info: bool = false,
23 merged: bool = false,
22 has_meaningful_data: bool = true,
24 clean_p1: bool = false,
23 has_meaningful_mtime: bool = true,
25 clean_p2: bool = false,
26 possibly_dirty: bool = false,
27 parentfiledata: Option<(i32, i32, i32)> = None,
24 parentfiledata: Option<(i32, i32, i32)> = None,
28
25
29 ) -> PyResult<DirstateItem> {
26 ) -> PyResult<DirstateItem> {
30 let mut flags = Flags::empty();
27 let mut mode_size_opt = None;
31 flags.set(Flags::WDIR_TRACKED, wc_tracked);
28 let mut mtime_opt = None;
32 flags.set(Flags::P1_TRACKED, p1_tracked);
29 if let Some((mode, size, mtime)) = parentfiledata {
33 flags.set(Flags::P2_TRACKED, p2_tracked);
30 if has_meaningful_data {
34 flags.set(Flags::MERGED, merged);
31 mode_size_opt = Some((mode, size))
35 flags.set(Flags::CLEAN_P1, clean_p1);
32 }
36 flags.set(Flags::CLEAN_P2, clean_p2);
33 if has_meaningful_mtime {
37 flags.set(Flags::POSSIBLY_DIRTY, possibly_dirty);
34 mtime_opt = Some(mtime)
38 let entry = DirstateEntry::new(flags, parentfiledata);
35 }
36 }
37 let entry = DirstateEntry::new(
38 wc_tracked, p1_tracked, p2_info, mode_size_opt, mtime_opt,
39 );
39 DirstateItem::create_instance(py, Cell::new(entry))
40 DirstateItem::create_instance(py, Cell::new(entry))
40 }
41 }
41
42
General Comments 0
You need to be logged in to leave comments. Login now