diff --git a/mercurial/dirstateutils/timestamp.py b/mercurial/dirstateutils/timestamp.py --- a/mercurial/dirstateutils/timestamp.py +++ b/mercurial/dirstateutils/timestamp.py @@ -66,12 +66,22 @@ def mtime_of(stat_result): Takes an `os.stat_result`-like object and returns a `timestamp` object for its modification time. """ - # https://docs.python.org/2/library/os.html#os.stat_float_times - # "For compatibility with older Python versions, - # accessing stat_result as a tuple always returns integers." - secs = stat_result[stat.ST_MTIME] + try: + # TODO: add this attribute to `osutil.stat` objects, + # see `mercurial/cext/osutil.c`. + # + # This attribute is also not available on Python 2. + nanos = stat_result.st_mtime_ns + except AttributeError: + # https://docs.python.org/2/library/os.html#os.stat_float_times + # "For compatibility with older Python versions, + # accessing stat_result as a tuple always returns integers." + secs = stat_result[stat.ST_MTIME] - # For now - subsec_nanos = 0 + subsec_nanos = 0 + else: + billion = int(1e9) + secs = nanos // billion + subsec_nanos = nanos % billion return timestamp((secs, subsec_nanos)) diff --git a/mercurial/dirstateutils/v2.py b/mercurial/dirstateutils/v2.py --- a/mercurial/dirstateutils/v2.py +++ b/mercurial/dirstateutils/v2.py @@ -101,15 +101,12 @@ def parse_nodes(map, copy_map, data, sta flags, size, mtime_s, - _mtime_ns, + mtime_ns, ) = NODE.unpack(node_bytes) # Parse child nodes of this node recursively parse_nodes(map, copy_map, data, children_start, children_count) - # Don’t yet use sub-second precision if it exists in the file, - # since other parts of the code still set it to zero. - mtime_ns = 0 item = parsers.DirstateItem.from_v2_data(flags, size, mtime_s, mtime_ns) if not item.any_tracked: continue diff --git a/rust/hg-core/src/dirstate/entry.rs b/rust/hg-core/src/dirstate/entry.rs --- a/rust/hg-core/src/dirstate/entry.rs +++ b/rust/hg-core/src/dirstate/entry.rs @@ -91,11 +91,6 @@ impl TruncatedTimestamp { } } - pub fn to_integer_second(mut self) -> Self { - self.nanoseconds = 0; - self - } - /// The lower 31 bits of the number of seconds since the epoch. pub fn truncated_seconds(&self) -> u32 { self.truncated_seconds diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs b/rust/hg-core/src/dirstate_tree/on_disk.rs --- a/rust/hg-core/src/dirstate_tree/on_disk.rs +++ b/rust/hg-core/src/dirstate_tree/on_disk.rs @@ -376,15 +376,7 @@ impl Node { // MTIME_SECOND_AMBIGUOUS requires. So we ignore the mtime && !self.flags().contains(Flags::MTIME_SECOND_AMBIGUOUS) { - // TODO: replace this by `self.mtime.try_into()?` to use - // sub-second precision from the file. - // We don’t do this yet because other parts of the code - // always set it to zero. - let mtime = TruncatedTimestamp::from_already_truncated( - self.mtime.truncated_seconds.get(), - 0, - )?; - Some(mtime) + Some(self.mtime.try_into()?) } else { None }; diff --git a/rust/hg-core/src/dirstate_tree/status.rs b/rust/hg-core/src/dirstate_tree/status.rs --- a/rust/hg-core/src/dirstate_tree/status.rs +++ b/rust/hg-core/src/dirstate_tree/status.rs @@ -531,9 +531,7 @@ impl<'a, 'tree, 'on_disk> StatusCommon<' let mtime_looks_clean; if let Some(dirstate_mtime) = entry.truncated_mtime() { let fs_mtime = TruncatedTimestamp::for_mtime_of(fs_metadata) - .expect("OS/libc does not support mtime?") - // For now don’t use sub-second precision for file mtimes - .to_integer_second(); + .expect("OS/libc does not support mtime?"); mtime_looks_clean = fs_mtime.likely_equal(dirstate_mtime) && !fs_mtime.likely_equal(self.options.last_normal_time) } else {