##// END OF EJS Templates
dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags...
Simon Sapin -
r49046:f7fd629f default
parent child Browse files
Show More
@@ -119,7 +119,7 b' static PyObject *dirstate_item_new(PyTyp'
119 t->size = 0;
119 t->size = 0;
120 }
120 }
121 if (has_meaningful_mtime) {
121 if (has_meaningful_mtime) {
122 t->flags |= dirstate_flag_has_meaningful_mtime;
122 t->flags |= dirstate_flag_has_file_mtime;
123 t->mtime = mtime;
123 t->mtime = mtime;
124 } else {
124 } else {
125 t->mtime = 0;
125 t->mtime = 0;
@@ -225,7 +225,7 b' static inline int dirstate_item_c_v1_mti'
225 {
225 {
226 if (dirstate_item_c_removed(self)) {
226 if (dirstate_item_c_removed(self)) {
227 return 0;
227 return 0;
228 } else if (!(self->flags & dirstate_flag_has_meaningful_mtime) ||
228 } else if (!(self->flags & dirstate_flag_has_file_mtime) ||
229 !(self->flags & dirstate_flag_p1_tracked) ||
229 !(self->flags & dirstate_flag_p1_tracked) ||
230 !(self->flags & dirstate_flag_wc_tracked) ||
230 !(self->flags & dirstate_flag_wc_tracked) ||
231 (self->flags & dirstate_flag_p2_info)) {
231 (self->flags & dirstate_flag_p2_info)) {
@@ -334,7 +334,7 b' dirstate_item_from_v1_data(char state, i'
334 t->flags = (dirstate_flag_wc_tracked |
334 t->flags = (dirstate_flag_wc_tracked |
335 dirstate_flag_p1_tracked |
335 dirstate_flag_p1_tracked |
336 dirstate_flag_has_meaningful_data |
336 dirstate_flag_has_meaningful_data |
337 dirstate_flag_has_meaningful_mtime);
337 dirstate_flag_has_file_mtime);
338 t->mode = mode;
338 t->mode = mode;
339 t->size = size;
339 t->size = size;
340 t->mtime = mtime;
340 t->mtime = mtime;
@@ -395,7 +395,7 b' static PyObject *dirstate_item_from_v2_m'
395 to make sure it is correct. */
395 to make sure it is correct. */
396 static PyObject *dirstate_item_set_possibly_dirty(dirstateItemObject *self)
396 static PyObject *dirstate_item_set_possibly_dirty(dirstateItemObject *self)
397 {
397 {
398 self->flags &= ~dirstate_flag_has_meaningful_mtime;
398 self->flags &= ~dirstate_flag_has_file_mtime;
399 Py_RETURN_NONE;
399 Py_RETURN_NONE;
400 }
400 }
401
401
@@ -409,7 +409,7 b' static PyObject *dirstate_item_set_clean'
409 }
409 }
410 self->flags = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
410 self->flags = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked |
411 dirstate_flag_has_meaningful_data |
411 dirstate_flag_has_meaningful_data |
412 dirstate_flag_has_meaningful_mtime;
412 dirstate_flag_has_file_mtime;
413 self->mode = mode;
413 self->mode = mode;
414 self->size = size;
414 self->size = size;
415 self->mtime = mtime;
415 self->mtime = mtime;
@@ -419,7 +419,7 b' static PyObject *dirstate_item_set_clean'
419 static PyObject *dirstate_item_set_tracked(dirstateItemObject *self)
419 static PyObject *dirstate_item_set_tracked(dirstateItemObject *self)
420 {
420 {
421 self->flags |= dirstate_flag_wc_tracked;
421 self->flags |= dirstate_flag_wc_tracked;
422 self->flags &= ~dirstate_flag_has_meaningful_mtime;
422 self->flags &= ~dirstate_flag_has_file_mtime;
423 Py_RETURN_NONE;
423 Py_RETURN_NONE;
424 }
424 }
425
425
@@ -437,7 +437,7 b' static PyObject *dirstate_item_drop_merg'
437 if (self->flags & dirstate_flag_p2_info) {
437 if (self->flags & dirstate_flag_p2_info) {
438 self->flags &= ~(dirstate_flag_p2_info |
438 self->flags &= ~(dirstate_flag_p2_info |
439 dirstate_flag_has_meaningful_data |
439 dirstate_flag_has_meaningful_data |
440 dirstate_flag_has_meaningful_mtime);
440 dirstate_flag_has_file_mtime);
441 self->mode = 0;
441 self->mode = 0;
442 self->mtime = 0;
442 self->mtime = 0;
443 self->size = 0;
443 self->size = 0;
@@ -35,9 +35,10 b' static const unsigned char dirstate_flag'
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_info = 1 << 2;
36 static const unsigned char dirstate_flag_p2_info = 1 << 2;
37 static const unsigned char dirstate_flag_has_meaningful_data = 1 << 3;
37 static const unsigned char dirstate_flag_has_meaningful_data = 1 << 3;
38 static const unsigned char dirstate_flag_has_meaningful_mtime = 1 << 4;
38 static const unsigned char dirstate_flag_has_file_mtime = 1 << 4;
39 static const unsigned char dirstate_flag_mode_exec_perm = 1 << 5;
39 static const unsigned char dirstate_flag_has_directory_mtime = 1 << 5;
40 static const unsigned char dirstate_flag_mode_is_symlink = 1 << 6;
40 static const unsigned char dirstate_flag_mode_exec_perm = 1 << 6;
41 static const unsigned char dirstate_flag_mode_is_symlink = 1 << 7;
41
42
42 extern PyTypeObject dirstateItemType;
43 extern PyTypeObject dirstateItemType;
43 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType)
44 #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType)
@@ -379,9 +379,10 b' Node components are:'
379 P1_TRACKED = 1 << 1
379 P1_TRACKED = 1 << 1
380 P2_INFO = 1 << 2
380 P2_INFO = 1 << 2
381 HAS_MODE_AND_SIZE = 1 << 3
381 HAS_MODE_AND_SIZE = 1 << 3
382 HAS_MTIME = 1 << 4
382 HAS_FILE_MTIME = 1 << 4
383 MODE_EXEC_PERM = 1 << 5
383 HAS_DIRECTORY_MTIME = 1 << 5
384 MODE_IS_SYMLINK = 1 << 6
384 MODE_EXEC_PERM = 1 << 6
385 MODE_IS_SYMLINK = 1 << 7
385
386
386 The meaning of each bit is described below.
387 The meaning of each bit is described below.
387
388
@@ -401,10 +402,25 b' Node components are:'
401 The seconds component of an `mtime` field described below,
402 The seconds component of an `mtime` field described below,
402 as a 32-bit integer.
403 as a 32-bit integer.
403 Unlike in dirstate-v1, negative values are not used.
404 Unlike in dirstate-v1, negative values are not used.
405 When `mtime` is used, this is number of seconds since the Unix epoch
406 truncated to its lower 31 bits.
404
407
405 * Offset 40:
408 * Offset 40:
406 The nanoseconds component of an `mtime` field described below,
409 The nanoseconds component of an `mtime` field described below,
407 as a 32-bit integer.
410 as a 32-bit integer.
411 When `mtime` is used,
412 this is the number of nanoseconds since `mtime.seconds`,
413 always stritctly less than one billion.
414
415 This may be zero if more precision is not available.
416 (This can happen because of limitations in any of Mercurial, Python,
417 libc, the operating system, …)
418
419 When comparing two mtimes and either has this component set to zero,
420 the sub-second precision of both should be ignored.
421 False positives when checking mtime equality due to clock resolution
422 are always possible and the status algorithm needs to deal with them,
423 but having too many false negatives could be harmful too.
408
424
409 * (Offset 44: end of this node)
425 * (Offset 44: end of this node)
410
426
@@ -454,21 +470,18 b' by enabling it to skip `readdir` in more'
454 If this is unset the expected size, permission, and file type are unknown.
470 If this is unset the expected size, permission, and file type are unknown.
455 The `size` field is unused (set to zero).
471 The `size` field is unused (set to zero).
456
472
457 `HAS_MTIME`
473 `HAS_FILE_MTIME`
458 If unset, the `mtime` field is unused (set to zero).
474 Must be unset for untracked nodes.
459 If set, it contains a timestamp represented as
475 If this and `HAS_DIRECTORY_MTIME` are both unset,
460 - the number of seconds since the Unix epoch,
476 the `mtime` field is unused (set to zero).
461 truncated to its lower 31 bits.
477 If this is set, `mtime` is the modification time
462 - and the number of nanoseconds since `mtime.seconds`,
478 expected for the file to be considered clean.
463 always stritctly less than one billion.
464 This may be zero if more precision is not available.
465 (This can happen because of limitations in any of Mercurial, Python,
466 libc, the operating system, …)
467
479
468 If set for a file tracked anywhere,
480 `HAS_DIRECTORY_MTIME`
469 `mtime` is the expected modification time for the file to be clean.
481 Must be unset for file tracked anywhere.
470
482 If this and `HAS_DIRECTORY_MTIME` are both unset,
471 If set for an untracked node, at some point,
483 the `mtime` field is unused (set to zero).
484 If this is set, at some point,
472 this path in the working directory was observed:
485 this path in the working directory was observed:
473
486
474 - To be a directory
487 - To be a directory
@@ -49,9 +49,10 b' DIRSTATE_V2_WDIR_TRACKED = 1 << 0'
49 DIRSTATE_V2_P1_TRACKED = 1 << 1
49 DIRSTATE_V2_P1_TRACKED = 1 << 1
50 DIRSTATE_V2_P2_INFO = 1 << 2
50 DIRSTATE_V2_P2_INFO = 1 << 2
51 DIRSTATE_V2_HAS_MODE_AND_SIZE = 1 << 3
51 DIRSTATE_V2_HAS_MODE_AND_SIZE = 1 << 3
52 DIRSTATE_V2_HAS_MTIME = 1 << 4
52 DIRSTATE_V2_HAS_FILE_MTIME = 1 << 4
53 DIRSTATE_V2_MODE_EXEC_PERM = 1 << 5
53 _DIRSTATE_V2_HAS_DIRCTORY_MTIME = 1 << 5 # Unused when Rust is not available
54 DIRSTATE_V2_MODE_IS_SYMLINK = 1 << 6
54 DIRSTATE_V2_MODE_EXEC_PERM = 1 << 6
55 DIRSTATE_V2_MODE_IS_SYMLINK = 1 << 7
55
56
56
57
57 @attr.s(slots=True, init=False)
58 @attr.s(slots=True, init=False)
@@ -138,7 +139,7 b' class DirstateItem(object):'
138 p1_tracked=bool(flags & DIRSTATE_V2_P1_TRACKED),
139 p1_tracked=bool(flags & DIRSTATE_V2_P1_TRACKED),
139 p2_info=bool(flags & DIRSTATE_V2_P2_INFO),
140 p2_info=bool(flags & DIRSTATE_V2_P2_INFO),
140 has_meaningful_data=has_mode_size,
141 has_meaningful_data=has_mode_size,
141 has_meaningful_mtime=bool(flags & DIRSTATE_V2_HAS_MTIME),
142 has_meaningful_mtime=bool(flags & DIRSTATE_V2_HAS_FILE_MTIME),
142 parentfiledata=(mode, size, mtime),
143 parentfiledata=(mode, size, mtime),
143 )
144 )
144
145
@@ -329,7 +330,7 b' class DirstateItem(object):'
329 if stat.S_ISLNK(self.mode):
330 if stat.S_ISLNK(self.mode):
330 flags |= DIRSTATE_V2_MODE_IS_SYMLINK
331 flags |= DIRSTATE_V2_MODE_IS_SYMLINK
331 if self._mtime is not None:
332 if self._mtime is not None:
332 flags |= DIRSTATE_V2_HAS_MTIME
333 flags |= DIRSTATE_V2_HAS_FILE_MTIME
333 return (flags, self._size or 0, self._mtime or 0)
334 return (flags, self._size or 0, self._mtime or 0)
334
335
335 def v1_state(self):
336 def v1_state(self):
@@ -106,9 +106,10 b' bitflags! {'
106 const P1_TRACKED = 1 << 1;
106 const P1_TRACKED = 1 << 1;
107 const P2_INFO = 1 << 2;
107 const P2_INFO = 1 << 2;
108 const HAS_MODE_AND_SIZE = 1 << 3;
108 const HAS_MODE_AND_SIZE = 1 << 3;
109 const HAS_MTIME = 1 << 4;
109 const HAS_FILE_MTIME = 1 << 4;
110 const MODE_EXEC_PERM = 1 << 5;
110 const HAS_DIRECTORY_MTIME = 1 << 5;
111 const MODE_IS_SYMLINK = 1 << 6;
111 const MODE_EXEC_PERM = 1 << 6;
112 const MODE_IS_SYMLINK = 1 << 7;
112 }
113 }
113 }
114 }
114
115
@@ -320,13 +321,15 b' impl Node {'
320 pub(super) fn cached_directory_mtime(
321 pub(super) fn cached_directory_mtime(
321 &self,
322 &self,
322 ) -> Result<Option<TruncatedTimestamp>, DirstateV2ParseError> {
323 ) -> Result<Option<TruncatedTimestamp>, DirstateV2ParseError> {
323 Ok(
324 if self.flags().contains(Flags::HAS_DIRECTORY_MTIME) {
324 if self.flags().contains(Flags::HAS_MTIME) && !self.has_entry() {
325 if self.flags().contains(Flags::HAS_FILE_MTIME) {
325 Some(self.mtime.try_into()?)
326 Err(DirstateV2ParseError)
326 } else {
327 } else {
327 None
328 Ok(Some(self.mtime.try_into()?))
328 },
329 }
329 )
330 } else {
331 Ok(None)
332 }
330 }
333 }
331
334
332 fn synthesize_unix_mode(&self) -> u32 {
335 fn synthesize_unix_mode(&self) -> u32 {
@@ -353,7 +356,7 b' impl Node {'
353 } else {
356 } else {
354 None
357 None
355 };
358 };
356 let mtime = if self.flags().contains(Flags::HAS_MTIME) {
359 let mtime = if self.flags().contains(Flags::HAS_FILE_MTIME) {
357 Some(self.mtime.truncated_seconds.into())
360 Some(self.mtime.truncated_seconds.into())
358 } else {
361 } else {
359 None
362 None
@@ -422,7 +425,7 b' impl Node {'
422 0.into()
425 0.into()
423 };
426 };
424 let mtime = if let Some(m) = mtime_opt {
427 let mtime = if let Some(m) = mtime_opt {
425 flags.insert(Flags::HAS_MTIME);
428 flags.insert(Flags::HAS_FILE_MTIME);
426 PackedTruncatedTimestamp {
429 PackedTruncatedTimestamp {
427 truncated_seconds: m.into(),
430 truncated_seconds: m.into(),
428 nanoseconds: 0.into(),
431 nanoseconds: 0.into(),
@@ -580,9 +583,11 b" impl Writer<'_, '_> {"
580 dirstate_map::NodeData::Entry(entry) => {
583 dirstate_map::NodeData::Entry(entry) => {
581 Node::from_dirstate_entry(entry)
584 Node::from_dirstate_entry(entry)
582 }
585 }
583 dirstate_map::NodeData::CachedDirectory { mtime } => {
586 dirstate_map::NodeData::CachedDirectory { mtime } => (
584 (Flags::HAS_MTIME, 0.into(), (*mtime).into())
587 Flags::HAS_DIRECTORY_MTIME,
585 }
588 0.into(),
589 (*mtime).into(),
590 ),
586 dirstate_map::NodeData::None => (
591 dirstate_map::NodeData::None => (
587 Flags::empty(),
592 Flags::empty(),
588 0.into(),
593 0.into(),
General Comments 0
You need to be logged in to leave comments. Login now