##// END OF EJS Templates
dirstate-item: make sure we load `mtime-second-ambiguous` from disk...
dirstate-item: make sure we load `mtime-second-ambiguous` from disk Now that we support the associated logic, we can safely load it from it. It is no longer necessary to ignore the stored mtime when the flag is encountered. Differential Revision: https://phab.mercurial-scm.org/D11846

File last commit:

r49227:111098af default
r49231:be231716 default
Show More
timestamp.py
117 lines | 3.4 KiB | text/x-python | PythonLexer
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 # Copyright Mercurial Contributors
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
Simon Sapin
dirstate: ignore sub-second component when either is zero in mtime...
r49081 import functools
dirstate: move "get fs now" in the timestamp utility module...
r49202 import os
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 import stat
dirstate: drop comparison primitive on the timestamp class...
r49226 from .. import error
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079
rangemask = 0x7FFFFFFF
Simon Sapin
dirstate: ignore sub-second component when either is zero in mtime...
r49081 @functools.total_ordering
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 class timestamp(tuple):
"""
Simon Sapin
dirstate: ignore sub-second component when either is zero in mtime...
r49081 A Unix timestamp with optional nanoseconds precision,
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 modulo 2**31 seconds.
A 2-tuple containing:
`truncated_seconds`: seconds since the Unix epoch,
truncated to its lower 31 bits
`subsecond_nanoseconds`: number of nanoseconds since `truncated_seconds`.
Simon Sapin
dirstate: ignore sub-second component when either is zero in mtime...
r49081 When this is zero, the sub-second precision is considered unknown.
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 """
def __new__(cls, value):
dirstate-item: add a "second_ambiguous` flag in the mtime tuple...
r49227 truncated_seconds, subsec_nanos, second_ambiguous = value
value = (truncated_seconds & rangemask, subsec_nanos, second_ambiguous)
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 return super(timestamp, cls).__new__(cls, value)
Simon Sapin
dirstate: ignore sub-second component when either is zero in mtime...
r49081 def __eq__(self, other):
dirstate: drop comparison primitive on the timestamp class...
r49226 raise error.ProgrammingError(
'timestamp should never be compared directly'
Simon Sapin
dirstate: ignore sub-second component when either is zero in mtime...
r49081 )
def __gt__(self, other):
dirstate: drop comparison primitive on the timestamp class...
r49226 raise error.ProgrammingError(
'timestamp should never be compared directly'
)
Simon Sapin
dirstate: ignore sub-second component when either is zero in mtime...
r49081
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079
dirstate: move "get fs now" in the timestamp utility module...
r49202 def get_fs_now(vfs):
"""return a timestamp for "now" in the current vfs
This will raise an exception if no temporary files could be created.
"""
tmpfd, tmpname = vfs.mkstemp()
try:
return mtime_of(os.fstat(tmpfd))
finally:
os.close(tmpfd)
vfs.unlink(tmpname)
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 def zero():
"""
Returns the `timestamp` at the Unix epoch.
"""
return tuple.__new__(timestamp, (0, 0))
def mtime_of(stat_result):
"""
Takes an `os.stat_result`-like object and returns a `timestamp` object
for its modification time.
"""
Simon Sapin
dirstate-v2: actually use sub-second mtime precision...
r49082 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]
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079
Simon Sapin
dirstate-v2: actually use sub-second mtime precision...
r49082 subsec_nanos = 0
else:
billion = int(1e9)
secs = nanos // billion
subsec_nanos = nanos % billion
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079
dirstate-item: add a "second_ambiguous` flag in the mtime tuple...
r49227 return timestamp((secs, subsec_nanos, False))
status: move the boundary comparison logic within the timestamp module...
r49224
def reliable_mtime_of(stat_result, present_mtime):
"""same as `mtime_of`, but return None if the date might be ambiguous
A modification time is reliable if it is older than "present_time" (or
sufficiently in the futur).
Otherwise a concurrent modification might happens with the same mtime.
"""
file_mtime = mtime_of(stat_result)
file_second = file_mtime[0]
boundary_second = present_mtime[0]
# If the mtime of the ambiguous file is younger (or equal) to the starting
# point of the `status` walk, we cannot garantee that another, racy, write
# will not happen right after with the same mtime and we cannot cache the
# information.
#
# However is the mtime is far away in the future, this is likely some
# mismatch between the current clock and previous file system operation. So
# mtime more than one days in the future are considered fine.
if boundary_second <= file_second < (3600 * 24 + boundary_second):
return None
else:
return file_mtime