##// END OF EJS Templates
dirstate-v2: adds a flag to mark a file as modified...
Simon Sapin -
r49066:1730b2fc default
parent child Browse files
Show More
@@ -139,18 +139,16 b' static inline bool dirstate_item_c_track'
139 139
140 140 static inline bool dirstate_item_c_any_tracked(dirstateItemObject *self)
141 141 {
142 const unsigned char mask = dirstate_flag_wc_tracked |
143 dirstate_flag_p1_tracked |
142 const int mask = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
144 143 dirstate_flag_p2_info;
145 144 return (self->flags & mask);
146 145 }
147 146
148 147 static inline bool dirstate_item_c_added(dirstateItemObject *self)
149 148 {
150 const unsigned char mask =
151 (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
149 const int mask = (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
152 150 dirstate_flag_p2_info);
153 const unsigned char target = dirstate_flag_wc_tracked;
151 const int target = dirstate_flag_wc_tracked;
154 152 return (self->flags & mask) == target;
155 153 }
156 154
@@ -237,7 +235,7 b' static inline int dirstate_item_c_v1_mti'
237 235
238 236 static PyObject *dirstate_item_v2_data(dirstateItemObject *self)
239 237 {
240 unsigned char flags = self->flags;
238 int flags = self->flags;
241 239 int mode = dirstate_item_c_v1_mode(self);
242 240 if ((mode & S_IXUSR) != 0) {
243 241 flags |= dirstate_flag_mode_exec_perm;
@@ -249,7 +247,7 b' static PyObject *dirstate_item_v2_data(d'
249 247 } else {
250 248 flags &= ~dirstate_flag_mode_is_symlink;
251 249 }
252 return Py_BuildValue("Bii", flags, self->size, self->mtime);
250 return Py_BuildValue("iii", flags, self->size, self->mtime);
253 251 };
254 252
255 253 static PyObject *dirstate_item_v1_state(dirstateItemObject *self)
@@ -372,9 +370,14 b' static PyObject *dirstate_item_from_v2_m'
372 370 if (!t) {
373 371 return NULL;
374 372 }
375 if (!PyArg_ParseTuple(args, "bii", &t->flags, &t->size, &t->mtime)) {
373 if (!PyArg_ParseTuple(args, "iii", &t->flags, &t->size, &t->mtime)) {
376 374 return NULL;
377 375 }
376 if (t->flags & dirstate_flag_expected_state_is_modified) {
377 t->flags &= ~(dirstate_flag_expected_state_is_modified |
378 dirstate_flag_has_meaningful_data |
379 dirstate_flag_has_file_mtime);
380 }
378 381 t->mode = 0;
379 382 if (t->flags & dirstate_flag_has_meaningful_data) {
380 383 if (t->flags & dirstate_flag_mode_exec_perm) {
@@ -24,21 +24,22 b''
24 24 /* clang-format off */
25 25 typedef struct {
26 26 PyObject_HEAD
27 unsigned char flags;
27 int flags;
28 28 int mode;
29 29 int size;
30 30 int mtime;
31 31 } dirstateItemObject;
32 32 /* clang-format on */
33 33
34 static const unsigned char dirstate_flag_wc_tracked = 1;
35 static const unsigned char dirstate_flag_p1_tracked = 1 << 1;
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_file_mtime = 1 << 4;
39 static const unsigned char dirstate_flag_has_directory_mtime = 1 << 5;
40 static const unsigned char dirstate_flag_mode_exec_perm = 1 << 6;
41 static const unsigned char dirstate_flag_mode_is_symlink = 1 << 7;
34 static const int dirstate_flag_wc_tracked = 1;
35 static const int dirstate_flag_p1_tracked = 1 << 1;
36 static const int dirstate_flag_p2_info = 1 << 2;
37 static const int dirstate_flag_has_meaningful_data = 1 << 3;
38 static const int dirstate_flag_has_file_mtime = 1 << 4;
39 static const int dirstate_flag_has_directory_mtime = 1 << 5;
40 static const int dirstate_flag_mode_exec_perm = 1 << 6;
41 static const int dirstate_flag_mode_is_symlink = 1 << 7;
42 static const int dirstate_flag_expected_state_is_modified = 1 << 8;
42 43
43 44 extern PyTypeObject dirstateItemType;
44 45 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType)
@@ -383,6 +383,7 b' Node components are:'
383 383 HAS_DIRECTORY_MTIME = 1 << 5
384 384 MODE_EXEC_PERM = 1 << 6
385 385 MODE_IS_SYMLINK = 1 << 7
386 EXPECTED_STATE_IS_MODIFIED = 1 << 8
386 387
387 388 The meaning of each bit is described below.
388 389
@@ -461,8 +462,7 b' by enabling it to skip `readdir` in more'
461 462 Must be unset for untracked nodes.
462 463 For files tracked anywhere, if this is set:
463 464 - The `size` field is the expected file size,
464 in bytes truncated its lower to 31 bits,
465 for the file to be clean.
465 in bytes truncated its lower to 31 bits.
466 466 - The expected execute permission for the file’s owner
467 467 is given by `MODE_EXEC_PERM`
468 468 - The expected file type is given by `MODE_IS_SIMLINK`:
@@ -474,8 +474,7 b' by enabling it to skip `readdir` in more'
474 474 Must be unset for untracked nodes.
475 475 If this and `HAS_DIRECTORY_MTIME` are both unset,
476 476 the `mtime` field is unused (set to zero).
477 If this is set, `mtime` is the modification time
478 expected for the file to be considered clean.
477 If this is set, `mtime` is the expected modification time.
479 478
480 479 `HAS_DIRECTORY_MTIME`
481 480 Must be unset for file tracked anywhere.
@@ -514,3 +513,20 b' by enabling it to skip `readdir` in more'
514 513 If `HAS_MODE_AND_SIZE` is set,
515 514 this indicates whether the file is expected to be a symlink
516 515 as opposed to a normal file.
516
517 `EXPECTED_STATE_IS_MODIFIED`
518 Must be unset for untracked nodes.
519 For:
520 - a file tracked anywhere
521 - that has expected metadata (`HAS_MODE_AND_SIZE` and `HAS_FILE_MTIME`)
522 - if that metadata matches
523 metadata found in the working directory with `stat`
524 This bit indicates the status of the file.
525 If set, the status is modified. If unset, it is clean.
526
527 In cases where `hg status` needs to read the contents of a file
528 because metadata is ambiguous, this bit lets it record the result
529 if the result is modified so that a future run of `hg status`
530 does not need to do the same again.
531 It is valid to never set this bit,
532 and consider expected metadata ambiguous if it is set.
@@ -53,6 +53,7 b' DIRSTATE_V2_HAS_FILE_MTIME = 1 << 4'
53 53 _DIRSTATE_V2_HAS_DIRCTORY_MTIME = 1 << 5 # Unused when Rust is not available
54 54 DIRSTATE_V2_MODE_EXEC_PERM = 1 << 6
55 55 DIRSTATE_V2_MODE_IS_SYMLINK = 1 << 7
56 DIRSTATE_V2_EXPECTED_STATE_IS_MODIFIED = 1 << 8
56 57
57 58
58 59 @attr.s(slots=True, init=False)
@@ -123,7 +124,15 b' class DirstateItem(object):'
123 124 def from_v2_data(cls, flags, size, mtime):
124 125 """Build a new DirstateItem object from V2 data"""
125 126 has_mode_size = bool(flags & DIRSTATE_V2_HAS_MODE_AND_SIZE)
127 has_meaningful_mtime = bool(flags & DIRSTATE_V2_HAS_FILE_MTIME)
126 128 mode = None
129
130 if flags & +DIRSTATE_V2_EXPECTED_STATE_IS_MODIFIED:
131 # we do not have support for this flag in the code yet,
132 # force a lookup for this file.
133 has_mode_size = False
134 has_meaningful_mtime = False
135
127 136 if has_mode_size:
128 137 assert stat.S_IXUSR == 0o100
129 138 if flags & DIRSTATE_V2_MODE_EXEC_PERM:
@@ -139,7 +148,7 b' class DirstateItem(object):'
139 148 p1_tracked=bool(flags & DIRSTATE_V2_P1_TRACKED),
140 149 p2_info=bool(flags & DIRSTATE_V2_P2_INFO),
141 150 has_meaningful_data=has_mode_size,
142 has_meaningful_mtime=bool(flags & DIRSTATE_V2_HAS_FILE_MTIME),
151 has_meaningful_mtime=has_meaningful_mtime,
143 152 parentfiledata=(mode, size, mtime),
144 153 )
145 154
@@ -110,6 +110,7 b' bitflags! {'
110 110 const HAS_DIRECTORY_MTIME = 1 << 5;
111 111 const MODE_EXEC_PERM = 1 << 6;
112 112 const MODE_IS_SYMLINK = 1 << 7;
113 const EXPECTED_STATE_IS_MODIFIED = 1 << 8;
113 114 }
114 115 }
115 116
@@ -351,12 +352,16 b' impl Node {'
351 352 let wdir_tracked = self.flags().contains(Flags::WDIR_TRACKED);
352 353 let p1_tracked = self.flags().contains(Flags::P1_TRACKED);
353 354 let p2_info = self.flags().contains(Flags::P2_INFO);
354 let mode_size = if self.flags().contains(Flags::HAS_MODE_AND_SIZE) {
355 let mode_size = if self.flags().contains(Flags::HAS_MODE_AND_SIZE)
356 && !self.flags().contains(Flags::EXPECTED_STATE_IS_MODIFIED)
357 {
355 358 Some((self.synthesize_unix_mode(), self.size.into()))
356 359 } else {
357 360 None
358 361 };
359 let mtime = if self.flags().contains(Flags::HAS_FILE_MTIME) {
362 let mtime = if self.flags().contains(Flags::HAS_FILE_MTIME)
363 && !self.flags().contains(Flags::EXPECTED_STATE_IS_MODIFIED)
364 {
360 365 Some(self.mtime.truncated_seconds.into())
361 366 } else {
362 367 None
General Comments 0
You need to be logged in to leave comments. Login now