1 #include "clar_libgit2.h"
2 #include "index.h"
3 
4 static git_repository *g_repo = NULL;
5 
test_index_version__cleanup(void)6 void test_index_version__cleanup(void)
7 {
8         cl_git_sandbox_cleanup();
9         g_repo = NULL;
10 }
11 
test_index_version__can_read_v4(void)12 void test_index_version__can_read_v4(void)
13 {
14 	const char *paths[] = {
15 	    "file.tx", "file.txt", "file.txz", "foo", "zzz",
16 	};
17 	git_index *index;
18 	size_t i;
19 
20 	g_repo = cl_git_sandbox_init("indexv4");
21 
22 	cl_git_pass(git_repository_index(&index, g_repo));
23 	cl_assert_equal_sz(git_index_entrycount(index), 5);
24 
25 	for (i = 0; i < ARRAY_SIZE(paths); i++) {
26 		const git_index_entry *entry =
27 		    git_index_get_bypath(index, paths[i], GIT_INDEX_STAGE_NORMAL);
28 
29 		cl_assert(entry != NULL);
30 	}
31 
32 	git_index_free(index);
33 }
34 
test_index_version__can_write_v4(void)35 void test_index_version__can_write_v4(void)
36 {
37 	const char *paths[] = {
38 	    "foo",
39 	    "foox",
40 	    "foobar",
41 	    "foobal",
42 	    "x",
43 	    "xz",
44 	    "xyzzyx"
45 	};
46 	git_repository *repo;
47 	git_index_entry entry;
48 	git_index *index;
49 	size_t i;
50 
51 	g_repo = cl_git_sandbox_init("empty_standard_repo");
52 	cl_git_pass(git_repository_index(&index, g_repo));
53 	cl_git_pass(git_index_set_version(index, 4));
54 
55 	for (i = 0; i < ARRAY_SIZE(paths); i++) {
56 		memset(&entry, 0, sizeof(entry));
57 		entry.path = paths[i];
58 		entry.mode = GIT_FILEMODE_BLOB;
59 		cl_git_pass(git_index_add_from_buffer(index, &entry, paths[i],
60 						     strlen(paths[i]) + 1));
61 	}
62 	cl_assert_equal_sz(git_index_entrycount(index), ARRAY_SIZE(paths));
63 
64 	cl_git_pass(git_index_write(index));
65 	git_index_free(index);
66 
67 	cl_git_pass(git_repository_open(&repo, git_repository_path(g_repo)));
68 	cl_git_pass(git_repository_index(&index, repo));
69 	cl_assert(git_index_version(index) == 4);
70 
71 	for (i = 0; i < ARRAY_SIZE(paths); i++) {
72 		const git_index_entry *e;
73 
74 		cl_assert(e = git_index_get_bypath(index, paths[i], 0));
75 		cl_assert_equal_s(paths[i], e->path);
76 	}
77 
78 	git_index_free(index);
79 	git_repository_free(repo);
80 }
81 
test_index_version__v4_uses_path_compression(void)82 void test_index_version__v4_uses_path_compression(void)
83 {
84 	git_index_entry entry;
85 	git_index *index;
86 	char path[250], buf[1];
87 	struct stat st;
88 	char i, j;
89 
90 	memset(path, 'a', sizeof(path));
91 	memset(buf, 'a', sizeof(buf));
92 
93 	memset(&entry, 0, sizeof(entry));
94 	entry.path = path;
95 	entry.mode = GIT_FILEMODE_BLOB;
96 
97 	g_repo = cl_git_sandbox_init("indexv4");
98 	cl_git_pass(git_repository_index(&index, g_repo));
99 
100 	/* write 676 paths of 250 bytes length */
101 	for (i = 'a'; i <= 'z'; i++) {
102 		for (j = 'a'; j < 'z'; j++) {
103 			path[ARRAY_SIZE(path) - 3] = i;
104 			path[ARRAY_SIZE(path) - 2] = j;
105 			path[ARRAY_SIZE(path) - 1] = '\0';
106 			cl_git_pass(git_index_add_from_buffer(index, &entry, buf, sizeof(buf)));
107 		}
108 	}
109 
110 	cl_git_pass(git_index_write(index));
111 	cl_git_pass(p_stat(git_index_path(index), &st));
112 
113 	/*
114 	 * Without path compression, the written paths would at
115 	 * least take
116 	 *
117 	 *    (entries * pathlen) = len
118 	 *    (676 * 250) = 169000
119 	 *
120 	 *  bytes. As index v4 uses suffix-compression and our
121 	 *  written paths only differ in the last two entries,
122 	 *  this number will be much smaller, e.g.
123 	 *
124 	 *    (1 * pathlen) + (675 * 2) = len
125 	 *    676 + 1350 = 2026
126 	 *
127 	 *    bytes.
128 	 *
129 	 *    Note that the above calculations do not include
130 	 *    additional metadata of the index, e.g. OIDs or
131 	 *    index extensions. Including those we get an index
132 	 *    of approx. 200kB without compression and 40kB with
133 	 *    compression. As this is a lot smaller than without
134 	 *    compression, we can verify that path compression is
135 	 *    used.
136 	 */
137 	cl_assert_(st.st_size < 75000, "path compression not enabled");
138 
139 	git_index_free(index);
140 }
141