packbuilder.c 5.7 KB
Newer Older
Michael Schubert committed
1
#include "clar_libgit2.h"
2
#include "fileops.h"
3
#include "pack.h"
4
#include "hash.h"
Michael Schubert committed
5 6
#include "iterator.h"
#include "vector.h"
Ben Straub committed
7
#include "posix.h"
Michael Schubert committed
8 9 10 11

static git_repository *_repo;
static git_revwalk *_revwalker;
static git_packbuilder *_packbuilder;
12
static git_indexer *_indexer;
Michael Schubert committed
13
static git_vector _commits;
14
static int _commits_is_initialized;
15
static git_transfer_progress _stats;
Michael Schubert committed
16 17 18

void test_pack_packbuilder__initialize(void)
{
Vicent Marti committed
19
	_repo = cl_git_sandbox_init("testrepo.git");
20
	cl_git_pass(p_chdir("testrepo.git"));
Michael Schubert committed
21 22 23
	cl_git_pass(git_revwalk_new(&_revwalker, _repo));
	cl_git_pass(git_packbuilder_new(&_packbuilder, _repo));
	cl_git_pass(git_vector_init(&_commits, 0, NULL));
24
	_commits_is_initialized = 1;
25
	memset(&_stats, 0, sizeof(_stats));
Michael Schubert committed
26 27 28 29 30 31 32
}

void test_pack_packbuilder__cleanup(void)
{
	git_oid *o;
	unsigned int i;

33 34 35 36 37 38
	if (_commits_is_initialized) {
		_commits_is_initialized = 0;
		git_vector_foreach(&_commits, i, o) {
			git__free(o);
		}
		git_vector_free(&_commits);
Michael Schubert committed
39
	}
40

Michael Schubert committed
41
	git_packbuilder_free(_packbuilder);
42 43
	_packbuilder = NULL;

Michael Schubert committed
44
	git_revwalk_free(_revwalker);
45 46
	_revwalker = NULL;

47
	git_indexer_free(_indexer);
48
	_indexer = NULL;
49

50
	cl_git_pass(p_chdir(".."));
Vicent Marti committed
51
	cl_git_sandbox_cleanup();
52
	_repo = NULL;
Michael Schubert committed
53 54
}

55
static void seed_packbuilder(void)
Michael Schubert committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
{
	git_oid oid, *o;
	unsigned int i;

	git_revwalk_sorting(_revwalker, GIT_SORT_TIME);
	cl_git_pass(git_revwalk_push_ref(_revwalker, "HEAD"));

	while (git_revwalk_next(&oid, _revwalker) == 0) {
		o = git__malloc(GIT_OID_RAWSZ);
		cl_assert(o != NULL);
		git_oid_cpy(o, &oid);
		cl_git_pass(git_vector_insert(&_commits, o));
	}

	git_vector_foreach(&_commits, i, o) {
		cl_git_pass(git_packbuilder_insert(_packbuilder, o, NULL));
	}

	git_vector_foreach(&_commits, i, o) {
		git_object *obj;
		cl_git_pass(git_object_lookup(&obj, _repo, o, GIT_OBJ_COMMIT));
		cl_git_pass(git_packbuilder_insert_tree(_packbuilder,
Vicent Marti committed
78
					git_commit_tree_id((git_commit *)obj)));
Michael Schubert committed
79 80
		git_object_free(obj);
	}
81 82
}

83 84 85 86
static int feed_indexer(void *ptr, size_t len, void *payload)
{
	git_transfer_progress *stats = (git_transfer_progress *)payload;

87
	return git_indexer_append(_indexer, ptr, len, stats);
88 89
}

