Commit 52949c806b43ce1fec283c2a9627aa0688f8aa9e

Edward Thomson 2017-01-21T18:30:12

Merge branch 'pr/4060'

diff --git a/src/indexer.c b/src/indexer.c
index 4e8919a..05a02f6 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -33,7 +33,7 @@ struct entry {
 
 struct git_indexer {
 	unsigned int parsed_header :1,
-		opened_pack :1,
+		pack_committed :1,
 		have_stream :1,
 		have_delta :1;
 	struct git_pack_header hdr;
@@ -151,6 +151,12 @@ cleanup:
 	if (fd != -1)
 		p_close(fd);
 
+	if (git_buf_len(&tmp_path) > 0)
+		p_unlink(git_buf_cstr(&tmp_path));
+
+	if (idx->pack != NULL)
+		p_unlink(idx->pack->pack_name);
+
 	git_buf_free(&path);
 	git_buf_free(&tmp_path);
 	git__free(idx);
@@ -1054,6 +1060,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
 
 	/* And don't forget to rename the packfile to its new place. */
 	p_rename(idx->pack->pack_name, git_buf_cstr(&filename));
+	idx->pack_committed = 1;
 
 	git_buf_free(&filename);
 	git_hash_ctx_cleanup(&ctx);
@@ -1084,6 +1091,16 @@ void git_indexer_free(git_indexer *idx)
 
 	git_vector_free_deep(&idx->deltas);
 
+	/* Try to delete the temporary file in case it was not committed. */
+	git_mwindow_free_all(&idx->pack->mwf);
+
+	/* We need to close the descriptor here so Windows doesn't choke on unlink */
+	if (idx->pack->mwf.fd != -1)
+		p_close(idx->pack->mwf.fd);
+
+	if (!idx->pack_committed)
+		p_unlink(idx->pack->pack_name);
+
 	if (!git_mutex_lock(&git__mwindow_mutex)) {
 		git_packfile_free(idx->pack);
 		git_mutex_unlock(&git__mwindow_mutex);
diff --git a/tests/pack/indexer.c b/tests/pack/indexer.c
index 49a106d..1e514b2 100644
--- a/tests/pack/indexer.c
+++ b/tests/pack/indexer.c
@@ -125,3 +125,44 @@ void test_pack_indexer__fix_thin(void)
 		git_indexer_free(idx);
 	}
 }
+
+static int find_tmp_file_recurs(void *opaque, git_buf *path)
+{
+	int error = 0;
+	git_buf *first_tmp_file = opaque;
+	struct stat st;
+
+	if ((error = p_lstat_posixly(path->ptr, &st)) < 0)
+		return error;
+
+	if (S_ISDIR(st.st_mode))
+		return git_path_direach(path, 0, find_tmp_file_recurs, opaque);
+
+	/* This is the template that's used in git_futils_mktmp. */
+	if (strstr(git_buf_cstr(path), "_git2_") != NULL)
+		return git_buf_sets(first_tmp_file, git_buf_cstr(path));
+
+	return 0;
+}
+
+void test_pack_indexer__no_tmp_files(void)
+{
+	git_indexer *idx = NULL;
+	git_buf path = GIT_BUF_INIT;
+	git_buf first_tmp_file = GIT_BUF_INIT;
+
+	/* Precondition: there are no temporary files. */
+	cl_git_pass(git_buf_sets(&path, clar_sandbox_path()));
+	cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path));
+	git_buf_free(&path);
+	cl_assert(git_buf_len(&first_tmp_file) == 0);
+
+	cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL));
+	git_indexer_free(idx);
+
+	cl_git_pass(git_buf_sets(&path, clar_sandbox_path()));
+	cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path));
+	git_buf_free(&path);
+	cl_assert(git_buf_len(&first_tmp_file) == 0);
+	git_buf_free(&first_tmp_file);
+}