Commit 1c2c0ae2a4d09f5b0de3c4c091c5a93ab34baa46

Edward Thomson 2016-12-14T12:51:40

packbuilder: honor git_object__synchronized_writing Honor `git_object__synchronized_writing` when creating a packfile and corresponding index.

diff --git a/src/indexer.c b/src/indexer.c
index 869e229..30c3655 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -17,6 +17,7 @@
 #include "oid.h"
 #include "oidmap.h"
 #include "zstream.h"
+#include "object.h"
 
 extern git_mutex git__mwindow_mutex;
 
@@ -989,7 +990,9 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
 		return -1;
 
 	if (git_filebuf_open(&index_file, filename.ptr,
-		GIT_FILEBUF_HASH_CONTENTS, idx->mode) < 0)
+		GIT_FILEBUF_HASH_CONTENTS |
+		(git_object__synchronized_writing ? GIT_FILEBUF_FSYNC : 0),
+		idx->mode) < 0)
 		goto on_error;
 
 	/* Write out the header */
@@ -1066,6 +1069,11 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
 		return -1;
 	}
 
+	if (git_object__synchronized_writing && p_fsync(idx->pack->mwf.fd) < 0) {
+		giterr_set(GITERR_OS, "failed to fsync packfile");
+		goto on_error;
+	}
+
 	/* We need to close the descriptor here so Windows doesn't choke on commit_at */
 	if (p_close(idx->pack->mwf.fd) < 0) {
 		giterr_set(GITERR_OS, "failed to close packfile");
diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c
index 29f3e2d..9afc178 100644
--- a/tests/pack/packbuilder.c
+++ b/tests/pack/packbuilder.c
@@ -23,6 +23,7 @@ void test_pack_packbuilder__initialize(void)
 	cl_git_pass(git_vector_init(&_commits, 0, NULL));
 	_commits_is_initialized = 1;
 	memset(&_stats, 0, sizeof(_stats));
+	p_fsync__cnt = 0;
 }
 
 void test_pack_packbuilder__cleanup(void)
@@ -30,6 +31,8 @@ void test_pack_packbuilder__cleanup(void)
 	git_oid *o;
 	unsigned int i;
 
+	cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 0));
+
 	if (_commits_is_initialized) {
 		_commits_is_initialized = 0;
 		git_vector_foreach(&_commits, i, o) {
@@ -188,6 +191,22 @@ void test_pack_packbuilder__permissions_readwrite(void)
 	test_write_pack_permission(0666, 0666);
 }
 
+void test_pack_packbuilder__does_not_fsync_by_default(void)
+{
+	seed_packbuilder();
+	git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
+	cl_assert_equal_sz(0, p_fsync__cnt);
+}
+
+void test_pack_packbuilder__fsync_when_asked(void)
+{
+	cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 1));
+	p_fsync__cnt = 0;
+	seed_packbuilder();
+	git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
+	cl_assert_equal_sz(2, p_fsync__cnt);
+}
+
 static int foreach_cb(void *buf, size_t len, void *payload)
 {
 	git_indexer *idx = (git_indexer *) payload;