Browse Source

Use os.sync where possible.

Check st_size to prevent reading existing file unless it has the same
size as the old file in build_file_from_blob.
Jelmer Vernooij 8 years ago
parent
commit
5a446a7bc9
2 changed files with 22 additions and 22 deletions
  1. 14 12
      dulwich/index.py
  2. 8 10
      dulwich/tests/test_index.py

+ 14 - 12
dulwich/index.py

@@ -422,26 +422,28 @@ def build_file_from_blob(blob, mode, target_path, honor_filemode=True):
     :param honor_filemode: An optional flag to honor core.filemode setting in
         config file, default is core.filemode=True, change executable bit
     """
+    try:
+        oldstat = os.stat(target_path)
+    except OSError as e:
+        if e.errno == errno.ENOENT:
+            oldstat = None
+        else:
+            raise
+    contents = blob.as_raw_string()
     if stat.S_ISLNK(mode):
         # FIXME: This will fail on Windows. What should we do instead?
-        src_path = blob.as_raw_string()
-        try:
-            os.symlink(src_path, target_path)
-        except OSError as e:
-            if e.errno == errno.EEXIST:
-                os.unlink(target_path)
-                os.symlink(src_path, target_path)
-            else:
-                raise
+        if oldstat:
+            os.unlink(target_path)
+        os.symlink(contents, target_path)
     else:
-        if os.path.exists(target_path):
+        if oldstat is not None and oldstat.st_size == len(contents):
             with open(target_path, 'rb') as f:
-                if f.read() == blob.as_raw_string():
+                if f.read() == contents:
                     return
 
         with open(target_path, 'wb') as f:
             # Write out file
-            f.write(blob.as_raw_string())
+            f.write(contents)
 
         if honor_filemode:
             os.chmod(target_path, mode)

+ 8 - 10
dulwich/tests/test_index.py

@@ -369,10 +369,10 @@ class BuildIndexTests(TestCase):
                 sorted(os.listdir(os.path.join(repo.path, 'c'))))
 
     def test_norewrite(self):
+        sync = getattr(os, 'sync', lambda: os.system('sync'))
         repo_dir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, repo_dir)
         with Repo.init(repo_dir) as repo:
-
             # Populate repo
             filea = Blob.from_string(b'file a')
             filea_path = os.path.join(repo_dir, 'a')
@@ -386,28 +386,26 @@ class BuildIndexTests(TestCase):
             build_index_from_tree(repo.path, repo.index_path(),
                                   repo.object_store, tree.id)
             # Use sync as metadata can be cached on some FS
-            os.system('sync')
+            sync()
             mtime = os.stat(filea_path).st_mtime
 
             # Test Rewrite
             build_index_from_tree(repo.path, repo.index_path(),
                                   repo.object_store, tree.id)
-            os.system('sync')
-            self.assertEqual(mtime, 
-                             os.stat(filea_path).st_mtime)
+            sync()
+            self.assertEqual(mtime, os.stat(filea_path).st_mtime)
 
             # Modify content
             with open(filea_path, 'wb') as fh:
                 fh.write(b'test a')
-            os.system('sync')
+            sync()
             mtime = os.stat(filea_path).st_mtime
- 
+
             # Test rewrite
             build_index_from_tree(repo.path, repo.index_path(),
                                   repo.object_store, tree.id)
-            os.system('sync')
-            self.assertNotEqual(mtime, 
-                                os.stat(filea_path).st_mtime)
+            sync()
+            self.assertNotEqual(mtime, os.stat(filea_path).st_mtime)
 
 
     @skipIf(not getattr(os, 'symlink', None), 'Requires symlink support')