Mercurial > hg
changeset 26493:13272104bb07
util: use tuple accessor to get accurate st_mtime value (issue4836)
Because st.st_mtime is computed as 'sec + 1e-9 * nsec' and double is too narrow
to represent nanoseconds, int(st.st_mtime) can be 'sec + 1'. Therefore, that
value could be different from the one got by osutils.listdir().
This patch fixes the problem by accessing to raw st_mtime by tuple index.
It catches TypeError to fall back to st.st_mtime because our osutil.stat does
not support tuple index. In dirstate.normal(), 'st' is always a Python stat,
but in dirstate.status(), it can be either a Python stat or an osutil.stat.
Thanks to vgatien-baron@janestreet.com for finding the root cause of this
subtle problem.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 04 Oct 2015 22:35:36 +0900 |
parents | 3a0bb61371c5 |
children | 832f40d2af53 |
files | mercurial/util.py |
diffstat | 1 files changed, 13 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/util.py Sun Oct 04 22:25:29 2015 +0900 +++ b/mercurial/util.py Sun Oct 04 22:35:36 2015 +0900 @@ -19,6 +19,7 @@ import errno, shutil, sys, tempfile, traceback import re as remod import os, time, datetime, calendar, textwrap, signal, collections +import stat import imp, socket, urllib import gc import bz2 @@ -953,7 +954,18 @@ return os.stat(fp.name) def statmtimesec(st): - return int(st.st_mtime) + """Get mtime as integer of seconds + + 'int(st.st_mtime)' cannot be used because st.st_mtime is computed as + 'sec + 1e-9 * nsec' and double-precision floating-point type is too narrow + to represent nanoseconds. If 'nsec' is close to 1 sec, 'int(st.st_mtime)' + can be 'sec + 1'. (issue4836) + """ + try: + return st[stat.ST_MTIME] + except TypeError: + # osutil.stat doesn't allow index access and its st_mtime is int + return st.st_mtime # File system features