瀏覽代碼

Switch to st_mtime_ns when available

Jonas Borgström 12 年之前
父節點
當前提交
ad08664b65
共有 5 個文件被更改,包括 27 次插入16 次删除
  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 .chunker import chunkify
 from .helpers import uid2user, user2uid, gid2group, group2gid, \
 from .helpers import uid2user, user2uid, gid2group, group2gid, \
-    Statistics, decode_dict
+    Statistics, decode_dict, st_mtime_ns
 
 
 ITEMS_BUFFER = 1024 * 1024
 ITEMS_BUFFER = 1024 * 1024
 CHUNK_MIN = 1024
 CHUNK_MIN = 1024
@@ -20,6 +20,7 @@ WINDOW_SIZE = 0xfff
 CHUNK_MASK = 0xffff
 CHUNK_MASK = 0xffff
 
 
 utime_supports_fd = os.utime in getattr(os, 'supports_fd', {})
 utime_supports_fd = os.utime in getattr(os, 'supports_fd', {})
+has_mtime_ns = sys.version >= '3.3'
 has_lchmod = hasattr(os, 'lchmod')
 has_lchmod = hasattr(os, 'lchmod')
 
 
 
 
@@ -304,11 +305,11 @@ class Archive(object):
         elif has_lchmod:  # Not available on Linux
         elif has_lchmod:  # Not available on Linux
             os.lchmod(path, item[b'mode'])
             os.lchmod(path, item[b'mode'])
         if fd and utime_supports_fd:  # Python >= 3.3
         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
         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:
         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):
     def verify_file(self, item, start, result, peek=None):
         if not item[b'chunks']:
         if not item[b'chunks']:
@@ -347,7 +348,7 @@ class Archive(object):
             b'mode': st.st_mode,
             b'mode': st.st_mode,
             b'uid': st.st_uid, b'user': uid2user(st.st_uid),
             b'uid': st.st_uid, b'user': uid2user(st.st_uid),
             b'gid': st.st_gid, b'group': gid2group(st.st_gid),
             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:
         if self.numeric_owner:
             item[b'user'] = item[b'group'] = None
             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'])
                         size = sum(size for _, size, _ in item[b'chunks'])
                     except KeyError:
                     except KeyError:
                         pass
                         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 b'source' in item:
                     if type == 'l':
                     if type == 'l':
                         extra = ' -> %s' % item[b'source']
                         extra = ' -> %s' % item[b'source']

+ 5 - 5
darc/cache.py

@@ -6,7 +6,7 @@ import os
 from binascii import hexlify, unhexlify
 from binascii import hexlify, unhexlify
 import shutil
 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
 from .hashindex import ChunkIndex
 
 
 
 
@@ -190,7 +190,7 @@ class Cache(object):
         if self.files is None:
         if self.files is None:
             self._read_files()
             self._read_files()
         entry = self.files.get(path_hash)
         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):
             and entry[2] == st.st_size and entry[1] == st.st_ino):
             # reset entry age
             # reset entry age
             self.files[path_hash][0] = 0
             self.files[path_hash][0] = 0
@@ -200,6 +200,6 @@ class Cache(object):
 
 
     def memorize_file(self, path_hash, st, ids):
     def memorize_file(self, path_hash, st, ids):
         # Entry: Age, inode, size, mtime, chunk 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'):
 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 .store import Store, suite as StoreSuite
 from .remote import Store, suite as RemoteStoreSuite
 from .remote import Store, suite as RemoteStoreSuite
 
 
+has_mtime_ns = sys.version >= '3.3'
 utime_supports_fd = os.utime in getattr(os, 'supports_fd', {})
 utime_supports_fd = os.utime in getattr(os, 'supports_fd', {})
 
 
 
 
@@ -89,12 +90,13 @@ class Test(unittest.TestCase):
             s2 = os.lstat(path2)
             s2 = os.lstat(path2)
             attrs = ['st_mode', 'st_uid', 'st_gid', 'st_rdev']
             attrs = ['st_mode', 'st_uid', 'st_gid', 'st_rdev']
             if not os.path.islink(path1) or utime_supports_fd:
             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]
             d1 = [filename] + [getattr(s1, a) for a in attrs]
             d2 = [filename] + [getattr(s2, 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))
             d1.append(self.get_xattrs(path1))
             d2.append(self.get_xattrs(path2))
             d2.append(self.get_xattrs(path2))
             self.assertEqual(d1, d2)
             self.assertEqual(d1, d2)