Switch to st_mtime_ns when available

This commit is contained in:
Jonas Borgström 2013-06-15 20:56:27 +02:00
parent 1fdc5eabc6
commit ad08664b65
5 changed files with 27 additions and 16 deletions

View file

@ -12,7 +12,7 @@ import xattr
from .chunker import chunkify
from .helpers import uid2user, user2uid, gid2group, group2gid, \
Statistics, decode_dict
Statistics, decode_dict, st_mtime_ns
ITEMS_BUFFER = 1024 * 1024
CHUNK_MIN = 1024
@ -20,6 +20,7 @@ WINDOW_SIZE = 0xfff
CHUNK_MASK = 0xffff
utime_supports_fd = os.utime in getattr(os, 'supports_fd', {})
has_mtime_ns = sys.version >= '3.3'
has_lchmod = hasattr(os, 'lchmod')
@ -304,11 +305,11 @@ class Archive(object):
elif has_lchmod: # Not available on Linux
os.lchmod(path, item[b'mode'])
if fd and utime_supports_fd: # Python >= 3.3
os.utime(fd, (item[b'mtime'], item[b'mtime']))
os.utime(fd, None, ns=(item[b'mtime'], item[b'mtime']))
elif utime_supports_fd: # Python >= 3.3
os.utime(path, (item[b'mtime'], item[b'mtime']), follow_symlinks=False)
os.utime(path, None, ns=(item[b'mtime'], item[b'mtime']), follow_symlinks=False)
elif not symlink:
os.utime(path, (item[b'mtime'], item[b'mtime']))
os.utime(path, (item[b'mtime'] / 10**9, item[b'mtime'] / 10**9))
def verify_file(self, item, start, result, peek=None):
if not item[b'chunks']:
@ -347,7 +348,7 @@ class Archive(object):
b'mode': st.st_mode,
b'uid': st.st_uid, b'user': uid2user(st.st_uid),
b'gid': st.st_gid, b'group': gid2group(st.st_gid),
b'mtime': st.st_mtime,
b'mtime': st_mtime_ns(st),
}
if self.numeric_owner:
item[b'user'] = item[b'group'] = None

View file

@ -195,7 +195,7 @@ class Archiver(object):
size = sum(size for _, size, _ in item[b'chunks'])
except KeyError:
pass
mtime = format_time(datetime.fromtimestamp(item[b'mtime']))
mtime = format_time(datetime.fromtimestamp(item[b'mtime'] / 10**9))
if b'source' in item:
if type == 'l':
extra = ' -> %s' % item[b'source']

View file

@ -6,7 +6,7 @@ import os
from binascii import hexlify, unhexlify
import shutil
from .helpers import get_cache_dir, decode_dict
from .helpers import get_cache_dir, decode_dict, st_mtime_ns
from .hashindex import ChunkIndex
@ -190,7 +190,7 @@ class Cache(object):
if self.files is None:
self._read_files()
entry = self.files.get(path_hash)
if (entry and entry[3] == st.st_mtime
if (entry and entry[3] == st_mtime_ns(st)
and entry[2] == st.st_size and entry[1] == st.st_ino):
# reset entry age
self.files[path_hash][0] = 0
@ -200,6 +200,6 @@ class Cache(object):
def memorize_file(self, path_hash, st, ids):
# Entry: Age, inode, size, mtime, chunk ids
self.files[path_hash] = 0, st.st_ino, st.st_size, st.st_mtime, ids
self._newest_mtime = max(self._newest_mtime, st.st_mtime)
mtime_ns = st_mtime_ns(st)
self.files[path_hash] = 0, st.st_ino, st.st_size, mtime_ns, ids
self._newest_mtime = max(self._newest_mtime, mtime_ns)

View file

@ -375,4 +375,12 @@ def decode_dict(d, keys, encoding='utf-8', errors='surrogateescape'):
def remove_surrogates(s, errors='replace'):
return s.encode('utf-8', errors).decode('utf-8')
return s.encode('utf-8', errors).decode('utf-8')
if sys.version < '3.3':
def st_mtime_ns(st):
return int(st.st_mtime * 10**9)
else:
def st_mtime_ns(st):
return st.st_mtime_ns

View file

@ -16,6 +16,7 @@ from .key import suite as KeySuite
from .store import Store, suite as StoreSuite
from .remote import Store, suite as RemoteStoreSuite
has_mtime_ns = sys.version >= '3.3'
utime_supports_fd = os.utime in getattr(os, 'supports_fd', {})
@ -89,12 +90,13 @@ class Test(unittest.TestCase):
s2 = os.lstat(path2)
attrs = ['st_mode', 'st_uid', 'st_gid', 'st_rdev']
if not os.path.islink(path1) or utime_supports_fd:
attrs.append('st_mtime')
attrs.append('st_mtime_ns' if has_mtime_ns else 'st_mtime')
d1 = [filename] + [getattr(s1, a) for a in attrs]
d2 = [filename] + [getattr(s2, a) for a in attrs]
if(len(d1) == 6):
d1[-1] = int(d1[-1])
d2[-1] = int(d2[-1])
# 'st_mtime precision is limited'
if attrs[-1] == 'st_mtime':
d1[-1] = round(d1[-1], 4)
d2[-1] = round(d2[-1], 4)
d1.append(self.get_xattrs(path1))
d2.append(self.get_xattrs(path2))
self.assertEqual(d1, d2)