From 13d5737ee6de729ed85d951cccaa3127cd22dcde Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 21 Feb 2013 21:50:07 -0500 Subject: [PATCH] fsync loose objects before moving into place When we write a loose object to disk, we simply close the file object before moving it into place. If the machine crashes shortly after our write, the contents may not have been committed to disk (depending your filesystem, usually the metadata is, and you end up with a corrupt, zero-length loose object file). This is especially bad because we report that the object is successfully written, which means we may have updated refs to point to it. A corrupt object at that point means not only does the operation fail, but the repository is left in a corrupted and unusable state. We can fix this by calling fsync on the object file before linking it into place. Between this and the previous commit, our object writing should now behave exactly like git's internal routines. --- lib/grit/git-ruby/internal/loose.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/grit/git-ruby/internal/loose.rb b/lib/grit/git-ruby/internal/loose.rb index 3ac9df31..db1940a3 100644 --- a/lib/grit/git-ruby/internal/loose.rb +++ b/lib/grit/git-ruby/internal/loose.rb @@ -66,6 +66,7 @@ def get_raw_object(buf) def safe_write(path, content) Tempfile.open("tmp_obj_", File.dirname(path), :opt => "wb") do |f| f.write content + f.fsync f.close begin File.link(f.path, path)