Merge branch 'pr/4060'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
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);
+}