Show More
@@ -119,7 +119,7 b' static PyObject *dirstate_item_new(PyTyp' | |||
|
119 | 119 | t->size = 0; |
|
120 | 120 | } |
|
121 | 121 | if (has_meaningful_mtime) { |
|
122 |
t->flags |= dirstate_flag_has_ |
|
|
122 | t->flags |= dirstate_flag_has_file_mtime; | |
|
123 | 123 | t->mtime = mtime; |
|
124 | 124 | } else { |
|
125 | 125 | t->mtime = 0; |
@@ -225,7 +225,7 b' static inline int dirstate_item_c_v1_mti' | |||
|
225 | 225 | { |
|
226 | 226 | if (dirstate_item_c_removed(self)) { |
|
227 | 227 | return 0; |
|
228 |
} else if (!(self->flags & dirstate_flag_has_ |
|
|
228 | } else if (!(self->flags & dirstate_flag_has_file_mtime) || | |
|
229 | 229 | !(self->flags & dirstate_flag_p1_tracked) || |
|
230 | 230 | !(self->flags & dirstate_flag_wc_tracked) || |
|
231 | 231 | (self->flags & dirstate_flag_p2_info)) { |
@@ -334,7 +334,7 b' dirstate_item_from_v1_data(char state, i' | |||
|
334 | 334 | t->flags = (dirstate_flag_wc_tracked | |
|
335 | 335 | dirstate_flag_p1_tracked | |
|
336 | 336 | dirstate_flag_has_meaningful_data | |
|
337 |
dirstate_flag_has_ |
|
|
337 | dirstate_flag_has_file_mtime); | |
|
338 | 338 | t->mode = mode; |
|
339 | 339 | t->size = size; |
|
340 | 340 | t->mtime = mtime; |
@@ -395,7 +395,7 b' static PyObject *dirstate_item_from_v2_m' | |||
|
395 | 395 | to make sure it is correct. */ |
|
396 | 396 | static PyObject *dirstate_item_set_possibly_dirty(dirstateItemObject *self) |
|
397 | 397 | { |
|
398 |
self->flags &= ~dirstate_flag_has_ |
|
|
398 | self->flags &= ~dirstate_flag_has_file_mtime; | |
|
399 | 399 | Py_RETURN_NONE; |
|
400 | 400 | } |
|
401 | 401 | |
@@ -409,7 +409,7 b' static PyObject *dirstate_item_set_clean' | |||
|
409 | 409 | } |
|
410 | 410 | self->flags = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked | |
|
411 | 411 | dirstate_flag_has_meaningful_data | |
|
412 |
dirstate_flag_has_ |
|
|
412 | dirstate_flag_has_file_mtime; | |
|
413 | 413 | self->mode = mode; |
|
414 | 414 | self->size = size; |
|
415 | 415 | self->mtime = mtime; |
@@ -419,7 +419,7 b' static PyObject *dirstate_item_set_clean' | |||
|
419 | 419 | static PyObject *dirstate_item_set_tracked(dirstateItemObject *self) |
|
420 | 420 | { |
|
421 | 421 | self->flags |= dirstate_flag_wc_tracked; |
|
422 |
self->flags &= ~dirstate_flag_has_ |
|
|
422 | self->flags &= ~dirstate_flag_has_file_mtime; | |
|
423 | 423 | Py_RETURN_NONE; |
|
424 | 424 | } |
|
425 | 425 | |
@@ -437,7 +437,7 b' static PyObject *dirstate_item_drop_merg' | |||
|
437 | 437 | if (self->flags & dirstate_flag_p2_info) { |
|
438 | 438 | self->flags &= ~(dirstate_flag_p2_info | |
|
439 | 439 | dirstate_flag_has_meaningful_data | |
|
440 |
dirstate_flag_has_ |
|
|
440 | dirstate_flag_has_file_mtime); | |
|
441 | 441 | self->mode = 0; |
|
442 | 442 | self->mtime = 0; |
|
443 | 443 | self->size = 0; |
@@ -35,9 +35,10 b' static const unsigned char dirstate_flag' | |||
|
35 | 35 | static const unsigned char dirstate_flag_p1_tracked = 1 << 1; |
|
36 | 36 | static const unsigned char dirstate_flag_p2_info = 1 << 2; |
|
37 | 37 | static const unsigned char dirstate_flag_has_meaningful_data = 1 << 3; |
|
38 |
static const unsigned char dirstate_flag_has_ |
|
|
39 |
static const unsigned char dirstate_flag_ |
|
|
40 |
static const unsigned char dirstate_flag_mode_ |
|
|
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; | |
|
41 | 42 | |
|
42 | 43 | extern PyTypeObject dirstateItemType; |
|
43 | 44 | #define dirstate_tuple_check(op) (Py_TYPE(op) == &dirstateItemType) |
@@ -379,9 +379,10 b' Node components are:' | |||
|
379 | 379 | P1_TRACKED = 1 << 1 |
|
380 | 380 | P2_INFO = 1 << 2 |
|
381 | 381 | HAS_MODE_AND_SIZE = 1 << 3 |
|
382 | HAS_MTIME = 1 << 4 | |
|
383 |
|
|
|
384 |
MODE_ |
|
|
382 | HAS_FILE_MTIME = 1 << 4 | |
|
383 | HAS_DIRECTORY_MTIME = 1 << 5 | |
|
384 | MODE_EXEC_PERM = 1 << 6 | |
|
385 | MODE_IS_SYMLINK = 1 << 7 | |
|
385 | 386 | |
|
386 | 387 | The meaning of each bit is described below. |
|
387 | 388 | |
@@ -401,10 +402,25 b' Node components are:' | |||
|
401 | 402 | The seconds component of an `mtime` field described below, |
|
402 | 403 | as a 32-bit integer. |
|
403 | 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 | 408 | * Offset 40: |
|
406 | 409 | The nanoseconds component of an `mtime` field described below, |
|
407 | 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 | 425 | * (Offset 44: end of this node) |
|
410 | 426 | |
@@ -454,21 +470,18 b' by enabling it to skip `readdir` in more' | |||
|
454 | 470 | If this is unset the expected size, permission, and file type are unknown. |
|
455 | 471 | The `size` field is unused (set to zero). |
|
456 | 472 | |
|
457 | `HAS_MTIME` | |
|
458 | If unset, the `mtime` field is unused (set to zero). | |
|
459 | If set, it contains a timestamp represented as | |
|
460 | - the number of seconds since the Unix epoch, | |
|
461 | truncated to its lower 31 bits. | |
|
462 | - and the number of nanoseconds since `mtime.seconds`, | |
|
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, β¦) | |
|
473 | `HAS_FILE_MTIME` | |
|
474 | Must be unset for untracked nodes. | |
|
475 | If this and `HAS_DIRECTORY_MTIME` are both unset, | |
|
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. | |
|
467 | 479 | |
|
468 | If set for a file tracked anywhere, | |
|
469 | `mtime` is the expected modification time for the file to be clean. | |
|
470 | ||
|
471 | If set for an untracked node, at some point, | |
|
480 | `HAS_DIRECTORY_MTIME` | |
|
481 | Must be unset for file tracked anywhere. | |
|
482 | If this and `HAS_DIRECTORY_MTIME` are both unset, | |
|
483 | the `mtime` field is unused (set to zero). | |
|
484 | If this is set, at some point, | |
|
472 | 485 | this path in the working directory was observed: |
|
473 | 486 | |
|
474 | 487 | - To be a directory |
@@ -49,9 +49,10 b' DIRSTATE_V2_WDIR_TRACKED = 1 << 0' | |||
|
49 | 49 | DIRSTATE_V2_P1_TRACKED = 1 << 1 |
|
50 | 50 | DIRSTATE_V2_P2_INFO = 1 << 2 |
|
51 | 51 | DIRSTATE_V2_HAS_MODE_AND_SIZE = 1 << 3 |
|
52 | DIRSTATE_V2_HAS_MTIME = 1 << 4 | |
|
53 | DIRSTATE_V2_MODE_EXEC_PERM = 1 << 5 | |
|
54 |
DIRSTATE_V2_MODE_ |
|
|
52 | DIRSTATE_V2_HAS_FILE_MTIME = 1 << 4 | |
|
53 | _DIRSTATE_V2_HAS_DIRCTORY_MTIME = 1 << 5 # Unused when Rust is not available | |
|
54 | DIRSTATE_V2_MODE_EXEC_PERM = 1 << 6 | |
|
55 | DIRSTATE_V2_MODE_IS_SYMLINK = 1 << 7 | |
|
55 | 56 | |
|
56 | 57 | |
|
57 | 58 | @attr.s(slots=True, init=False) |
@@ -138,7 +139,7 b' class DirstateItem(object):' | |||
|
138 | 139 | p1_tracked=bool(flags & DIRSTATE_V2_P1_TRACKED), |
|
139 | 140 | p2_info=bool(flags & DIRSTATE_V2_P2_INFO), |
|
140 | 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 | 143 | parentfiledata=(mode, size, mtime), |
|
143 | 144 | ) |
|
144 | 145 | |
@@ -329,7 +330,7 b' class DirstateItem(object):' | |||
|
329 | 330 | if stat.S_ISLNK(self.mode): |
|
330 | 331 | flags |= DIRSTATE_V2_MODE_IS_SYMLINK |
|
331 | 332 | if self._mtime is not None: |
|
332 | flags |= DIRSTATE_V2_HAS_MTIME | |
|
333 | flags |= DIRSTATE_V2_HAS_FILE_MTIME | |
|
333 | 334 | return (flags, self._size or 0, self._mtime or 0) |
|
334 | 335 | |
|
335 | 336 | def v1_state(self): |
@@ -106,9 +106,10 b' bitflags! {' | |||
|
106 | 106 | const P1_TRACKED = 1 << 1; |
|
107 | 107 | const P2_INFO = 1 << 2; |
|
108 | 108 | const HAS_MODE_AND_SIZE = 1 << 3; |
|
109 | const HAS_MTIME = 1 << 4; | |
|
110 |
const |
|
|
111 |
const MODE_ |
|
|
109 | const HAS_FILE_MTIME = 1 << 4; | |
|
110 | const HAS_DIRECTORY_MTIME = 1 << 5; | |
|
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 | 321 | pub(super) fn cached_directory_mtime( |
|
321 | 322 | &self, |
|
322 | 323 | ) -> Result<Option<TruncatedTimestamp>, DirstateV2ParseError> { |
|
323 | Ok( | |
|
324 |
if self.flags().contains(Flags::HAS_MTIME |
|
|
325 | Some(self.mtime.try_into()?) | |
|
324 | if self.flags().contains(Flags::HAS_DIRECTORY_MTIME) { | |
|
325 | if self.flags().contains(Flags::HAS_FILE_MTIME) { | |
|
326 | Err(DirstateV2ParseError) | |
|
326 | 327 | } else { |
|
327 | None | |
|
328 |
} |
|
|
329 |
|
|
|
328 | Ok(Some(self.mtime.try_into()?)) | |
|
329 | } | |
|
330 | } else { | |
|
331 | Ok(None) | |
|
332 | } | |
|
330 | 333 | } |
|
331 | 334 | |
|
332 | 335 | fn synthesize_unix_mode(&self) -> u32 { |
@@ -353,7 +356,7 b' impl Node {' | |||
|
353 | 356 | } else { |
|
354 | 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 | 360 | Some(self.mtime.truncated_seconds.into()) |
|
358 | 361 | } else { |
|
359 | 362 | None |
@@ -422,7 +425,7 b' impl Node {' | |||
|
422 | 425 | 0.into() |
|
423 | 426 | }; |
|
424 | 427 | let mtime = if let Some(m) = mtime_opt { |
|
425 | flags.insert(Flags::HAS_MTIME); | |
|
428 | flags.insert(Flags::HAS_FILE_MTIME); | |
|
426 | 429 | PackedTruncatedTimestamp { |
|
427 | 430 | truncated_seconds: m.into(), |
|
428 | 431 | nanoseconds: 0.into(), |
@@ -580,9 +583,11 b" impl Writer<'_, '_> {" | |||
|
580 | 583 | dirstate_map::NodeData::Entry(entry) => { |
|
581 | 584 | Node::from_dirstate_entry(entry) |
|
582 | 585 | } |
|
583 |
dirstate_map::NodeData::CachedDirectory { mtime } => |
|
|
584 |
|
|
|
585 |
|
|
|
586 | dirstate_map::NodeData::CachedDirectory { mtime } => ( | |
|
587 | Flags::HAS_DIRECTORY_MTIME, | |
|
588 | 0.into(), | |
|
589 | (*mtime).into(), | |
|
590 | ), | |
|
586 | 591 | dirstate_map::NodeData::None => ( |
|
587 | 592 | Flags::empty(), |
|
588 | 593 | 0.into(), |
General Comments 0
You need to be logged in to leave comments.
Login now