Mercurial > public > mercurial-scm > hg
annotate mercurial/dirstateutils/timestamp.py @ 52055:b332ae615714
merge: improve working-copy mtime race handling
Explanations inline. This also makes use of `make_mtime_reliable`, which
unifies our mtime raciness logic from the status.
On top of this, this fixes the handling of the pure dirstate status to better
catch racy status, as we've been doing in Rust for a long time now.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Wed, 16 Oct 2024 19:14:30 +0200 |
parents | 572d80e51094 |
children | 5cc8deb96b48 |
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 |
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) |
48260
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
41 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
|
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) |