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_ |
|
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_ |
|
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_ |
|
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_ |
|
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_ |
|
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_ |
|
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_ |
|
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_ |
|
38 | static const unsigned char dirstate_flag_has_file_mtime = 1 << 4; | |
39 |
static const unsigned char dirstate_flag_ |
|
39 | static const unsigned char dirstate_flag_has_directory_mtime = 1 << 5; | |
40 |
static const unsigned char dirstate_flag_mode_ |
|
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 |
|
|
383 | HAS_DIRECTORY_MTIME = 1 << 5 | |
384 |
MODE_ |
|
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_ |
|
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 |
|
110 | const HAS_DIRECTORY_MTIME = 1 << 5; | |
111 |
const MODE_ |
|
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 |
|
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 |
|
|
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