packbuilder.c 5.58 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");
Michael Schubert committed
20 21 22
	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));
23
	_commits_is_initialized = 1;
24
	memset(&_stats, 0, sizeof(_stats));
Michael Schubert committed
25 26 27 28 29 30 31
}

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

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

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

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

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

Vicent Marti committed
49
	cl_git_sandbox_cleanup();
50
	_repo = NULL;
Michael Schubert committed
51 52
}

53
static void seed_packbuilder(void)
Michael Schubert committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
{
	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
76
					git_commit_tree_id((git_commit *)obj)));
Michael Schubert committed
77 78
		git_object_free(obj);
	}
79 80
}

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

85
	return git_indexer_append(_indexer, ptr, len, stats);
86 87
}

88 89 90
void test_pack_packbuilder__create_pack(void)
{
	git_transfer_progress stats;
91
	git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
92 93 94
	git_hash_ctx ctx;
	git_oid hash;
	char hex[41]; hex[40] = '\0';
Michael Schubert committed
95

96
	seed_packbuilder();
Michael Schubert committed
97

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

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

	/*
	 * 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).
	 *
111
	 * $ cd tests/resources/testrepo.git
112 113 114 115 116 117 118
	 * $ git rev-list --objects HEAD | \
	 * 	git pack-objects -q --no-reuse-delta --threads=1 pack
	 * $ sha1sum git-80e61eb315239ef3c53033e37fee43b744d57122.pack
	 * 5d410bdf97cf896f9007681b92868471d636954b
	 *
	 */

119
	cl_git_pass(git_futils_readbuffer(&buf, git_buf_cstr(&path)));
120

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

126
	git_buf_free(&path);
127 128 129 130 131
	git_buf_free(&buf);

	git_oid_fmt(hex, &hash);

	cl_assert_equal_s(hex, "5d410bdf97cf896f9007681b92868471d636954b");
Michael Schubert committed
132
}
133

134 135 136 137 138 139
void test_pack_packbuilder__get_hash(void)
{
	char hex[41]; hex[40] = '\0';

	seed_packbuilder();

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

	cl_assert_equal_s(hex, "80e61eb315239ef3c53033e37fee43b744d57122");
}

146 147 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
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);
}

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

void test_pack_packbuilder__foreach(void)
{
198
	git_indexer *idx;
199 200

	seed_packbuilder();
201
	cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL));
202
	cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx));
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
	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);
222
	git_indexer_free(idx);
223
}