Hash :
a3cd5e94
Author :
Date :
2017-12-06T03:03:18
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 137 138 139 140 141 142 143 144 145 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 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
#include "clar_libgit2.h"
#include <git2.h>
#include "fileops.h"
#include "hash.h"
#include "iterator.h"
#include "vector.h"
#include "posix.h"
/*
* This is a packfile with three objects. The second is a delta which
* depends on the third, which is also a delta.
*/
static const unsigned char out_of_order_pack[] = {
0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
0x32, 0x78, 0x9c, 0x63, 0x67, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x76,
0xe6, 0x8f, 0xe8, 0x12, 0x9b, 0x54, 0x6b, 0x10, 0x1a, 0xee, 0x95, 0x10,
0xc5, 0x32, 0x8e, 0x7f, 0x21, 0xca, 0x1d, 0x18, 0x78, 0x9c, 0x63, 0x62,
0x66, 0x4e, 0xcb, 0xcf, 0x07, 0x00, 0x02, 0xac, 0x01, 0x4d, 0x75, 0x01,
0xd7, 0x71, 0x36, 0x66, 0xf4, 0xde, 0x82, 0x27, 0x76, 0xc7, 0x62, 0x2c,
0x10, 0xf1, 0xb0, 0x7d, 0xe2, 0x80, 0xdc, 0x78, 0x9c, 0x63, 0x62, 0x62,
0x62, 0xb7, 0x03, 0x00, 0x00, 0x69, 0x00, 0x4c, 0xde, 0x7d, 0xaa, 0xe4,
0x19, 0x87, 0x58, 0x80, 0x61, 0x09, 0x9a, 0x33, 0xca, 0x7a, 0x31, 0x92,
0x6f, 0xae, 0x66, 0x75
};
static const unsigned int out_of_order_pack_len = 112;
/*
* Packfile with two objects. The second is a delta against an object
* which is not in the packfile
*/
static const unsigned char thin_pack[] = {
0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,
0x32, 0x78, 0x9c, 0x63, 0x67, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x76,
0xe6, 0x8f, 0xe8, 0x12, 0x9b, 0x54, 0x6b, 0x10, 0x1a, 0xee, 0x95, 0x10,
0xc5, 0x32, 0x8e, 0x7f, 0x21, 0xca, 0x1d, 0x18, 0x78, 0x9c, 0x63, 0x62,
0x66, 0x4e, 0xcb, 0xcf, 0x07, 0x00, 0x02, 0xac, 0x01, 0x4d, 0x42, 0x52,
0x3a, 0x6f, 0x39, 0xd1, 0xfe, 0x66, 0x68, 0x6b, 0xa5, 0xe5, 0xe2, 0x97,
0xac, 0x94, 0x6c, 0x76, 0x0b, 0x04
};
static const unsigned int thin_pack_len = 78;
/*
* Packfile that causes the packfile stream to open in a way in which it leaks
* the stream reader.
*/
static const unsigned char leaky_pack[] = {
0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03,
0xf4, 0xbd, 0x51, 0x51, 0x51, 0x51, 0x51, 0x72, 0x65, 0x41, 0x4b, 0x63,
0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0xbd, 0x41, 0x4b
};
static const unsigned int leaky_pack_len = 33;
static const unsigned char base_obj[] = { 07, 076 };
static const unsigned int base_obj_len = 2;
void test_pack_indexer__out_of_order(void)
{
git_indexer *idx = 0;
git_transfer_progress stats = { 0 };
cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL));
cl_git_pass(git_indexer_append(
idx, out_of_order_pack, out_of_order_pack_len, &stats));
cl_git_pass(git_indexer_commit(idx, &stats));
cl_assert_equal_i(stats.total_objects, 3);
cl_assert_equal_i(stats.received_objects, 3);
cl_assert_equal_i(stats.indexed_objects, 3);
git_indexer_free(idx);
}
void test_pack_indexer__leaky(void)
{
git_indexer *idx = 0;
git_transfer_progress stats = { 0 };
cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL));
cl_git_pass(git_indexer_append(
idx, leaky_pack, leaky_pack_len, &stats));
cl_git_fail(git_indexer_commit(idx, &stats));
cl_assert(giterr_last() != NULL);
cl_assert_equal_i(giterr_last()->klass, GITERR_INDEXER);
git_indexer_free(idx);
}
void test_pack_indexer__missing_trailer(void)
{
git_indexer *idx = 0;
git_transfer_progress stats = { 0 };
cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL));
/* Truncate a valid packfile */
cl_git_pass(git_indexer_append(
idx, out_of_order_pack, out_of_order_pack_len - 20, &stats));
cl_git_fail(git_indexer_commit(idx, &stats));
cl_assert(giterr_last() != NULL);
cl_assert_equal_i(giterr_last()->klass, GITERR_INDEXER);
git_indexer_free(idx);
}
void test_pack_indexer__fix_thin(void)
{
git_indexer *idx = NULL;
git_transfer_progress stats = { 0 };
git_repository *repo;
git_odb *odb;
git_oid id, should_id;
cl_git_pass(git_repository_init(&repo, "thin.git", true));
cl_git_pass(git_repository_odb(&odb, repo));
/* Store the missing base into your ODB so the indexer can fix the pack */
cl_git_pass(git_odb_write(&id, odb, base_obj, base_obj_len, GIT_OBJ_BLOB));
git_oid_fromstr(&should_id, "e68fe8129b546b101aee9510c5328e7f21ca1d18");
cl_assert_equal_oid(&should_id, &id);
cl_git_pass(git_indexer_new(&idx, ".", 0, odb, NULL, NULL));
cl_git_pass(git_indexer_append(idx, thin_pack, thin_pack_len, &stats));
cl_git_pass(git_indexer_commit(idx, &stats));
cl_assert_equal_i(stats.total_objects, 2);
cl_assert_equal_i(stats.received_objects, 2);
cl_assert_equal_i(stats.indexed_objects, 2);
cl_assert_equal_i(stats.local_objects, 1);
git_oid_fromstr(&should_id, "fefdb2d740a3a6b6c03a0c7d6ce431c6d5810e13");
cl_assert_equal_oid(&should_id, git_indexer_hash(idx));
git_indexer_free(idx);
git_odb_free(odb);
git_repository_free(repo);
/*
* The pack's name/hash only tells us what objects there are,
* so we need to go through the packfile again in order to
* figure out whether we calculated the trailer correctly.
*/
{
unsigned char buffer[128];
int fd;
ssize_t read;
struct stat st;
const char *name = "pack-fefdb2d740a3a6b6c03a0c7d6ce431c6d5810e13.pack";
fd = p_open(name, O_RDONLY);
cl_assert(fd != -1);
cl_git_pass(p_stat(name, &st));
cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL));
read = p_read(fd, buffer, sizeof(buffer));
cl_assert(read != -1);
p_close(fd);
cl_git_pass(git_indexer_append(idx, buffer, read, &stats));
cl_git_pass(git_indexer_commit(idx, &stats));
cl_assert_equal_i(stats.total_objects, 3);
cl_assert_equal_i(stats.received_objects, 3);
cl_assert_equal_i(stats.indexed_objects, 3);
cl_assert_equal_i(stats.local_objects, 0);
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);
}