Mercurial > hg
changeset 48263:83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Instead of zero, set the nanoseconds field to its correct value whenever
possible and preserve it across serialization+parsing.
Differential Revision: https://phab.mercurial-scm.org/D11702
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Wed, 13 Oct 2021 15:58:14 +0200 |
parents | 68bb472aee9c |
children | bb240915f69f |
files | mercurial/dirstateutils/timestamp.py mercurial/dirstateutils/v2.py rust/hg-core/src/dirstate/entry.rs rust/hg-core/src/dirstate_tree/on_disk.rs rust/hg-core/src/dirstate_tree/status.rs |
diffstat | 5 files changed, 19 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/dirstateutils/timestamp.py Thu Oct 14 13:54:39 2021 +0200 +++ b/mercurial/dirstateutils/timestamp.py Wed Oct 13 15:58:14 2021 +0200 @@ -66,12 +66,22 @@ 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))
--- a/mercurial/dirstateutils/v2.py Thu Oct 14 13:54:39 2021 +0200 +++ b/mercurial/dirstateutils/v2.py Wed Oct 13 15:58:14 2021 +0200 @@ -101,15 +101,12 @@ 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
--- a/rust/hg-core/src/dirstate/entry.rs Thu Oct 14 13:54:39 2021 +0200 +++ b/rust/hg-core/src/dirstate/entry.rs Wed Oct 13 15:58:14 2021 +0200 @@ -91,11 +91,6 @@ } } - 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
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs Thu Oct 14 13:54:39 2021 +0200 +++ b/rust/hg-core/src/dirstate_tree/on_disk.rs Wed Oct 13 15:58:14 2021 +0200 @@ -376,15 +376,7 @@ // 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 };
--- a/rust/hg-core/src/dirstate_tree/status.rs Thu Oct 14 13:54:39 2021 +0200 +++ b/rust/hg-core/src/dirstate_tree/status.rs Wed Oct 13 15:58:14 2021 +0200 @@ -531,9 +531,7 @@ 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 {