1 #include "clar_libgit2.h"
6 #include "git2/sys/filter.h"
7 #include "git2/sys/repository.h"
8 #include "custom_helpers.h"
10 /* going TO_WORKDIR, filters are executed low to high
11 * going TO_ODB, filters are executed high to low
13 #define BITFLIP_FILTER_PRIORITY -1
14 #define REVERSE_FILTER_PRIORITY -2
17 # define NEWLINE "\r\n"
22 static char workdir_data
[] =
25 "that will be" NEWLINE
29 #define REVERSED_DATA_LEN 51
31 /* Represents the data above scrambled (bits flipped) after \r\n -> \n
32 * conversion, then bytewise reversed
34 static unsigned char bitflipped_and_reversed_data
[] =
35 { 0xf5, 0xd1, 0x9b, 0x9a, 0x93, 0x9d, 0x92, 0x9e, 0x8d, 0x9c, 0x8c,
36 0xf5, 0x86, 0x93, 0x93, 0x9e, 0x96, 0x89, 0x96, 0x8d, 0x8b, 0xf5,
37 0x9a, 0x9d, 0xdf, 0x93, 0x93, 0x96, 0x88, 0xdf, 0x8b, 0x9e, 0x97,
38 0x8b, 0xf5, 0x9e, 0x8b, 0x9e, 0x9b, 0xf5, 0x9a, 0x93, 0x8f, 0x92,
39 0x96, 0x8c, 0xdf, 0x9a, 0x92, 0x90, 0x8c };
41 #define BITFLIPPED_AND_REVERSED_DATA_LEN 51
43 static git_repository
*g_repo
= NULL
;
45 static void register_custom_filters(void);
47 void test_filter_custom__initialize(void)
49 register_custom_filters();
51 g_repo
= cl_git_sandbox_init("empty_standard_repo");
54 "empty_standard_repo/.gitattributes",
55 "hero* bitflip reverse\n"
57 "heroflip -reverse binary\n"
62 void test_filter_custom__cleanup(void)
64 cl_git_sandbox_cleanup();
68 static void register_custom_filters(void)
70 static int filters_registered
= 0;
72 if (!filters_registered
) {
73 cl_git_pass(git_filter_register(
74 "bitflip", create_bitflip_filter(), BITFLIP_FILTER_PRIORITY
));
76 cl_git_pass(git_filter_register(
77 "reverse", create_reverse_filter("+reverse"),
78 REVERSE_FILTER_PRIORITY
));
80 /* re-register reverse filter with standard filter=xyz priority */
81 cl_git_pass(git_filter_register(
83 create_reverse_filter("+prereverse"),
84 GIT_FILTER_DRIVER_PRIORITY
));
86 cl_git_pass(git_filter_register(
88 create_erroneous_filter("+erroneous"),
89 GIT_FILTER_DRIVER_PRIORITY
));
91 filters_registered
= 1;
95 void test_filter_custom__to_odb(void)
99 git_buf in
= GIT_BUF_INIT_CONST(workdir_data
, strlen(workdir_data
));
101 cl_git_pass(git_filter_list_load(
102 &fl
, g_repo
, NULL
, "herofile", GIT_FILTER_TO_ODB
, 0));
104 cl_git_pass(git_filter_list_apply_to_data(&out
, fl
, &in
));
106 cl_assert_equal_i(BITFLIPPED_AND_REVERSED_DATA_LEN
, out
.size
);
109 0, memcmp(bitflipped_and_reversed_data
, out
.ptr
, out
.size
));
111 git_filter_list_free(fl
);
112 git_buf_dispose(&out
);
115 void test_filter_custom__to_workdir(void)
119 git_buf in
= GIT_BUF_INIT_CONST(
120 bitflipped_and_reversed_data
, BITFLIPPED_AND_REVERSED_DATA_LEN
);
122 cl_git_pass(git_filter_list_load(
123 &fl
, g_repo
, NULL
, "herofile", GIT_FILTER_TO_WORKTREE
, 0));
125 cl_git_pass(git_filter_list_apply_to_data(&out
, fl
, &in
));
127 cl_assert_equal_i(strlen(workdir_data
), out
.size
);
130 0, memcmp(workdir_data
, out
.ptr
, out
.size
));
132 git_filter_list_free(fl
);
133 git_buf_dispose(&out
);
136 void test_filter_custom__can_register_a_custom_filter_in_the_repository(void)
140 cl_git_pass(git_filter_list_load(
141 &fl
, g_repo
, NULL
, "herofile", GIT_FILTER_TO_WORKTREE
, 0));
142 /* expect: bitflip, reverse, crlf */
143 cl_assert_equal_sz(3, git_filter_list_length(fl
));
144 git_filter_list_free(fl
);
146 cl_git_pass(git_filter_list_load(
147 &fl
, g_repo
, NULL
, "herocorp", GIT_FILTER_TO_WORKTREE
, 0));
148 /* expect: bitflip, reverse - possibly crlf depending on global config */
150 size_t flen
= git_filter_list_length(fl
);
151 cl_assert(flen
== 2 || flen
== 3);
153 git_filter_list_free(fl
);
155 cl_git_pass(git_filter_list_load(
156 &fl
, g_repo
, NULL
, "hero.bin", GIT_FILTER_TO_WORKTREE
, 0));
157 /* expect: bitflip, reverse */
158 cl_assert_equal_sz(2, git_filter_list_length(fl
));
159 git_filter_list_free(fl
);
161 cl_git_pass(git_filter_list_load(
162 &fl
, g_repo
, NULL
, "heroflip", GIT_FILTER_TO_WORKTREE
, 0));
163 /* expect: bitflip (because of -reverse) */
164 cl_assert_equal_sz(1, git_filter_list_length(fl
));
165 git_filter_list_free(fl
);
167 cl_git_pass(git_filter_list_load(
168 &fl
, g_repo
, NULL
, "doesntapplytome.bin",
169 GIT_FILTER_TO_WORKTREE
, 0));
171 cl_assert_equal_sz(0, git_filter_list_length(fl
));
172 git_filter_list_free(fl
);
175 void test_filter_custom__order_dependency(void)
181 /* so if ident and reverse are used together, an interesting thing
182 * happens - a reversed "$Id$" string is no longer going to trigger
183 * ident correctly. When checking out, the filters should be applied
184 * in order CLRF, then ident, then reverse, so ident expansion should
185 * work correctly. On check in, the content should be reversed, then
186 * ident, then CRLF filtered. Let's make sure that works...
190 "empty_standard_repo/.gitattributes",
191 "hero.*.rev-ident text ident prereverse eol=lf\n");
194 "empty_standard_repo/hero.1.rev-ident",
195 "This is a test\n$Id$\nHave fun!\n");
198 "empty_standard_repo/hero.2.rev-ident",
199 "Another test\n$dI$\nCrazy!\n");
201 cl_git_pass(git_repository_index(&index
, g_repo
));
202 cl_git_pass(git_index_add_bypath(index
, "hero.1.rev-ident"));
203 cl_git_pass(git_index_add_bypath(index
, "hero.2.rev-ident"));
204 cl_repo_commit_from_index(NULL
, g_repo
, NULL
, 0, "Filter chains\n");
205 git_index_free(index
);
207 cl_git_pass(git_blob_lookup(&blob
, g_repo
,
208 & git_index_get_bypath(index
, "hero.1.rev-ident", 0)->id
));
210 "\n!nuf evaH\n$dI$\ntset a si sihT", git_blob_rawcontent(blob
));
211 cl_git_pass(git_blob_filter(&buf
, blob
, "hero.1.rev-ident", NULL
));
212 /* no expansion because id was reversed at checkin and now at ident
213 * time, reverse is not applied yet */
215 "This is a test\n$Id$\nHave fun!\n", buf
.ptr
);
218 cl_git_pass(git_blob_lookup(&blob
, g_repo
,
219 & git_index_get_bypath(index
, "hero.2.rev-ident", 0)->id
));
221 "\n!yzarC\n$Id$\ntset rehtonA", git_blob_rawcontent(blob
));
222 cl_git_pass(git_blob_filter(&buf
, blob
, "hero.2.rev-ident", NULL
));
223 /* expansion because reverse was applied at checkin and at ident time,
224 * reverse is not applied yet */
226 "Another test\n$ 59001fe193103b1016b27027c0c827d036fd0ac8 :dI$\nCrazy!\n", buf
.ptr
);
227 cl_assert_equal_i(0, git_oid_strcmp(
228 git_blob_id(blob
), "8ca0df630d728c0c72072b6101b301391ef10095"));
231 git_buf_dispose(&buf
);
234 void test_filter_custom__filter_registry_failure_cases(void)
236 git_filter fake
= { GIT_FILTER_VERSION
, 0 };
238 cl_assert_equal_i(GIT_EEXISTS
, git_filter_register("bitflip", &fake
, 0));
240 cl_git_fail(git_filter_unregister(GIT_FILTER_CRLF
));
241 cl_git_fail(git_filter_unregister(GIT_FILTER_IDENT
));
242 cl_assert_equal_i(GIT_ENOTFOUND
, git_filter_unregister("not-a-filter"));
245 void test_filter_custom__erroneous_filter_fails(void)
247 git_filter_list
*filters
;
248 git_buf out
= GIT_BUF_INIT
;
249 git_buf in
= GIT_BUF_INIT_CONST(workdir_data
, strlen(workdir_data
));
251 cl_git_pass(git_filter_list_load(
252 &filters
, g_repo
, NULL
, "villain", GIT_FILTER_TO_WORKTREE
, 0));
254 cl_git_fail(git_filter_list_apply_to_data(&out
, filters
, &in
));
256 git_filter_list_free(filters
);
257 git_buf_dispose(&out
);