##// 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 52 dirstateItemObject *t;
53 53 int wc_tracked;
54 54 int p1_tracked;
55 int p2_tracked;
56 int merged;
57 int clean_p1;
58 int clean_p2;
59 int possibly_dirty;
55 int p2_info;
56 int has_meaningful_data;
57 int has_meaningful_mtime;
58 int mode;
59 int size;
60 int mtime;
60 61 PyObject *parentfiledata;
61 62 static char *keywords_name[] = {
62 "wc_tracked", "p1_tracked", "p2_tracked",
63 "merged", "clean_p1", "clean_p2",
64 "possibly_dirty", "parentfiledata", NULL,
63 "wc_tracked",
64 "p1_tracked",
65 "p2_info",
66 "has_meaningful_data",
67 "has_meaningful_mtime",
68 "parentfiledata",
69 NULL,
65 70 };
66 71 wc_tracked = 0;
67 72 p1_tracked = 0;
68 p2_tracked = 0;
69 merged = 0;
70 clean_p1 = 0;
71 clean_p2 = 0;
72 possibly_dirty = 0;
73 p2_info = 0;
74 has_meaningful_mtime = 1;
75 has_meaningful_data = 1;
73 76 parentfiledata = Py_None;
74 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iiiiiiiO", keywords_name,
75 &wc_tracked, &p1_tracked, &p2_tracked,
76 &merged, &clean_p1, &clean_p2,
77 &possibly_dirty, &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`");
77 if (!PyArg_ParseTupleAndKeywords(
78 args, kwds, "|iiiiiO", keywords_name, &wc_tracked, &p1_tracked,
79 &p2_info, &has_meaningful_data, &has_meaningful_mtime,
80 &parentfiledata)) {
86 81 return NULL;
87 82 }
88 83 t = (dirstateItemObject *)subtype->tp_alloc(subtype, 1);
@@ -97,24 +92,10 b' static PyObject *dirstate_item_new(PyTyp'
97 92 if (p1_tracked) {
98 93 t->flags |= dirstate_flag_p1_tracked;
99 94 }
100 if (p2_tracked) {
101 t->flags |= dirstate_flag_p2_tracked;
102 }
103 if (possibly_dirty) {
104 t->flags |= dirstate_flag_possibly_dirty;
105 }
106 if (merged) {
107 t->flags |= dirstate_flag_merged;
95 if (p2_info) {
96 t->flags |= dirstate_flag_p2_info;
108 97 }
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;
98
118 99 if (parentfiledata != Py_None) {
119 100 if (!PyTuple_CheckExact(parentfiledata)) {
120 101 PyErr_SetString(
@@ -122,12 +103,26 b' static PyObject *dirstate_item_new(PyTyp'
122 103 "parentfiledata should be a Tuple or None");
123 104 return NULL;
124 105 }
125 t->mode =
126 (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 0));
127 t->size =
128 (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 1));
129 t->mtime =
130 (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 2));
106 mode = (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 0));
107 size = (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 1));
108 mtime = (int)PyLong_AsLong(PyTuple_GetItem(parentfiledata, 2));
109 } else {
110 has_meaningful_data = 0;
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 127 return (PyObject *)t;
133 128 }
@@ -142,12 +137,20 b' static inline bool dirstate_item_c_track'
142 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 148 static inline bool dirstate_item_c_added(dirstateItemObject *self)
146 149 {
147 unsigned char mask =
150 const unsigned char mask =
148 151 (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
149 dirstate_flag_p2_tracked);
150 unsigned char target = dirstate_flag_wc_tracked;
152 dirstate_flag_p2_info);
153 const unsigned char target = dirstate_flag_wc_tracked;
151 154 return (self->flags & mask) == target;
152 155 }
153 156
@@ -157,21 +160,21 b' static inline bool dirstate_item_c_remov'
157 160 return false;
158 161 }
159 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 166 static inline bool dirstate_item_c_merged(dirstateItemObject *self)
164 167 {
165 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 173 static inline bool dirstate_item_c_from_p2(dirstateItemObject *self)
170 174 {
171 if (!dirstate_item_c_tracked(self)) {
172 return false;
173 }
174 return (self->flags & dirstate_flag_clean_p2);
175 return ((self->flags & dirstate_flag_wc_tracked) &&
176 !(self->flags & dirstate_flag_p1_tracked) &&
177 (self->flags & dirstate_flag_p2_info));
175 178 }
176 179
177 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 193 static inline int dirstate_item_c_v1_mode(dirstateItemObject *self)
191 194 {
195 if (self->flags & dirstate_flag_has_meaningful_data) {
192 196 return self->mode;
197 } else {
198 return 0;
199 }
193 200 }
194 201
195 202 static inline int dirstate_item_c_v1_size(dirstateItemObject *self)
196 203 {
197 if (dirstate_item_c_removed(self) &&
198 (self->flags & dirstate_flag_merged)) {
204 if (!(self->flags & dirstate_flag_wc_tracked) &&
205 (self->flags & dirstate_flag_p2_info)) {
206 if (self->flags & dirstate_flag_p1_tracked) {
199 207 return dirstate_v1_nonnormal;
200 } else if (dirstate_item_c_removed(self) &&
201 (self->flags & dirstate_flag_clean_p2)) {
208 } else {
202 209 return dirstate_v1_from_p2;
210 }
203 211 } else if (dirstate_item_c_removed(self)) {
204 212 return 0;
205 } else if (dirstate_item_c_merged(self)) {
213 } else if (self->flags & dirstate_flag_p2_info) {
206 214 return dirstate_v1_from_p2;
207 215 } else if (dirstate_item_c_added(self)) {
208 216 return dirstate_v1_nonnormal;
209 } else if (dirstate_item_c_from_p2(self)) {
210 return dirstate_v1_from_p2;
211 } else if (self->flags & dirstate_flag_possibly_dirty) {
212 return self->size; /* NON NORMAL ? */
217 } else if (self->flags & dirstate_flag_has_meaningful_data) {
218 return self->size;
213 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 226 if (dirstate_item_c_removed(self)) {
221 227 return 0;
222 } else if (self->flags & dirstate_flag_possibly_dirty) {
223 return ambiguous_time;
224 } else if (dirstate_item_c_merged(self)) {
225 return ambiguous_time;
226 } else if (dirstate_item_c_added(self)) {
227 return ambiguous_time;
228 } else if (dirstate_item_c_from_p2(self)) {
228 } else if (!(self->flags & dirstate_flag_has_meaningful_mtime) ||
229 !(self->flags & dirstate_flag_p1_tracked) ||
230 !(self->flags & dirstate_flag_wc_tracked) ||
231 (self->flags & dirstate_flag_p2_info)) {
229 232 return ambiguous_time;
230 233 } else {
231 234 return self->mtime;
@@ -278,58 +281,43 b' dirstate_item_from_v1_data(char state, i'
278 281 if (!t) {
279 282 return NULL;
280 283 }
281
282 if (state == 'm') {
283 t->flags =
284 (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
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') {
290 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') {
284 t->flags = 0;
295 285 t->mode = 0;
296 286 t->size = 0;
297 287 t->mtime = 0;
288
289 if (state == 'm') {
290 t->flags = (dirstate_flag_wc_tracked |
291 dirstate_flag_p1_tracked | dirstate_flag_p2_info);
292 } else if (state == 'a') {
293 t->flags = dirstate_flag_wc_tracked;
294 } else if (state == 'r') {
298 295 if (size == dirstate_v1_nonnormal) {
299 296 t->flags =
300 (dirstate_flag_p1_tracked |
301 dirstate_flag_p2_tracked | dirstate_flag_merged);
297 dirstate_flag_p1_tracked | dirstate_flag_p2_info;
302 298 } else if (size == dirstate_v1_from_p2) {
303 t->flags =
304 (dirstate_flag_p2_tracked | dirstate_flag_clean_p2);
299 t->flags = dirstate_flag_p2_info;
305 300 } else {
306 301 t->flags = dirstate_flag_p1_tracked;
307 302 }
308 303 } else if (state == 'n') {
309 304 if (size == dirstate_v1_from_p2) {
310 305 t->flags =
311 (dirstate_flag_wc_tracked |
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;
306 dirstate_flag_wc_tracked | dirstate_flag_p2_info;
316 307 } else if (size == dirstate_v1_nonnormal) {
317 t->flags = (dirstate_flag_wc_tracked |
318 dirstate_flag_p1_tracked |
319 dirstate_flag_possibly_dirty);
320 t->mode = 0;
321 t->size = dirstate_v1_nonnormal;
322 t->mtime = ambiguous_time;
308 t->flags =
309 dirstate_flag_wc_tracked | dirstate_flag_p1_tracked;
323 310 } else if (mtime == ambiguous_time) {
324 311 t->flags = (dirstate_flag_wc_tracked |
325 312 dirstate_flag_p1_tracked |
326 dirstate_flag_possibly_dirty);
313 dirstate_flag_has_meaningful_data);
327 314 t->mode = mode;
328 315 t->size = size;
329 t->mtime = 0;
330 316 } else {
331 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 321 t->mode = mode;
334 322 t->size = size;
335 323 t->mtime = mtime;
@@ -371,8 +359,8 b' static PyObject *dirstate_item_new_added'
371 359 }
372 360 t->flags = dirstate_flag_wc_tracked;
373 361 t->mode = 0;
374 t->size = dirstate_v1_nonnormal;
375 t->mtime = ambiguous_time;
362 t->size = 0;
363 t->mtime = 0;
376 364 return (PyObject *)t;
377 365 };
378 366
@@ -387,10 +375,10 b' static PyObject *dirstate_item_new_merge'
387 375 return NULL;
388 376 }
389 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 379 t->mode = 0;
392 t->size = dirstate_v1_from_p2;
393 t->mtime = ambiguous_time;
380 t->size = 0;
381 t->mtime = 0;
394 382 return (PyObject *)t;
395 383 };
396 384
@@ -406,11 +394,10 b' static PyObject *dirstate_item_new_from_'
406 394 if (!t) {
407 395 return NULL;
408 396 }
409 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p2_tracked |
410 dirstate_flag_clean_p2);
397 t->flags = dirstate_flag_wc_tracked | dirstate_flag_p2_info;
411 398 t->mode = 0;
412 t->size = dirstate_v1_from_p2;
413 t->mtime = ambiguous_time;
399 t->size = 0;
400 t->mtime = 0;
414 401 return (PyObject *)t;
415 402 };
416 403
@@ -426,11 +413,10 b' static PyObject *dirstate_item_new_possi'
426 413 if (!t) {
427 414 return NULL;
428 415 }
429 t->flags = (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
430 dirstate_flag_possibly_dirty);
416 t->flags = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked;
431 417 t->mode = 0;
432 t->size = dirstate_v1_nonnormal;
433 t->mtime = ambiguous_time;
418 t->size = 0;
419 t->mtime = 0;
434 420 return (PyObject *)t;
435 421 };
436 422
@@ -462,7 +448,7 b' static PyObject *dirstate_item_new_norma'
462 448 to make sure it is correct. */
463 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 452 Py_RETURN_NONE;
467 453 }
468 454
@@ -474,7 +460,9 b' static PyObject *dirstate_item_set_clean'
474 460 if (!PyArg_ParseTuple(args, "iii", &mode, &size, &mtime)) {
475 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 466 self->mode = mode;
479 467 self->size = size;
480 468 self->mtime = mtime;
@@ -484,11 +472,7 b' static PyObject *dirstate_item_set_clean'
484 472 static PyObject *dirstate_item_set_tracked(dirstateItemObject *self)
485 473 {
486 474 self->flags |= dirstate_flag_wc_tracked;
487 self->flags |= dirstate_flag_possibly_dirty;
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;
475 self->flags &= ~dirstate_flag_has_meaningful_mtime;
492 476 Py_RETURN_NONE;
493 477 }
494 478
@@ -503,22 +487,13 b' static PyObject *dirstate_item_set_untra'
503 487
504 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)) {
507 if (dirstate_item_c_merged(self)) {
508 self->flags |= dirstate_flag_p1_tracked;
509 } else {
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;
490 if (self->flags & dirstate_flag_p2_info) {
491 self->flags &= ~(dirstate_flag_p2_info |
492 dirstate_flag_has_meaningful_data |
493 dirstate_flag_has_meaningful_mtime);
516 494 self->mode = 0;
517 495 self->mtime = 0;
518 /* size = None on the python size turn into size = NON_NORMAL
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;
496 self->size = 0;
522 497 }
523 498 Py_RETURN_NONE;
524 499 }
@@ -624,11 +599,9 b' static PyObject *dirstate_item_get_maybe'
624 599 {
625 600 if (!(self->flags & dirstate_flag_wc_tracked)) {
626 601 Py_RETURN_FALSE;
627 } else if (dirstate_item_c_added(self)) {
602 } else if (!(self->flags & dirstate_flag_p1_tracked)) {
628 603 Py_RETURN_FALSE;
629 } else if (self->flags & dirstate_flag_merged) {
630 Py_RETURN_FALSE;
631 } else if (self->flags & dirstate_flag_clean_p2) {
604 } else if (self->flags & dirstate_flag_p2_info) {
632 605 Py_RETURN_FALSE;
633 606 } else {
634 607 Py_RETURN_TRUE;
@@ -637,10 +610,7 b' static PyObject *dirstate_item_get_maybe'
637 610
638 611 static PyObject *dirstate_item_get_any_tracked(dirstateItemObject *self)
639 612 {
640 unsigned char mask = dirstate_flag_wc_tracked |
641 dirstate_flag_p1_tracked |
642 dirstate_flag_p2_tracked;
643 if ((self->flags & mask) != 0) {
613 if (dirstate_item_c_any_tracked(self)) {
644 614 Py_RETURN_TRUE;
645 615 } else {
646 616 Py_RETURN_FALSE;
@@ -33,11 +33,9 b' typedef struct {'
33 33
34 34 static const unsigned char dirstate_flag_wc_tracked = 1;
35 35 static const unsigned char dirstate_flag_p1_tracked = 1 << 1;
36 static const unsigned char dirstate_flag_p2_tracked = 1 << 2;
37 static const unsigned char dirstate_flag_possibly_dirty = 1 << 3;
38 static const unsigned char dirstate_flag_merged = 1 << 4;
39 static const unsigned char dirstate_flag_clean_p1 = 1 << 5;
40 static const unsigned char dirstate_flag_clean_p2 = 1 << 6;
36 static const unsigned char dirstate_flag_p2_info = 1 << 2;
37 static const unsigned char dirstate_flag_has_meaningful_data = 1 << 3;
38 static const unsigned char dirstate_flag_has_meaningful_mtime = 1 << 4;
41 39
42 40 extern PyTypeObject dirstateItemType;
43 41 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType)
@@ -137,14 +137,7 b' class _dirstatemapcommon(object):'
137 137 if entry is None:
138 138 self._dirs_incr(filename)
139 139 entry = DirstateItem(
140 p1_tracked=False,
141 p2_tracked=False,
142 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 143 self._insert_entry(filename, entry)
@@ -208,37 +201,20 b' class _dirstatemapcommon(object):'
208 201 self._drop_entry(filename)
209 202 self._dirs_decr(filename, old_entry=old_entry)
210 203 return
211 elif merged:
212 pass
213 elif not (p1_tracked or p2_tracked) and wc_tracked:
214 pass # file is added, nothing special to adjust
215 elif (p1_tracked or p2_tracked) and not wc_tracked:
216 pass
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'
204
205 p2_info = merged or clean_p2
206 if merged:
207 assert p1_tracked
208
209 has_meaningful_mtime = not possibly_dirty
231 210
232 211 old_entry = self._map.get(filename)
233 212 self._dirs_incr(filename, old_entry)
234 213 entry = DirstateItem(
235 214 wc_tracked=wc_tracked,
236 215 p1_tracked=p1_tracked,
237 p2_tracked=p2_tracked,
238 merged=merged,
239 clean_p1=clean_p1,
240 clean_p2=clean_p2,
241 possibly_dirty=possibly_dirty,
216 p2_info=p2_info,
217 has_meaningful_mtime=has_meaningful_mtime,
242 218 parentfiledata=parentfiledata,
243 219 )
244 220 self._insert_entry(filename, entry)
@@ -53,36 +53,32 b' class DirstateItem(object):'
53 53 # about file tracking
54 54 - wc_tracked: is the file tracked by the working copy
55 55 - p1_tracked: is the file tracked in working copy first parent
56 - p2_tracked: is the file tracked in working copy second parent
57
58 # about what possible merge action related to this file
59 - clean_p1: merge picked the file content from p1
60 - clean_p2: merge picked the file content from p2
61 - merged: file gather changes from both side.
56 - p2_info: the file has been involved in some merge operation. Either
57 because it was actually merged, or because the p2 version was
58 ahead, or because some renamed moved it there. In either case
59 `hg status` will want it displayed as modified.
62 60
63 61 # about the file state expected from p1 manifest:
64 62 - mode: the file mode in p1
65 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 71 # about the file state on disk last time we saw it:
68 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
71 trusted) value exists.
72
74 This value can be set to None if no cachable state exist. Either because we
75 do not care (see previous section) or because we could not cache something
76 yet.
73 77 """
74 78
75 79 _wc_tracked = attr.ib()
76 80 _p1_tracked = attr.ib()
77 _p2_tracked = 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()
81 _p2_info = attr.ib()
86 82 _mode = attr.ib()
87 83 _size = attr.ib()
88 84 _mtime = attr.ib()
@@ -91,32 +87,25 b' class DirstateItem(object):'
91 87 self,
92 88 wc_tracked=False,
93 89 p1_tracked=False,
94 p2_tracked=False,
95 merged=False,
96 clean_p1=False,
97 clean_p2=False,
98 possibly_dirty=False,
90 p2_info=False,
91 has_meaningful_data=True,
92 has_meaningful_mtime=True,
99 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 95 self._wc_tracked = wc_tracked
107 96 self._p1_tracked = p1_tracked
108 self._p2_tracked = p2_tracked
109 self._merged = merged
110 self._clean_p1 = clean_p1
111 self._clean_p2 = clean_p2
112 self._possibly_dirty = possibly_dirty
113 if parentfiledata is None:
97 self._p2_info = p2_info
98
114 99 self._mode = None
115 100 self._size = None
116 101 self._mtime = None
117 else:
102 if parentfiledata is None:
103 has_meaningful_mtime = False
104 has_meaningful_data = False
105 if has_meaningful_data:
118 106 self._mode = parentfiledata[0]
119 107 self._size = parentfiledata[1]
108 if has_meaningful_mtime:
120 109 self._mtime = parentfiledata[2]
121 110
122 111 @classmethod
@@ -125,11 +114,7 b' class DirstateItem(object):'
125 114
126 115 Should eventually be removed
127 116 """
128 instance = cls()
129 instance._wc_tracked = True
130 instance._p1_tracked = False
131 instance._p2_tracked = False
132 return instance
117 return cls(wc_tracked=True)
133 118
134 119 @classmethod
135 120 def new_merged(cls):
@@ -137,12 +122,7 b' class DirstateItem(object):'
137 122
138 123 Should eventually be removed
139 124 """
140 instance = cls()
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
125 return cls(wc_tracked=True, p1_tracked=True, p2_info=True)
146 126
147 127 @classmethod
148 128 def new_from_p2(cls):
@@ -150,12 +130,7 b' class DirstateItem(object):'
150 130
151 131 Should eventually be removed
152 132 """
153 instance = cls()
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
133 return cls(wc_tracked=True, p2_info=True)
159 134
160 135 @classmethod
161 136 def new_possibly_dirty(cls):
@@ -163,11 +138,7 b' class DirstateItem(object):'
163 138
164 139 Should eventually be removed
165 140 """
166 instance = cls()
167 instance._wc_tracked = True
168 instance._p1_tracked = True
169 instance._possibly_dirty = True
170 return instance
141 return cls(wc_tracked=True, p1_tracked=True)
171 142
172 143 @classmethod
173 144 def new_normal(cls, mode, size, mtime):
@@ -177,13 +148,11 b' class DirstateItem(object):'
177 148 """
178 149 assert size != FROM_P2
179 150 assert size != NONNORMAL
180 instance = cls()
181 instance._wc_tracked = True
182 instance._p1_tracked = True
183 instance._mode = mode
184 instance._size = size
185 instance._mtime = mtime
186 return instance
151 return cls(
152 wc_tracked=True,
153 p1_tracked=True,
154 parentfiledata=(mode, size, mtime),
155 )
187 156
188 157 @classmethod
189 158 def from_v1_data(cls, state, mode, size, mtime):
@@ -197,25 +166,16 b' class DirstateItem(object):'
197 166 elif state == b'a':
198 167 return cls.new_added()
199 168 elif state == b'r':
200 instance = cls()
201 instance._wc_tracked = False
202 169 if size == NONNORMAL:
203 instance._merged = True
204 instance._p1_tracked = (
205 True # might not be True because of rename ?
206 )
207 instance._p2_tracked = (
208 True # might not be True because of rename ?
209 )
170 p1_tracked = True
171 p2_info = True
210 172 elif size == FROM_P2:
211 instance._clean_p2 = True
212 instance._p1_tracked = (
213 False # We actually don't know (file history)
214 )
215 instance._p2_tracked = True
173 p1_tracked = False
174 p2_info = True
216 175 else:
217 instance._p1_tracked = True
218 return instance
176 p1_tracked = True
177 p2_info = False
178 return cls(p1_tracked=p1_tracked, p2_info=p2_info)
219 179 elif state == b'n':
220 180 if size == FROM_P2:
221 181 return cls.new_from_p2()
@@ -224,7 +184,6 b' class DirstateItem(object):'
224 184 elif mtime == AMBIGUOUS_TIME:
225 185 instance = cls.new_normal(mode, size, 42)
226 186 instance._mtime = None
227 instance._possibly_dirty = True
228 187 return instance
229 188 else:
230 189 return cls.new_normal(mode, size, mtime)
@@ -237,7 +196,7 b' class DirstateItem(object):'
237 196 This means the next status call will have to actually check its content
238 197 to make sure it is correct.
239 198 """
240 self._possibly_dirty = True
199 self._mtime = None
241 200
242 201 def set_clean(self, mode, size, mtime):
243 202 """mark a file as "clean" cancelling potential "possibly dirty call"
@@ -249,10 +208,6 b' class DirstateItem(object):'
249 208 """
250 209 self._wc_tracked = True
251 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 211 self._mode = mode
257 212 self._size = size
258 213 self._mtime = mtime
@@ -263,11 +218,11 b' class DirstateItem(object):'
263 218 This will ultimately be called by command like `hg add`.
264 219 """
265 220 self._wc_tracked = True
266 # `set_tracked` is replacing various `normallookup` call. So we set
267 # "possibly dirty" to stay on the safe side.
221 # `set_tracked` is replacing various `normallookup` call. So we mark
222 # the files as needing lookup
268 223 #
269 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 227 def set_untracked(self):
273 228 """mark a file as untracked in the working copy
@@ -284,15 +239,8 b' class DirstateItem(object):'
284 239
285 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):
288 return
289 self._p1_tracked = self.merged # why is this not already properly set ?
290
291 self._merged = False
292 self._clean_p1 = False
293 self._clean_p2 = False
294 self._p2_tracked = False
295 self._possibly_dirty = True
242 if self._p2_info:
243 self._p2_info = False
296 244 self._mode = None
297 245 self._size = None
298 246 self._mtime = None
@@ -334,23 +282,21 b' class DirstateItem(object):'
334 282 @property
335 283 def any_tracked(self):
336 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 287 @property
340 288 def added(self):
341 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 292 @property
345 293 def maybe_clean(self):
346 294 """True if the file has a chance to be in the "clean" state"""
347 295 if not self._wc_tracked:
348 296 return False
349 elif self.added:
297 elif not self._p1_tracked:
350 298 return False
351 elif self._merged:
352 return False
353 elif self._clean_p2:
299 elif self._p2_info:
354 300 return False
355 301 return True
356 302
@@ -360,7 +306,7 b' class DirstateItem(object):'
360 306
361 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 311 @property
366 312 def from_p2(self):
@@ -370,18 +316,16 b' class DirstateItem(object):'
370 316
371 317 Should only be set if a merge is in progress in the dirstate
372 318 """
373 if not self._wc_tracked:
374 return False
375 return self._clean_p2
319 return self._wc_tracked and (not self._p1_tracked) and self._p2_info
376 320
377 321 @property
378 322 def removed(self):
379 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 326 def v1_state(self):
383 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 329 # the object has no state to record, this is -currently-
386 330 # unsupported
387 331 raise RuntimeError('untracked item')
@@ -404,9 +348,9 b' class DirstateItem(object):'
404 348 # the object has no state to record, this is -currently-
405 349 # unsupported
406 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 352 return NONNORMAL
409 elif self.removed and self._clean_p2:
353 elif self.removed and self._p2_info:
410 354 return FROM_P2
411 355 elif self.removed:
412 356 return 0
@@ -416,8 +360,8 b' class DirstateItem(object):'
416 360 return NONNORMAL
417 361 elif self.from_p2:
418 362 return FROM_P2
419 elif self._possibly_dirty:
420 return self._size if self._size is not None else NONNORMAL
363 elif self._size is None:
364 return NONNORMAL
421 365 else:
422 366 return self._size
423 367
@@ -429,16 +373,14 b' class DirstateItem(object):'
429 373 raise RuntimeError('untracked item')
430 374 elif self.removed:
431 375 return 0
432 elif self._possibly_dirty:
433 return AMBIGUOUS_TIME
434 elif self.merged:
376 elif self._mtime is None:
435 377 return AMBIGUOUS_TIME
436 elif self.added:
378 elif self._p2_info:
437 379 return AMBIGUOUS_TIME
438 elif self.from_p2:
380 elif not self._p1_tracked:
439 381 return AMBIGUOUS_TIME
440 382 else:
441 return self._mtime if self._mtime is not None else 0
383 return self._mtime
442 384
443 385 def need_delay(self, now):
444 386 """True if the stored mtime would be ambiguous with the current time"""
@@ -16,21 +16,15 b' pub enum EntryState {'
16 16 #[derive(Debug, PartialEq, Copy, Clone)]
17 17 pub struct DirstateEntry {
18 18 flags: Flags,
19 mode: i32,
20 size: i32,
21 mtime: i32,
19 mode_size: Option<(i32, i32)>,
20 mtime: Option<i32>,
22 21 }
23 22
24 23 bitflags! {
25 pub struct Flags: u8 {
24 struct Flags: u8 {
26 25 const WDIR_TRACKED = 1 << 0;
27 26 const P1_TRACKED = 1 << 1;
28 const P2_TRACKED = 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;
27 const P2_INFO = 1 << 2;
34 28 }
35 29 }
36 30
@@ -48,15 +42,19 b' pub const SIZE_NON_NORMAL: i32 = -1;'
48 42
49 43 impl DirstateEntry {
50 44 pub fn new(
51 flags: Flags,
52 mode_size_mtime: Option<(i32, i32, i32)>,
45 wdir_tracked: bool,
46 p1_tracked: bool,
47 p2_info: bool,
48 mode_size: Option<(i32, i32)>,
49 mtime: Option<i32>,
53 50 ) -> Self {
54 let (mode, size, mtime) =
55 mode_size_mtime.unwrap_or((0, SIZE_NON_NORMAL, MTIME_UNSET));
51 let mut flags = Flags::empty();
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 55 Self {
57 56 flags,
58 mode,
59 size,
57 mode_size,
60 58 mtime,
61 59 }
62 60 }
@@ -75,12 +73,9 b' impl DirstateEntry {'
75 73 Self::new_possibly_dirty()
76 74 } else if mtime == MTIME_UNSET {
77 75 Self {
78 flags: Flags::WDIR_TRACKED
79 | Flags::P1_TRACKED
80 | Flags::POSSIBLY_DIRTY,
81 mode,
82 size,
83 mtime: 0,
76 flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED,
77 mode_size: Some((mode, size)),
78 mtime: None,
84 79 }
85 80 } else {
86 81 Self::new_normal(mode, size, mtime)
@@ -89,18 +84,15 b' impl DirstateEntry {'
89 84 EntryState::Added => Self::new_added(),
90 85 EntryState::Removed => Self {
91 86 flags: if size == SIZE_NON_NORMAL {
92 Flags::P1_TRACKED // might not be true because of rename ?
93 | Flags::P2_TRACKED // might not be true because of rename ?
94 | Flags::MERGED
87 Flags::P1_TRACKED | Flags::P2_INFO
95 88 } else if size == SIZE_FROM_OTHER_PARENT {
96 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 91 } else {
99 92 Flags::P1_TRACKED
100 93 },
101 mode: 0,
102 size: 0,
103 mtime: 0,
94 mode_size: None,
95 mtime: None,
104 96 },
105 97 EntryState::Merged => Self::new_merged(),
106 98 }
@@ -109,30 +101,25 b' impl DirstateEntry {'
109 101 pub fn new_from_p2() -> Self {
110 102 Self {
111 103 // might be missing P1_TRACKED
112 flags: Flags::WDIR_TRACKED | Flags::P2_TRACKED | Flags::CLEAN_P2,
113 mode: 0,
114 size: SIZE_FROM_OTHER_PARENT,
115 mtime: MTIME_UNSET,
104 flags: Flags::WDIR_TRACKED | Flags::P2_INFO,
105 mode_size: None,
106 mtime: None,
116 107 }
117 108 }
118 109
119 110 pub fn new_possibly_dirty() -> Self {
120 111 Self {
121 flags: Flags::WDIR_TRACKED
122 | Flags::P1_TRACKED
123 | Flags::POSSIBLY_DIRTY,
124 mode: 0,
125 size: SIZE_NON_NORMAL,
126 mtime: MTIME_UNSET,
112 flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED,
113 mode_size: None,
114 mtime: None,
127 115 }
128 116 }
129 117
130 118 pub fn new_added() -> Self {
131 119 Self {
132 120 flags: Flags::WDIR_TRACKED,
133 mode: 0,
134 size: SIZE_NON_NORMAL,
135 mtime: MTIME_UNSET,
121 mode_size: None,
122 mtime: None,
136 123 }
137 124 }
138 125
@@ -140,20 +127,17 b' impl DirstateEntry {'
140 127 Self {
141 128 flags: Flags::WDIR_TRACKED
142 129 | Flags::P1_TRACKED // might not be true because of rename ?
143 | Flags::P2_TRACKED // might not be true because of rename ?
144 | Flags::MERGED,
145 mode: 0,
146 size: SIZE_NON_NORMAL,
147 mtime: MTIME_UNSET,
130 | Flags::P2_INFO, // might not be true because of rename ?
131 mode_size: None,
132 mtime: None,
148 133 }
149 134 }
150 135
151 136 pub fn new_normal(mode: i32, size: i32, mtime: i32) -> Self {
152 137 Self {
153 138 flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED,
154 mode,
155 size,
156 mtime,
139 mode_size: Some((mode, size)),
140 mtime: Some(mtime),
157 141 }
158 142 }
159 143
@@ -169,36 +153,34 b' impl DirstateEntry {'
169 153 self.flags.contains(Flags::WDIR_TRACKED)
170 154 }
171 155
172 fn tracked_in_any_parent(&self) -> bool {
173 self.flags.intersects(Flags::P1_TRACKED | Flags::P2_TRACKED)
156 fn in_either_parent(&self) -> bool {
157 self.flags.intersects(Flags::P1_TRACKED | Flags::P2_INFO)
174 158 }
175 159
176 160 pub fn removed(&self) -> bool {
177 self.tracked_in_any_parent()
178 && !self.flags.contains(Flags::WDIR_TRACKED)
161 self.in_either_parent() && !self.flags.contains(Flags::WDIR_TRACKED)
179 162 }
180 163
181 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 169 pub fn added(&self) -> bool {
186 self.flags.contains(Flags::WDIR_TRACKED)
187 && !self.tracked_in_any_parent()
170 self.flags.contains(Flags::WDIR_TRACKED) && !self.in_either_parent()
188 171 }
189 172
190 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 178 pub fn maybe_clean(&self) -> bool {
195 179 if !self.flags.contains(Flags::WDIR_TRACKED) {
196 180 false
197 } else if self.added() {
181 } else if !self.flags.contains(Flags::P1_TRACKED) {
198 182 false
199 } else if self.flags.contains(Flags::MERGED) {
200 false
201 } else if self.flags.contains(Flags::CLEAN_P2) {
183 } else if self.flags.contains(Flags::P2_INFO) {
202 184 false
203 185 } else {
204 186 true
@@ -207,11 +189,15 b' impl DirstateEntry {'
207 189
208 190 pub fn any_tracked(&self) -> bool {
209 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 201 if self.removed() {
216 202 EntryState::Removed
217 203 } else if self.merged() {
@@ -223,14 +209,24 b' impl DirstateEntry {'
223 209 }
224 210 }
225 211
226 pub fn mode(&self) -> i32 {
227 self.mode
212 fn v1_mode(&self) -> i32 {
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 {
231 if self.removed() && self.flags.contains(Flags::MERGED) {
220 fn v1_size(&self) -> i32 {
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 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 230 SIZE_FROM_OTHER_PARENT
235 231 } else if self.removed() {
236 232 0
@@ -240,87 +236,81 b' impl DirstateEntry {'
240 236 SIZE_NON_NORMAL
241 237 } else if self.from_p2() {
242 238 SIZE_FROM_OTHER_PARENT
243 } else if self.flags.contains(Flags::POSSIBLY_DIRTY) {
244 self.size // TODO: SIZE_NON_NORMAL ?
239 } else if let Some((_mode, size)) = self.mode_size {
240 size
245 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 251 if self.removed() {
252 252 0
253 } else if self.flags.contains(Flags::POSSIBLY_DIRTY) {
254 MTIME_UNSET
255 } else if self.merged() {
253 } else if self.flags.contains(Flags::P2_INFO) {
256 254 MTIME_UNSET
257 } else if self.added() {
258 MTIME_UNSET
259 } else if self.from_p2() {
255 } else if !self.flags.contains(Flags::P1_TRACKED) {
260 256 MTIME_UNSET
261 257 } else {
262 self.mtime
258 self.mtime.unwrap_or(MTIME_UNSET)
259 }
260 }
261
262 // TODO: return `Option<EntryState>`? None when `!self.any_tracked`
263 pub fn state(&self) -> EntryState {
264 self.v1_state()
263 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()
264 280 }
265 281
266 282 pub fn drop_merge_data(&mut self) {
267 if self.flags.contains(Flags::CLEAN_P1)
268 || self.flags.contains(Flags::CLEAN_P2)
269 || self.flags.contains(Flags::MERGED)
270 || self.flags.contains(Flags::P2_TRACKED)
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;
283 if self.flags.contains(Flags::P2_INFO) {
284 self.flags.remove(Flags::P2_INFO);
285 self.mode_size = None;
286 self.mtime = None;
290 287 }
291 288 }
292 289
293 290 pub fn set_possibly_dirty(&mut self) {
294 self.flags.insert(Flags::POSSIBLY_DIRTY)
291 self.mtime = None
295 292 }
296 293
297 294 pub fn set_clean(&mut self, mode: i32, size: i32, mtime: i32) {
298 295 self.flags.insert(Flags::WDIR_TRACKED | Flags::P1_TRACKED);
299 self.flags.remove(
300 Flags::P2_TRACKED // This might be wrong
301 | Flags::MERGED
302 | Flags::CLEAN_P2
303 | Flags::POSSIBLY_DIRTY,
304 );
305 self.mode = mode;
306 self.size = size;
307 self.mtime = mtime;
296 self.mode_size = Some((mode, size));
297 self.mtime = Some(mtime);
308 298 }
309 299
310 300 pub fn set_tracked(&mut self) {
311 self.flags
312 .insert(Flags::WDIR_TRACKED | Flags::POSSIBLY_DIRTY);
313 // size = None on the python size turn into size = NON_NORMAL when
314 // accessed. So the next line is currently required, but a some future
315 // clean up would be welcome.
316 self.size = SIZE_NON_NORMAL;
301 self.flags.insert(Flags::WDIR_TRACKED);
302 // `set_tracked` is replacing various `normallookup` call. So we mark
303 // the files as needing lookup
304 //
305 // Consider dropping this in the future in favor of something less
306 // broad.
307 self.mtime = None;
317 308 }
318 309
319 310 pub fn set_untracked(&mut self) {
320 311 self.flags.remove(Flags::WDIR_TRACKED);
321 self.mode = 0;
322 self.size = 0;
323 self.mtime = 0;
312 self.mode_size = None;
313 self.mtime = None;
324 314 }
325 315
326 316 /// Returns `(state, mode, size, mtime)` for the puprose of serialization
@@ -330,7 +320,12 b' impl DirstateEntry {'
330 320 /// want to not represent these cases that way in memory, but serialization
331 321 /// will need to keep the same format.
332 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 331 pub(crate) fn is_from_other_parent(&self) -> bool {
@@ -354,12 +349,7 b' impl DirstateEntry {'
354 349 /// Returns a `(state, mode, size, mtime)` tuple as for
355 350 /// `DirstateMapMethods::debug_iter`.
356 351 pub fn debug_tuple(&self) -> (u8, i32, i32, i32) {
357 let state = if self.flags.contains(Flags::ENTRYLESS_TREE_NODE) {
358 b' '
359 } else {
360 self.state().into()
361 };
362 (state, self.mode(), self.size(), self.mtime())
352 (self.state().into(), self.mode(), self.size(), self.mtime())
363 353 }
364 354
365 355 pub fn mtime_is_ambiguous(&self, now: i32) -> bool {
@@ -378,14 +368,10 b' impl DirstateEntry {'
378 368 // dirstate, forcing future 'status' calls to compare the
379 369 // contents of the file if the size is the same. This prevents
380 370 // mistakenly treating such files as clean.
381 self.clear_mtime()
371 self.set_possibly_dirty()
382 372 }
383 373 ambiguous
384 374 }
385
386 pub fn clear_mtime(&mut self) {
387 self.mtime = -1;
388 }
389 375 }
390 376
391 377 impl EntryState {
@@ -695,7 +695,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
695 695 path.as_ref(),
696 696 )? {
697 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 6 use cpython::PyResult;
7 7 use cpython::Python;
8 8 use cpython::PythonObject;
9 use hg::dirstate::entry::Flags;
10 9 use hg::dirstate::DirstateEntry;
11 10 use hg::dirstate::EntryState;
12 11 use std::cell::Cell;
@@ -19,23 +18,25 b' py_class!(pub class DirstateItem |py| {'
19 18 _cls,
20 19 wc_tracked: bool = false,
21 20 p1_tracked: bool = false,
22 p2_tracked: bool = false,
23 merged: bool = false,
24 clean_p1: bool = false,
25 clean_p2: bool = false,
26 possibly_dirty: bool = false,
21 p2_info: bool = false,
22 has_meaningful_data: bool = true,
23 has_meaningful_mtime: bool = true,
27 24 parentfiledata: Option<(i32, i32, i32)> = None,
28 25
29 26 ) -> PyResult<DirstateItem> {
30 let mut flags = Flags::empty();
31 flags.set(Flags::WDIR_TRACKED, wc_tracked);
32 flags.set(Flags::P1_TRACKED, p1_tracked);
33 flags.set(Flags::P2_TRACKED, p2_tracked);
34 flags.set(Flags::MERGED, merged);
35 flags.set(Flags::CLEAN_P1, clean_p1);
36 flags.set(Flags::CLEAN_P2, clean_p2);
37 flags.set(Flags::POSSIBLY_DIRTY, possibly_dirty);
38 let entry = DirstateEntry::new(flags, parentfiledata);
27 let mut mode_size_opt = None;
28 let mut mtime_opt = None;
29 if let Some((mode, size, mtime)) = parentfiledata {
30 if has_meaningful_data {
31 mode_size_opt = Some((mode, size))
32 }
33 if has_meaningful_mtime {
34 mtime_opt = Some(mtime)
35 }
36 }
37 let entry = DirstateEntry::new(
38 wc_tracked, p1_tracked, p2_info, mode_size_opt, mtime_opt,
39 );
39 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