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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
#include "clar_libgit2.h"
#include "mwindow.h"
#include "global.h"
#include <git2.h>
#include "git2/sys/commit.h"
#include "git2/sys/mempack.h"
static size_t expected_open_mwindow_files = 0;
static size_t original_mwindow_file_limit = 0;
extern git_mwindow_ctl git_mwindow__mem_ctl;
void test_pack_filelimit__initialize_tiny(void)
{
expected_open_mwindow_files = 1;
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit));
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, expected_open_mwindow_files));
}
void test_pack_filelimit__initialize_medium(void)
{
expected_open_mwindow_files = 10;
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit));
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, expected_open_mwindow_files));
}
void test_pack_filelimit__initialize_unlimited(void)
{
expected_open_mwindow_files = 15;
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit));
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, 0));
}
void test_pack_filelimit__cleanup(void)
{
git_buf path = GIT_BUF_INIT;
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, original_mwindow_file_limit));
cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "repo.git"));
cl_fixture_cleanup(path.ptr);
git_buf_dispose(&path);
}
/*
* Create a packfile with one commit, one tree, and two blobs. The first blob
* (README.md) has the same content in all commits, but the second one
* (file.txt) has a different content in each commit.
*/
void create_packfile_commit(
git_repository *repo,
git_oid *out_commit_id,
git_oid *parent_id,
size_t commit_index,
size_t commit_count)
{
git_buf file_contents = GIT_BUF_INIT;
git_treebuilder *treebuilder;
git_packbuilder *packbuilder;
git_signature *s;
git_oid oid, tree_id, commit_id;
const git_oid *parents[] = { parent_id };
size_t parent_count = parent_id ? 1 : 0;
cl_git_pass(git_treebuilder_new(&treebuilder, repo, NULL));
cl_git_pass(git_blob_create_from_buffer(&oid, repo, "", 0));
cl_git_pass(git_treebuilder_insert(NULL, treebuilder, "README.md", &oid, 0100644));
cl_git_pass(git_buf_printf(&file_contents, "Commit %zd/%zd", commit_index, commit_count));
cl_git_pass(git_blob_create_from_buffer(&oid, repo, file_contents.ptr, file_contents.size));
cl_git_pass(git_treebuilder_insert(NULL, treebuilder, "file.txt", &oid, 0100644));
cl_git_pass(git_treebuilder_write(&tree_id, treebuilder));
cl_git_pass(git_signature_now(&s, "alice", "alice@example.com"));
cl_git_pass(git_commit_create_from_ids(&commit_id, repo, "refs/heads/master", s, s,
NULL, file_contents.ptr, &tree_id, parent_count, parents));
cl_git_pass(git_packbuilder_new(&packbuilder, repo));
cl_git_pass(git_packbuilder_insert_commit(packbuilder, &commit_id));
cl_git_pass(git_packbuilder_write(packbuilder, NULL, 0, NULL, NULL));
cl_git_pass(git_oid_cpy(out_commit_id, &commit_id));
git_buf_dispose(&file_contents);
git_treebuilder_free(treebuilder);
git_packbuilder_free(packbuilder);
git_signature_free(s);
}
void test_pack_filelimit__open_repo_with_multiple_packfiles(void)
{
git_buf path = GIT_BUF_INIT;
git_mwindow_ctl *ctl = &git_mwindow__mem_ctl;
git_repository *repo;
git_revwalk *walk;
git_oid id, *parent_id = NULL;
size_t i;
const size_t commit_count = 16;
unsigned int open_windows;
/*
* Create a repository and populate it with 16 commits, each in its own
* packfile.
*/
cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "repo.git"));
cl_git_pass(git_repository_init(&repo, path.ptr, true));
for (i = 0; i < commit_count; ++i) {
create_packfile_commit(repo, &id, parent_id, i + 1, commit_count);
parent_id = &id;
}
cl_git_pass(git_revwalk_new(&walk, repo));
cl_git_pass(git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL));
cl_git_pass(git_revwalk_push_ref(walk, "refs/heads/master"));
/* Walking the repository requires eventually opening each of the packfiles. */
i = 0;
while (git_revwalk_next(&id, walk) == 0)
++i;
cl_assert_equal_i(commit_count, i);
cl_git_pass(git_mutex_lock(&git__mwindow_mutex));
/*
* Adding an assert while holding a lock will cause the whole process to
* deadlock. Copy the value and do the assert after releasing the lock.
*/
open_windows = ctl->open_windows;
cl_git_pass(git_mutex_unlock(&git__mwindow_mutex));
cl_assert_equal_i(expected_open_mwindow_files, open_windows);
git_buf_dispose(&path);
git_revwalk_free(walk);
git_repository_free(repo);
}