util: remove os.stat_float_times(False)

Summary:
This is not available on Python3, instead stat.ST_MTIME and friends should be
used to get an integer time. This is achieved by wrapping the output of the
stat function and overriding the st_[acm]time properties.

Reviewed By: quark-zju

Differential Revision: D18819679

fbshipit-source-id: 2911f3d47506456e927872d57f69253d903618e2
This commit is contained in:
Xavier Deguillard 2019-12-09 13:09:25 -08:00 committed by Facebook Github Bot
parent 6da344eee2
commit 24d99a9178
16 changed files with 87 additions and 52 deletions

View File

@ -139,7 +139,7 @@ def snapshot(ui, repo, files, node, tmproot):
if node is None:
dest = os.path.join(base, wfn)
fnsandstat.append((dest, repo.wjoin(fn), os.lstat(dest)))
fnsandstat.append((dest, repo.wjoin(fn), util.lstat(dest)))
return dirname, fnsandstat
@ -293,7 +293,7 @@ def dodiff(ui, repo, cmdline, pats, opts):
ui.system(cmdline, cwd=tmproot, blockedtag="extdiff")
for copy_fn, working_fn, st in fnsandstat:
cpstat = os.lstat(copy_fn)
cpstat = util.lstat(copy_fn)
# Some tools copy the file and attributes, so mtime may not detect
# all changes. A size check will detect more cases, but not all.
# The only certain way to detect every case is to diff all files,

View File

@ -131,7 +131,7 @@ class basepackstore(object):
# (the index file and the pack file), we can yield once we see
# it twice.
if ext == self.INDEXSUFFIX or ext == self.PACKSUFFIX:
st = os.lstat(filename)
st = util.lstat(filename)
if statmod.S_ISDIR(st.st_mode):
continue

View File

@ -209,7 +209,7 @@ def _cleanupoldpacks(ui, packpath, limit):
with progress.spinner(ui, _("cleaning old packs")):
def _mtime(f):
stat = os.lstat(f)
stat = util.lstat(f)
return stat.st_mtime
def _listpackfiles(path):
@ -234,7 +234,7 @@ def _cleanupoldpacks(ui, packpath, limit):
while cachesize > limit:
f = files.pop()
stat = os.lstat(f)
stat = util.lstat(f)
# Dont't remove files that are newer than 10 minutes. This will
# avoid a race condition where mercurial downloads files from the

View File

