Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/util.py @ 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 | 56b2bcea2529 |
comparison
equal
deleted
inserted
replaced
26492:3a0bb61371c5 | 26493:13272104bb07 |
---|---|
17 _ = i18n._ | 17 _ = i18n._ |
18 import error, osutil, encoding, parsers | 18 import error, osutil, encoding, parsers |
19 import errno, shutil, sys, tempfile, traceback | 19 import errno, shutil, sys, tempfile, traceback |
20 import re as remod | 20 import re as remod |
21 import os, time, datetime, calendar, textwrap, signal, collections | 21 import os, time, datetime, calendar, textwrap, signal, collections |
22 import stat | |
22 import imp, socket, urllib | 23 import imp, socket, urllib |
23 import gc | 24 import gc |
24 import bz2 | 25 import bz2 |
25 import zlib | 26 import zlib |
26 | 27 |
951 return os.fstat(fp.fileno()) | 952 return os.fstat(fp.fileno()) |
952 except AttributeError: | 953 except AttributeError: |
953 return os.stat(fp.name) | 954 return os.stat(fp.name) |
954 | 955 |
955 def statmtimesec(st): | 956 def statmtimesec(st): |
956 return int(st.st_mtime) | 957 """Get mtime as integer of seconds |
958 | |
959 'int(st.st_mtime)' cannot be used because st.st_mtime is computed as | |
960 'sec + 1e-9 * nsec' and double-precision floating-point type is too narrow | |
961 to represent nanoseconds. If 'nsec' is close to 1 sec, 'int(st.st_mtime)' | |
962 can be 'sec + 1'. (issue4836) | |
963 """ | |
964 try: | |
965 return st[stat.ST_MTIME] | |
966 except TypeError: | |
967 # osutil.stat doesn't allow index access and its st_mtime is int | |
968 return st.st_mtime | |
957 | 969 |
958 # File system features | 970 # File system features |
959 | 971 |
960 def checkcase(path): | 972 def checkcase(path): |
961 """ | 973 """ |