##// 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 static inline bool dirstate_item_c_any_tracked(dirstateItemObject *self)
140 static inline bool dirstate_item_c_any_tracked(dirstateItemObject *self)
141 {
141 {
142 const unsigned char mask = dirstate_flag_wc_tracked |
142 const int mask = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
143 dirstate_flag_p1_tracked |
144 dirstate_flag_p2_info;
143 dirstate_flag_p2_info;
145 return (self->flags & mask);
144 return (self->flags & mask);
146 }
145 }
147
146
148 static inline bool dirstate_item_c_added(dirstateItemObject *self)
147 static inline bool dirstate_item_c_added(dirstateItemObject *self)
149 {
148 {
150 const unsigned char mask =
149 const int mask = (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
151 (dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
152 dirstate_flag_p2_info);
150 dirstate_flag_p2_info);
153 const unsigned char target = dirstate_flag_wc_tracked;
151 const int target = dirstate_flag_wc_tracked;
154 return (self->flags & mask) == target;
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 static PyObject *dirstate_item_v2_data(dirstateItemObject *self)
236 static PyObject *dirstate_item_v2_data(dirstateItemObject *self)
239 {
237 {
240 unsigned char flags = self->flags;
238 int flags = self->flags;
241 int mode = dirstate_item_c_v1_mode(self);
239 int mode = dirstate_item_c_v1_mode(self);
242 if ((mode & S_IXUSR) != 0) {
240 if ((mode & S_IXUSR) != 0) {
243 flags |= dirstate_flag_mode_exec_perm;
241 flags |= dirstate_flag_mode_exec_perm;
@@ -249,7 +247,7 b' static PyObject *dirstate_item_v2_data(d'
249 } else {
247 } else {
250 flags &= ~dirstate_flag_mode_is_symlink;
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 static PyObject *dirstate_item_v1_state(dirstateItemObject *self)
253 static PyObject *dirstate_item_v1_state(dirstateItemObject *self)
@@ -372,9 +370,14 b' static PyObject *dirstate_item_from_v2_m'
372 if (!t) {
370 if (!t) {
373 return NULL;
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 return NULL;
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 t->mode = 0;
381 t->mode = 0;
379 if (t->flags & dirstate_flag_has_meaningful_data) {
382 if (t->flags & dirstate_flag_has_meaningful_data) {
380 if (t->flags & dirstate_flag_mode_exec_perm) {
383 if (t->flags & dirstate_flag_mode_exec_perm) {
@@ -24,21 +24,22 b''
24 /* clang-format off */
24 /* clang-format off */
25 typedef struct {
25 typedef struct {
26 PyObject_HEAD
26 PyObject_HEAD
27 unsigned char flags;
27 int flags;
28 int mode;
28 int mode;
29 int size;
29 int size;
30 int mtime;
30 int mtime;
31 } dirstateItemObject;
31 } dirstateItemObject;
32 /* clang-format on */
32 /* clang-format on */
33
33
34 static const unsigned char dirstate_flag_wc_tracked = 1;
34 static const int dirstate_flag_wc_tracked = 1;
35 static const unsigned char dirstate_flag_p1_tracked = 1 << 1;
35 static const int dirstate_flag_p1_tracked = 1 << 1;
36 static const unsigned char dirstate_flag_p2_info = 1 << 2;
36 static const int dirstate_flag_p2_info = 1 << 2;
37 static const unsigned char dirstate_flag_has_meaningful_data = 1 << 3;
37 static const int dirstate_flag_has_meaningful_data = 1 << 3;
38 static const unsigned char dirstate_flag_has_file_mtime = 1 << 4;
38 static const int dirstate_flag_has_file_mtime = 1 << 4;
39 static const unsigned char dirstate_flag_has_directory_mtime = 1 << 5;
39 static const int dirstate_flag_has_directory_mtime = 1 << 5;
40 static const unsigned char dirstate_flag_mode_exec_perm = 1 << 6;
40 static const int dirstate_flag_mode_exec_perm = 1 << 6;
41 static const unsigned char dirstate_flag_mode_is_symlink = 1 << 7;
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 extern PyTypeObject dirstateItemType;
44 extern PyTypeObject dirstateItemType;
44 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType)
45 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType)
@@ -383,6 +383,7 b' Node components are:'
383 HAS_DIRECTORY_MTIME = 1 << 5
383 HAS_DIRECTORY_MTIME = 1 << 5
384 MODE_EXEC_PERM = 1 << 6
384 MODE_EXEC_PERM = 1 << 6
385 MODE_IS_SYMLINK = 1 << 7
385 MODE_IS_SYMLINK = 1 << 7
386 EXPECTED_STATE_IS_MODIFIED = 1 << 8
386
387
387 The meaning of each bit is described below.
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 Must be unset for untracked nodes.
462 Must be unset for untracked nodes.
462 For files tracked anywhere, if this is set:
463 For files tracked anywhere, if this is set:
463 - The `size` field is the expected file size,
464 - The `size` field is the expected file size,
464 in bytes truncated its lower to 31 bits,
465 in bytes truncated its lower to 31 bits.
465 for the file to be clean.
466 - The expected execute permission for the file’s owner
466 - The expected execute permission for the file’s owner
467 is given by `MODE_EXEC_PERM`
467 is given by `MODE_EXEC_PERM`
468 - The expected file type is given by `MODE_IS_SIMLINK`:
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 Must be unset for untracked nodes.
474 Must be unset for untracked nodes.
475 If this and `HAS_DIRECTORY_MTIME` are both unset,
475 If this and `HAS_DIRECTORY_MTIME` are both unset,
476 the `mtime` field is unused (set to zero).
476 the `mtime` field is unused (set to zero).
477 If this is set, `mtime` is the modification time
477 If this is set, `mtime` is the expected modification time.
478 expected for the file to be considered clean.
479
478
480 `HAS_DIRECTORY_MTIME`
479 `HAS_DIRECTORY_MTIME`
481 Must be unset for file tracked anywhere.
480 Must be unset for file tracked anywhere.
@@ -514,3 +513,20 b' by enabling it to skip `readdir` in more'
514 If `HAS_MODE_AND_SIZE` is set,
513 If `HAS_MODE_AND_SIZE` is set,
515 this indicates whether the file is expected to be a symlink
514 this indicates whether the file is expected to be a symlink
516 as opposed to a normal file.
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 _DIRSTATE_V2_HAS_DIRCTORY_MTIME = 1 << 5 # Unused when Rust is not available
53 _DIRSTATE_V2_HAS_DIRCTORY_MTIME = 1 << 5 # Unused when Rust is not available
54 DIRSTATE_V2_MODE_EXEC_PERM = 1 << 6
54 DIRSTATE_V2_MODE_EXEC_PERM = 1 << 6
55 DIRSTATE_V2_MODE_IS_SYMLINK = 1 << 7
55 DIRSTATE_V2_MODE_IS_SYMLINK = 1 << 7
56 DIRSTATE_V2_EXPECTED_STATE_IS_MODIFIED = 1 << 8
56
57
57
58
58 @attr.s(slots=True, init=False)
59 @attr.s(slots=True, init=False)
@@ -123,7 +124,15 b' class DirstateItem(object):'
123 def from_v2_data(cls, flags, size, mtime):
124 def from_v2_data(cls, flags, size, mtime):
124 """Build a new DirstateItem object from V2 data"""
125 """Build a new DirstateItem object from V2 data"""
125 has_mode_size = bool(flags & DIRSTATE_V2_HAS_MODE_AND_SIZE)
126 has_mode_size = bool(flags & DIRSTATE_V2_HAS_MODE_AND_SIZE)
127 has_meaningful_mtime = bool(flags & DIRSTATE_V2_HAS_FILE_MTIME)
126 mode = None
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 if has_mode_size:
136 if has_mode_size:
128 assert stat.S_IXUSR == 0o100
137 assert stat.S_IXUSR == 0o100
129 if flags & DIRSTATE_V2_MODE_EXEC_PERM:
138 if flags & DIRSTATE_V2_MODE_EXEC_PERM:
@@ -139,7 +148,7 b' class DirstateItem(object):'
139 p1_tracked=bool(flags & DIRSTATE_V2_P1_TRACKED),
148 p1_tracked=bool(flags & DIRSTATE_V2_P1_TRACKED),
140 p2_info=bool(flags & DIRSTATE_V2_P2_INFO),
149 p2_info=bool(flags & DIRSTATE_V2_P2_INFO),
141 has_meaningful_data=has_mode_size,
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 parentfiledata=(mode, size, mtime),
152 parentfiledata=(mode, size, mtime),
144 )
153 )
145
154
@@ -110,6 +110,7 b' bitflags! {'
110 const HAS_DIRECTORY_MTIME = 1 << 5;
110 const HAS_DIRECTORY_MTIME = 1 << 5;
111 const MODE_EXEC_PERM = 1 << 6;
111 const MODE_EXEC_PERM = 1 << 6;
112 const MODE_IS_SYMLINK = 1 << 7;
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 let wdir_tracked = self.flags().contains(Flags::WDIR_TRACKED);
352 let wdir_tracked = self.flags().contains(Flags::WDIR_TRACKED);
352 let p1_tracked = self.flags().contains(Flags::P1_TRACKED);
353 let p1_tracked = self.flags().contains(Flags::P1_TRACKED);
353 let p2_info = self.flags().contains(Flags::P2_INFO);
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 Some((self.synthesize_unix_mode(), self.size.into()))
358 Some((self.synthesize_unix_mode(), self.size.into()))
356 } else {
359 } else {
357 None
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 Some(self.mtime.truncated_seconds.into())
365 Some(self.mtime.truncated_seconds.into())
361 } else {
366 } else {
362 None
367 None
General Comments 0
You need to be logged in to leave comments. Login now