@ -369,7 +369,7 @@ class chgunixservicehandler(object):
# check later
tempaddress = _tempaddress(self._realaddress)
util.bindunixsocket(sock, tempaddress)
self._socketstat = os.stat(tempaddress)
self._socketstat = util.stat(tempaddress)
sock.listen(socket.SOMAXCONN)
# rename will replace the old socket file if exists atomically. the
# old server will detect ownership change and exit.
@ -384,7 +384,7 @@ class chgunixservicehandler(object):
def _issocketowner(self):
try:
stat = os.stat(self._realaddress)
stat = util.stat(self._realaddress)
return (
stat.st_ino == self._socketstat.st_ino
and stat.st_mtime == self._socketstat.st_mtime

View File

@ -71,7 +71,7 @@ def _getfsnow(vfs):
"""Get "now" timestamp on filesystem"""
tmpfd, tmpname = vfs.mkstemp()
try:
return os.fstat(tmpfd).st_mtime
return util.fstat(tmpfd).st_mtime
finally:
os.close(tmpfd)
vfs.unlink(tmpname)
@ -493,7 +493,7 @@ class dirstate(object):
def normal(self, f):
"""Mark a file normal and clean."""
s = os.lstat(self._join(f))
s = util.lstat(self._join(f))
mtime = s.st_mtime
self._addpath(f, "n", s.st_mode, s.st_size & _rangemask, mtime & _rangemask)
if not self._istreestate:

View File

@ -29,17 +29,6 @@ parsers = policy.importmod("parsers")
propertycache = util.propertycache
class statobject(object):
""" this is a stat-like object to represent information from eden."""
__slots__ = ("st_mode", "st_size", "st_mtime")
def __init__(self, mode=None, size=None, mtime=None):
self.st_mode = mode
self.st_size = size
self.st_mtime = mtime
class eden_dirstate(dirstate.dirstate):
def __init__(self, repo, ui, root):
self.eden_client = thrift.EdenThriftClient(repo)

View File

@ -209,7 +209,7 @@ class physicalfilesystem(object):
join = self.opener.join
walker = workingcopy.walker(join(""), match)
for fn in walker:
st = os.lstat(join(fn))
st = util.lstat(join(fn))
yield fn, st
@util.timefunction("fswalk", 0, "ui")

View File

@ -1175,9 +1175,9 @@ class cachedlocalrepo(object):
prefix = getattr(self._repo, attr)
p = os.path.join(prefix, fname)
try:
st = os.stat(p)
st = util.stat(p)
except OSError:
st = os.stat(prefix)
st = util.stat(prefix)
state.append((st.st_mtime, st.st_size))
maxmtime = max(maxmtime, st.st_mtime)

View File

@ -135,9 +135,9 @@ def get_stat(spath, fn):
"""stat fn if it exists, spath otherwise"""
cl_path = os.path.join(spath, fn)
if os.path.exists(cl_path):
return os.stat(cl_path)
return util.stat(cl_path)
else:
return os.stat(spath)
return util.stat(spath)
def get_mtime(spath):

View File

@ -988,11 +988,13 @@ def hidewindow():
class cachestat(object):
def __init__(self, path):
from . import util
if path is None:
self.stat = None
else:
try:
self.stat = os.stat(path)
self.stat = util.stat(path)
except OSError as ex:
if ex.errno == errno.ENOENT:
self.stat = None

View File

@ -41,6 +41,8 @@ def _mode_to_kind(mode):
def listdir(path, stat=False, skip=None):
from .. import util
"""listdir(path, stat=False) -> list_of_tuples
Return a sorted list containing information about the entries
@ -61,7 +63,7 @@ def listdir(path, stat=False, skip=None):
names = os.listdir(path)
names.sort()
for fn in names:
st = os.lstat(prefix + fn)
st = util.lstat(prefix + fn)
if fn == skip and statmod.S_ISDIR(st.st_mode):
return []
if stat:

View File

@ -407,7 +407,7 @@ def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
def adddir(dirlst, dirname):
match = False
dirstat = os.stat(dirname)
dirstat = util.stat(dirname)
for lstdirstat in dirlst:
if samestat(dirstat, lstdirstat):
match = True

View File

@ -41,7 +41,7 @@ import re as remod
import shutil
import signal
import socket
import stat
import stat as statmod
import string
import subprocess
import sys
@ -187,12 +187,6 @@ except AttributeError:
_notset = object()
# disable Python's problematic floating point timestamps (issue4836)
# (Python hypocritically says you shouldn't change this behavior in
# libraries, and sure enough Mercurial is not a library.)
# pyre-fixme[16]: Module `os` has no attribute `stat_float_times`.
os.stat_float_times(False)
def safehasattr(thing, attr):
# Use instead of the builtin ``hasattr``. (See
@ -1561,14 +1555,6 @@ def _reloadenv():
_reloadenv()
def fstat(fp):
"""stat file object that may not have fileno method."""
try:
return os.fstat(fp.fileno())
except AttributeError:
return os.stat(fp.name)
# File system features
@ -1849,17 +1835,17 @@ class filestat(object):
@classmethod
def frompath(cls, path):
try:
stat = os.stat(path)
st = stat(path)
except OSError as err:
if err.errno != errno.ENOENT:
raise
stat = None
return cls(stat)
st = None
return cls(st)
@classmethod
def fromfp(cls, fp):
stat = os.fstat(fp.fileno())
return cls(stat)
st = fstat(fp.fileno())
return cls(st)
__hash__ = object.__hash__
@ -2858,7 +2844,7 @@ if pyplatform.python_implementation() == "CPython" and sys.version_info < (3, 0)
def iterfile(fp):
fastpath = True
if type(fp) is file: # noqa
fastpath = stat.S_ISREG(os.fstat(fp.fileno()).st_mode)
fastpath = statmod.S_ISREG(os.fstat(fp.fileno()).st_mode)
if fastpath:
return fp
else:
@ -4661,3 +4647,56 @@ def smarttraceback(frame=None):
item += " # %s\n" % localarg
result += item
return result
class wrapped_stat_result(object):
"""Mercurial assumes that st_[amc]time is an integer, but both Python2 and
Python3 are returning a float value. This class overrides these attributes
with their integer counterpart.
"""
def __init__(self, stat):
self._stat = stat
@property
def st_mtime(self):
return self._stat[statmod.ST_MTIME]
@property
def st_ctime(self):
return self._stat[statmod.ST_CTIME]
@property
def st_atime(self):
return self._stat[statmod.ST_ATIME]
def __getattr__(self, name):
return getattr(self._stat, name)
def _fixup_time(st):
st.st_mtime = st[statmod.ST_MTIME]
st.st_ctime = st[statmod.ST_CTIME]
def stat(path):
res = os.stat(path)
return wrapped_stat_result(res)
def lstat(path):
res = os.lstat(path)
return wrapped_stat_result(res)
def fstat(fp):
"""stat file object that may not have fileno method."""
try:
res = os.fstat(fp)
except TypeError:
try:
res = os.fstat(fp.fileno())
except AttributeError:
res = os.stat(fp.name)
return wrapped_stat_result(res)

View File

@ -159,7 +159,7 @@ class abstractvfs(object):
return os.path.lexists(self.join(path))
def lstat(self, path=None):
return os.lstat(self.join(path))
return util.lstat(self.join(path))
def listdir(self, path=None):
return os.listdir(self.join(path))
@ -248,7 +248,7 @@ class abstractvfs(object):
return util.setflags(self.join(path), l, x)
def stat(self, path=None):
return os.stat(self.join(path))
return util.stat(self.join(path))
def unlink(self, path=None):
return util.unlink(self.join(path))

View File

@ -66,6 +66,9 @@ New errors are not allowed. Warnings are strongly discouraged.
Skipping tests/test-rustthreading.py it has no-che?k-code (glob)
edenscm/hgext/extlib/phabricator/graphql.py:*: use foobar, not foo_bar naming --> ca_bundle = repo.ui.configpath("web", "cacerts") (glob)
edenscm/hgext/extlib/phabricator/graphql.py:*: use foobar, not foo_bar naming --> def scmquery_log( (glob)
edenscm/mercurial/util.py:4662: use foobar, not foo_bar naming --> def st_mtime(self):
edenscm/mercurial/util.py:4666: use foobar, not foo_bar naming --> def st_ctime(self):
edenscm/mercurial/util.py:4670: use foobar, not foo_bar naming --> def st_atime(self):
tests/run-tests.py:*: don't use camelcase in identifiers --> self.testsSkipped = 0 (glob)
@commands in debugcommands.py should be in alphabetical order.

View File

@ -180,7 +180,7 @@ def antiambiguity():
fp.write("FOO")
fp.close()
oldstat = os.stat(filename)
oldstat = util.stat(filename)
if oldstat.st_ctime != oldstat.st_mtime:
# subsequent changing never causes ambiguity
continue