diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -1823,29 +1823,12 @@ s = self[f].lstat() mode = s.st_mode size = s.st_size - file_mtime = timestamp.mtime_of(s) - cache_info = (mode, size, file_mtime) - - file_second = file_mtime[0] - boundary_second = mtime_boundary[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) - ): + file_mtime = timestamp.reliable_mtime_of(s, mtime_boundary) + if file_mtime is not None: + cache_info = (mode, size, file_mtime) + fixup.append((f, cache_info)) + else: clean.append(f) - else: - fixup.append((f, cache_info)) except (IOError, OSError): # A file become inaccessible in between? Mark it as deleted, # matching dirstate behavior (issue5584). diff --git a/mercurial/dirstateutils/timestamp.py b/mercurial/dirstateutils/timestamp.py --- a/mercurial/dirstateutils/timestamp.py +++ b/mercurial/dirstateutils/timestamp.py @@ -99,3 +99,28 @@ subsec_nanos = nanos % billion return timestamp((secs, subsec_nanos)) + + +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