90 91 92
void test_pack_packbuilder__create_pack(void)
{
	git_transfer_progress stats;
93
	git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
94 95
	git_hash_ctx ctx;
	git_oid hash;
96
	char hex[GIT_OID_HEXSZ+1]; hex[GIT_OID_HEXSZ] = '\0';
Michael Schubert committed
97

98
	seed_packbuilder();
Michael Schubert committed
99

100
	cl_git_pass(git_indexer_new(&_indexer, ".", 0, NULL, NULL, NULL));
101
	cl_git_pass(git_packbuilder_foreach(_packbuilder, feed_indexer, &stats));
102
	cl_git_pass(git_indexer_commit(_indexer, &stats));
103

104
	git_oid_fmt(hex, git_indexer_hash(_indexer));
105
	git_buf_printf(&path, "pack-%s.pack", hex);
106 107 108 109 110 111 112

	/*
	 * By default, packfiles are created with only one thread.
	 * Therefore we can predict the object ordering and make sure
	 * we create exactly the same pack as git.git does when *not*
	 * reusing existing deltas (as libgit2).
	 *
113
	 * $ cd tests/resources/testrepo.git
114 115 116 117 118 119 120
	 * $ git rev-list --objects HEAD | \
	 * 	git pack-objects -q --no-reuse-delta --threads=1 pack
	 * $ sha1sum git-80e61eb315239ef3c53033e37fee43b744d57122.pack
	 * 5d410bdf97cf896f9007681b92868471d636954b
	 *
	 */

121
	cl_git_pass(git_futils_readbuffer(&buf, git_buf_cstr(&path)));
122

123
	cl_git_pass(git_hash_ctx_init(&ctx));
124 125
	cl_git_pass(git_hash_update(&ctx, buf.ptr, buf.size));
	cl_git_pass(git_hash_final(&hash, &ctx));
126
	git_hash_ctx_cleanup(&ctx);
127

128
	git_buf_free(&path);
129 130 131 132 133
	git_buf_free(&buf);

	git_oid_fmt(hex, &hash);

	cl_assert_equal_s(hex, "5d410bdf97cf896f9007681b92868471d636954b");
Michael Schubert committed
134
}
135

136 137
void test_pack_packbuilder__get_hash(void)
{
138
	char hex[GIT_OID_HEXSZ+1]; hex[GIT_OID_HEXSZ] = '\0';
139 140 141

	seed_packbuilder();

142
	git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL);
143 144 145 146 147
	git_oid_fmt(hex, git_packbuilder_hash(_packbuilder));

	cl_assert_equal_s(hex, "80e61eb315239ef3c53033e37fee43b744d57122");
}

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
static void test_write_pack_permission(mode_t given, mode_t expected)
{
	struct stat statbuf;
	mode_t mask, os_mask;

	seed_packbuilder();

	git_packbuilder_write(_packbuilder, ".", given, NULL, NULL);

	/* Windows does not return group/user bits from stat,
	* files are never executable.
	*/
#ifdef GIT_WIN32
	os_mask = 0600;
#else
	os_mask = 0777;
#endif

	mask = p_umask(0);
	p_umask(mask);

	cl_git_pass(p_stat("pack-80e61eb315239ef3c53033e37fee43b744d57122.idx", &statbuf));
	cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask);

	cl_git_pass(p_stat("pack-80e61eb315239ef3c53033e37fee43b744d57122.pack", &statbuf));
	cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask);
}

void test_pack_packbuilder__permissions_standard(void)
{
	test_write_pack_permission(0, GIT_PACK_FILE_MODE);
}

void test_pack_packbuilder__permissions_readonly(void)
{
	test_write_pack_permission(0444, 0444);
}

void test_pack_packbuilder__permissions_readwrite(void)
{
	test_write_pack_permission(0666, 0666);
}

191 192
static int foreach_cb(void *buf, size_t len, void *payload)
{
193
	git_indexer *idx = (git_indexer *) payload;
194
	cl_git_pass(git_indexer_append(idx, buf, len, &_stats));
195 196 197 198 199
	return 0;
}

void test_pack_packbuilder__foreach(void)
{
200
	git_indexer *idx;
201 202

	seed_packbuilder();
203
	cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL));
204
	cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx));
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
	cl_git_pass(git_indexer_commit(idx, &_stats));
	git_indexer_free(idx);
}

static int foreach_cancel_cb(void *buf, size_t len, void *payload)
{
	git_indexer *idx = (git_indexer *)payload;
	cl_git_pass(git_indexer_append(idx, buf, len, &_stats));
	return (_stats.total_objects > 2) ? -1111 : 0;
}

void test_pack_packbuilder__foreach_with_cancel(void)
{
	git_indexer *idx;

	seed_packbuilder();
	cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL));
	cl_git_fail_with(
		git_packbuilder_foreach(_packbuilder, foreach_cancel_cb, idx), -1111);
224
	git_indexer_free(idx);
225
}