author | Pierre-Yves David <pierre-yves.david@octobus.net> |
Tue, 11 Mar 2025 02:29:42 +0100 | |
branch | stable |
changeset 53042 | cdd7bf612c7b |
parent 52643 | 5cc8deb96b48 |
permissions | -rw-r--r-- |
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 |
|
51859
f4733654f144
typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents:
48875
diff
changeset
|
6 |
from __future__ import annotations |
48260
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 |
52052
7ea1cb46b590
timestamp: add type information to the module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51859
diff
changeset
|
11 |
import time |
7ea1cb46b590
timestamp: add type information to the module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51859
diff
changeset
|
12 |
from typing import Optional, Tuple |
48260
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
13 |
|
48397
8d585aa9becf
dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48395
diff
changeset
|
14 |
from .. import error |
8d585aa9becf
dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48395
diff
changeset
|
15 |
|
48260
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 |
rangemask = 0x7FFFFFFF |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
18 |
|
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
19 |
|
48262
68bb472aee9c
dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
48260
diff
changeset
|
20 |
@functools.total_ordering |
48260
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
21 |
class timestamp(tuple): |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
22 |
""" |
48262
68bb472aee9c
dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
48260
diff
changeset
|
23 |
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
|
24 |
modulo 2**31 seconds. |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
25 |
|
48442
c8ca21962ff4
dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents:
48422
diff
changeset
|
26 |
A 3-tuple containing: |
48260
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
27 |
|
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
28 |
`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
|
29 |
truncated to its lower 31 bits |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
30 |
|
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
31 |
`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
|
32 |
When this is zero, the sub-second precision is considered unknown. |
48442
c8ca21962ff4
dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents:
48422
diff
changeset
|
33 |
|
c8ca21962ff4
dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents:
48422
diff
changeset
|
34 |
`second_ambiguous`: whether this timestamp is still "reliable" |
c8ca21962ff4
dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents:
48422
diff
changeset
|
35 |
(see `reliable_mtime_of`) if we drop its sub-second component. |
48260
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
36 |
""" |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
37 |
|
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
38 |
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
|
39 |
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
|
40 |
value = (truncated_seconds & rangemask, subsec_nanos, second_ambiguous) |
52643
5cc8deb96b48
pyupgrade: modernize calls to superclass methods
Matt Harbison <matt_harbison@yahoo.com>
parents:
52055
diff
changeset
|
41 |
return super().__new__(cls, value) |
48260
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
42 |
|
48262
68bb472aee9c
dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
48260
diff
changeset
|
43 |
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
|
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' |
48262
68bb472aee9c
dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
48260
diff
changeset
|
46 |
) |
68bb472aee9c
dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
48260
diff
changeset
|
47 |
|
68bb472aee9c
dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
48260
diff
changeset
|
48 |
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
|
49 |
raise error.ProgrammingError( |
8d585aa9becf
dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48395
diff
changeset
|
50 |
'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
|
51 |
) |
48262
68bb472aee9c
dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
48260
diff
changeset
|
52 |
|
48260
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
53 |
|
52052
7ea1cb46b590
timestamp: add type information to the module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51859
diff
changeset
|
54 |
def get_fs_now(vfs) -> Optional[timestamp]: |
48379
08b060abd658
dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48263
diff
changeset
|
55 |
"""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
|
56 |
|
08b060abd658
dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48263
diff
changeset
|
57 |
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
|
58 |
""" |
08b060abd658
dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48263
diff
changeset
|
59 |
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
|
60 |
try: |
08b060abd658
dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48263
diff
changeset
|
61 |
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
|
62 |
finally: |
08b060abd658
dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48263
diff
changeset
|
63 |
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
|
64 |
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
|
65 |
|
08b060abd658
dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48263
diff
changeset
|
66 |
|
52052
7ea1cb46b590
timestamp: add type information to the module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51859
diff
changeset
|
67 |
def zero() -> timestamp: |
48260
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 |
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
|
70 |
""" |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
71 |
return tuple.__new__(timestamp, (0, 0)) |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
72 |
|
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
73 |
|
52052
7ea1cb46b590
timestamp: add type information to the module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51859
diff
changeset
|
74 |
def mtime_of(stat_result: os.stat_result) -> timestamp: |
48260
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
75 |
""" |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
76 |
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
|
77 |
for its modification time. |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
78 |
""" |
48263
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
79 |
try: |
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
80 |
# 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
|
81 |
# see `mercurial/cext/osutil.c`. |
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
82 |
# |
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
83 |
# 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
|
84 |
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
|
85 |
except AttributeError: |
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
86 |
# 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
|
87 |
# "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
|
88 |
# 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
|
89 |
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
|
90 |
|
48263
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
91 |
subsec_nanos = 0 |
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
92 |
else: |
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
93 |
billion = int(1e9) |
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
94 |
secs = nanos // billion |
83d0bd45b662
dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents:
48262
diff
changeset
|
95 |
subsec_nanos = nanos % billion |
48260
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
96 |
|
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
|
97 |
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
|
98 |
|
9ae0353c9f5d
status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48379
diff
changeset
|
99 |
|
52052
7ea1cb46b590
timestamp: add type information to the module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51859
diff
changeset
|
100 |
def reliable_mtime_of( |
7ea1cb46b590
timestamp: add type information to the module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51859
diff
changeset
|
101 |
stat_result: os.stat_result, present_mtime: timestamp |
7ea1cb46b590
timestamp: add type information to the module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51859
diff
changeset
|
102 |
) -> Optional[timestamp]: |
52053
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
103 |
"""Wrapper for `make_mtime_reliable` for stat objects""" |
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
104 |
file_mtime = mtime_of(stat_result) |
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
105 |
return make_mtime_reliable(file_mtime, present_mtime) |
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
106 |
|
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
107 |
|
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
108 |
def make_mtime_reliable( |
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
109 |
file_timestamp: timestamp, present_mtime: timestamp |
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
110 |
) -> Optional[timestamp]: |
48442
c8ca21962ff4
dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents:
48422
diff
changeset
|
111 |
"""Same as `mtime_of`, but return `None` or a `Timestamp` with |
c8ca21962ff4
dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents:
48422
diff
changeset
|
112 |
`second_ambiguous` set if the date might be ambiguous. |
48395
9ae0353c9f5d
status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48379
diff
changeset
|
113 |
|
9ae0353c9f5d
status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48379
diff
changeset
|
114 |
A modification time is reliable if it is older than "present_time" (or |
48422
000130cfafb6
rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents:
48403
diff
changeset
|
115 |
sufficiently in the future). |
48395
9ae0353c9f5d
status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48379
diff
changeset
|
116 |
|
9ae0353c9f5d
status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48379
diff
changeset
|
117 |
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
|
118 |
""" |
52053
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
119 |
file_second = file_timestamp[0] |
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
120 |
file_ns = file_timestamp[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
|
121 |
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
|
122 |
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
|
123 |
# 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
|
124 |
# 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
|
125 |
# 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
|
126 |
# information. |
9ae0353c9f5d
status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48379
diff
changeset
|
127 |
# |
48403
ca42667c8d26
status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48398
diff
changeset
|
128 |
# 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
|
129 |
# 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
|
130 |
# 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
|
131 |
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
|
132 |
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
|
133 |
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
|
134 |
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
|
135 |
return None |
ca42667c8d26
status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
48398
diff
changeset
|
136 |
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
|
137 |
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
|
138 |
else: |
52053
572d80e51094
timestamp: make the reliable comparison more usable from outside
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52052
diff
changeset
|
139 |
return file_timestamp |
52055
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
140 |
|
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
141 |
|
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
142 |
FS_TICK_WAIT_TIMEOUT = 0.1 # 100 milliseconds |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
143 |
|
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
144 |
|
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
145 |
def wait_until_fs_tick(vfs) -> Optional[Tuple[timestamp, bool]]: |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
146 |
"""Wait until the next update from the filesystem time by writing in a loop |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
147 |
a new temporary file inside the working directory and checking if its time |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
148 |
differs from the first one observed. |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
149 |
|
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
150 |
Returns `None` if we are unable to get the filesystem time, |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
151 |
`(timestamp, True)` if we've timed out waiting for the filesystem clock |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
152 |
to tick, and `(timestamp, False)` if we've waited successfully. |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
153 |
|
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
154 |
On Linux, your average tick is going to be a "jiffy", or 1/HZ. |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
155 |
HZ is your kernel's tick rate (if it has one configured) and the value |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
156 |
is the one returned by `grep 'CONFIG_HZ=' /boot/config-$(uname -r)`, |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
157 |
again assuming a normal setup. |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
158 |
|
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
159 |
In my case (Alphare) at the time of writing, I get `CONFIG_HZ=250`, |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
160 |
which equates to 4ms. |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
161 |
This might change with a series that could make it to Linux 6.12: |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
162 |
https://lore.kernel.org/all/20241002-mgtime-v10-8-d1c4717f5284@kernel.org |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
163 |
""" |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
164 |
start = time.monotonic() |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
165 |
|
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
166 |
try: |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
167 |
old_fs_time = get_fs_now(vfs) |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
168 |
new_fs_time = get_fs_now(vfs) |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
169 |
|
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
170 |
while ( |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
171 |
new_fs_time[0] == old_fs_time[0] |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
172 |
and new_fs_time[1] == old_fs_time[1] |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
173 |
): |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
174 |
if time.monotonic() - start > FS_TICK_WAIT_TIMEOUT: |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
175 |
return (old_fs_time, True) |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
176 |
new_fs_time = get_fs_now(vfs) |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
177 |
except OSError: |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
178 |
return None |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
179 |
else: |
b332ae615714
merge: improve working-copy mtime race handling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52053
diff
changeset
|
180 |
return (new_fs_time, False) |