annotate mercurial/dirstateutils/timestamp.py @ 48403:ca42667c8d26

status: keep second-ambiguous mtimes during fixup Now that we support the feature, we can keep "second ambiguous" mtime during the fixup phase. These are the mtime that would be ambiguous if we did not had sub-second pr?cions. See the v2 format documentation for details. Differential Revision: https://phab.mercurial-scm.org/D11847
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 24 Nov 2021 05:00:28 +0100
parents 111098af6356
children 000130cfafb6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
1 # Copyright Mercurial Contributors
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
2 #
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
3 # This software may be used and distributed according to the terms of the
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
4 # GNU General Public License version 2 or any later version.
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
5
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
6 from __future__ import absolute_import
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
7
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
8 import functools
48379
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
9 import os
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
10 import stat
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
11
48397
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
12 from .. import error
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
13
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
14
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
15 rangemask = 0x7FFFFFFF
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
16
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
17
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
18 @functools.total_ordering
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
19 class timestamp(tuple):
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
20 """
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
21 A Unix timestamp with optional nanoseconds precision,
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
22 modulo 2**31 seconds.
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
23
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
24 A 2-tuple containing:
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
25
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
26 `truncated_seconds`: seconds since the Unix epoch,
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
27 truncated to its lower 31 bits
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
28
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
29 `subsecond_nanoseconds`: number of nanoseconds since `truncated_seconds`.
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
30 When this is zero, the sub-second precision is considered unknown.
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
31 """
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
32
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
33 def __new__(cls, value):
48398
111098af6356 dirstate-item: add a "second_ambiguous` flag in the mtime tuple
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48397
diff changeset
34 truncated_seconds, subsec_nanos, second_ambiguous = value
111098af6356 dirstate-item: add a "second_ambiguous` flag in the mtime tuple
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48397
diff changeset
35 value = (truncated_seconds & rangemask, subsec_nanos, second_ambiguous)
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
36 return super(timestamp, cls).__new__(cls, value)
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
37
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
38 def __eq__(self, other):
48397
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
39 raise error.ProgrammingError(
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
40 'timestamp should never be compared directly'
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
41 )
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
42
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
43 def __gt__(self, other):
48397
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
44 raise error.ProgrammingError(
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
45 'timestamp should never be compared directly'
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
46 )
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
47
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
48
48379
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
49 def get_fs_now(vfs):
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
50 """return a timestamp for "now" in the current vfs
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
51
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
52 This will raise an exception if no temporary files could be created.
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
53 """
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
54 tmpfd, tmpname = vfs.mkstemp()
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
55 try:
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
56 return mtime_of(os.fstat(tmpfd))
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
57 finally:
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
58 os.close(tmpfd)
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
59 vfs.unlink(tmpname)
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
60
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
61
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
62 def zero():
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
63 """
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
64 Returns the `timestamp` at the Unix epoch.
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
65 """
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
66 return tuple.__new__(timestamp, (0, 0))
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
67
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
68
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
69 def mtime_of(stat_result):
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
70 """
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
71 Takes an `os.stat_result`-like object and returns a `timestamp` object
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
72 for its modification time.
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
73 """
48263
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
74 try:
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
75 # TODO: add this attribute to `osutil.stat` objects,
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
76 # see `mercurial/cext/osutil.c`.
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
77 #
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
78 # This attribute is also not available on Python 2.
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
79 nanos = stat_result.st_mtime_ns
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
80 except AttributeError:
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
81 # https://docs.python.org/2/library/os.html#os.stat_float_times
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
82 # "For compatibility with older Python versions,
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
83 # accessing stat_result as a tuple always returns integers."
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
84 secs = stat_result[stat.ST_MTIME]
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
85
48263
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
86 subsec_nanos = 0
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
87 else:
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
88 billion = int(1e9)
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
89 secs = nanos // billion
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
90 subsec_nanos = nanos % billion
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
91
48398
111098af6356 dirstate-item: add a "second_ambiguous` flag in the mtime tuple
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48397
diff changeset
92 return timestamp((secs, subsec_nanos, False))
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
93
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
94
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
95 def reliable_mtime_of(stat_result, present_mtime):
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
96 """same as `mtime_of`, but return None if the date might be ambiguous
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
97
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
98 A modification time is reliable if it is older than "present_time" (or
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
99 sufficiently in the futur).
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
100
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
101 Otherwise a concurrent modification might happens with the same mtime.
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
102 """
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
103 file_mtime = mtime_of(stat_result)
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
104 file_second = file_mtime[0]
48403
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
105 file_ns = file_mtime[1]
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
106 boundary_second = present_mtime[0]
48403
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
107 boundary_ns = present_mtime[1]
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
108 # If the mtime of the ambiguous file is younger (or equal) to the starting
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
109 # point of the `status` walk, we cannot garantee that another, racy, write
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
110 # will not happen right after with the same mtime and we cannot cache the
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
111 # information.
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
112 #
48403
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
113 # However if the mtime is far away in the future, this is likely some
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
114 # mismatch between the current clock and previous file system operation. So
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
115 # mtime more than one days in the future are considered fine.
48403
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
116 if boundary_second == file_second:
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
117 if file_ns and boundary_ns:
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
118 if file_ns < boundary_ns:
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
119 return timestamp((file_second, file_ns, True))
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
120 return None
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
121 elif boundary_second < file_second < (3600 * 24 + boundary_second):
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
122 return None
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
123 else:
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
124 return file_mtime