Ver código fonte

Switch to st_mtime_ns when available

Jonas Borgström 12 anos atrás
pai
commit
ad08664b65
5 arquivos alterados com 27 adições e 16 exclusões
  1. 6 5
      darc/archive.py
  2. 1 1
      darc/archiver.py
  3. 5 5
      darc/cache.py
  4. 9 1
      darc/helpers.py
  5. 6 4
      darc/test.py

+ 6 - 5
darc/archive.py

@@ -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

+ 1 - 1
darc/archiver.py

@@ -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']

+ 5 - 5
darc/cache.py

@@ -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)

+ 9 - 1
darc/helpers.py

@@ -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

+ 6 - 4
darc/test.py

@@ -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)