1 #include "clar_libgit2.h"
7 #include "attr_expect.h"
8 #include "git2/sys/repository.h"
10 static git_repository
*g_repo
= NULL
;
12 void test_attr_repo__initialize(void)
14 g_repo
= cl_git_sandbox_init("attr");
17 void test_attr_repo__cleanup(void)
19 cl_git_sandbox_cleanup();
21 cl_sandbox_set_search_path_defaults();
24 static struct attr_expected get_one_test_cases
[] = {
25 { "root_test1", "repoattr", EXPECT_TRUE
, NULL
},
26 { "root_test1", "rootattr", EXPECT_TRUE
, NULL
},
27 { "root_test1", "missingattr", EXPECT_UNDEFINED
, NULL
},
28 { "root_test1", "subattr", EXPECT_UNDEFINED
, NULL
},
29 { "root_test1", "negattr", EXPECT_UNDEFINED
, NULL
},
30 { "root_test2", "repoattr", EXPECT_TRUE
, NULL
},
31 { "root_test2", "rootattr", EXPECT_FALSE
, NULL
},
32 { "root_test2", "missingattr", EXPECT_UNDEFINED
, NULL
},
33 { "root_test2", "multiattr", EXPECT_FALSE
, NULL
},
34 { "root_test3", "repoattr", EXPECT_TRUE
, NULL
},
35 { "root_test3", "rootattr", EXPECT_UNDEFINED
, NULL
},
36 { "root_test3", "multiattr", EXPECT_STRING
, "3" },
37 { "root_test3", "multi2", EXPECT_UNDEFINED
, NULL
},
38 { "sub/subdir_test1", "repoattr", EXPECT_TRUE
, NULL
},
39 { "sub/subdir_test1", "rootattr", EXPECT_TRUE
, NULL
},
40 { "sub/subdir_test1", "missingattr", EXPECT_UNDEFINED
, NULL
},
41 { "sub/subdir_test1", "subattr", EXPECT_STRING
, "yes" },
42 { "sub/subdir_test1", "negattr", EXPECT_FALSE
, NULL
},
43 { "sub/subdir_test1", "another", EXPECT_UNDEFINED
, NULL
},
44 { "sub/subdir_test2.txt", "repoattr", EXPECT_TRUE
, NULL
},
45 { "sub/subdir_test2.txt", "rootattr", EXPECT_TRUE
, NULL
},
46 { "sub/subdir_test2.txt", "missingattr", EXPECT_UNDEFINED
, NULL
},
47 { "sub/subdir_test2.txt", "subattr", EXPECT_STRING
, "yes" },
48 { "sub/subdir_test2.txt", "negattr", EXPECT_FALSE
, NULL
},
49 { "sub/subdir_test2.txt", "another", EXPECT_STRING
, "zero" },
50 { "sub/subdir_test2.txt", "reposub", EXPECT_TRUE
, NULL
},
51 { "sub/sub/subdir.txt", "another", EXPECT_STRING
, "one" },
52 { "sub/sub/subdir.txt", "reposubsub", EXPECT_TRUE
, NULL
},
53 { "sub/sub/subdir.txt", "reposub", EXPECT_UNDEFINED
, NULL
},
54 { "does-not-exist", "foo", EXPECT_STRING
, "yes" },
55 { "sub/deep/file", "deepdeep", EXPECT_TRUE
, NULL
},
56 { "sub/sub/d/no", "test", EXPECT_STRING
, "a/b/d/*" },
57 { "sub/sub/d/yes", "test", EXPECT_UNDEFINED
, NULL
},
60 void test_attr_repo__get_one(void)
64 for (i
= 0; i
< (int)ARRAY_SIZE(get_one_test_cases
); ++i
) {
65 struct attr_expected
*scan
= &get_one_test_cases
[i
];
68 cl_git_pass(git_attr_get(&value
, g_repo
, 0, scan
->path
, scan
->attr
));
70 scan
->expected
, scan
->expected_str
, scan
->attr
, value
);
73 cl_assert(git_attr_cache__is_cached(
74 g_repo
, GIT_ATTR_FILE_SOURCE_FILE
, ".git/info/attributes"));
75 cl_assert(git_attr_cache__is_cached(
76 g_repo
, GIT_ATTR_FILE_SOURCE_FILE
, ".gitattributes"));
77 cl_assert(git_attr_cache__is_cached(
78 g_repo
, GIT_ATTR_FILE_SOURCE_FILE
, "sub/.gitattributes"));
81 void test_attr_repo__get_one_start_deep(void)
85 for (i
= (int)ARRAY_SIZE(get_one_test_cases
) - 1; i
>= 0; --i
) {
86 struct attr_expected
*scan
= &get_one_test_cases
[i
];
89 cl_git_pass(git_attr_get(&value
, g_repo
, 0, scan
->path
, scan
->attr
));
91 scan
->expected
, scan
->expected_str
, scan
->attr
, value
);
94 cl_assert(git_attr_cache__is_cached(
95 g_repo
, GIT_ATTR_FILE_SOURCE_FILE
, ".git/info/attributes"));
96 cl_assert(git_attr_cache__is_cached(
97 g_repo
, GIT_ATTR_FILE_SOURCE_FILE
, ".gitattributes"));
98 cl_assert(git_attr_cache__is_cached(
99 g_repo
, GIT_ATTR_FILE_SOURCE_FILE
, "sub/.gitattributes"));
102 void test_attr_repo__get_many(void)
104 const char *names
[4] = { "repoattr", "rootattr", "missingattr", "subattr" };
105 const char *values
[4];
107 cl_git_pass(git_attr_get_many(values
, g_repo
, 0, "root_test1", 4, names
));
109 cl_assert(GIT_ATTR_IS_TRUE(values
[0]));
110 cl_assert(GIT_ATTR_IS_TRUE(values
[1]));
111 cl_assert(GIT_ATTR_IS_UNSPECIFIED(values
[2]));
112 cl_assert(GIT_ATTR_IS_UNSPECIFIED(values
[3]));
114 cl_git_pass(git_attr_get_many(values
, g_repo
, 0, "root_test2", 4, names
));
116 cl_assert(GIT_ATTR_IS_TRUE(values
[0]));
117 cl_assert(GIT_ATTR_IS_FALSE(values
[1]));
118 cl_assert(GIT_ATTR_IS_UNSPECIFIED(values
[2]));
119 cl_assert(GIT_ATTR_IS_UNSPECIFIED(values
[3]));
121 cl_git_pass(git_attr_get_many(values
, g_repo
, 0, "sub/subdir_test1", 4, names
));
123 cl_assert(GIT_ATTR_IS_TRUE(values
[0]));
124 cl_assert(GIT_ATTR_IS_TRUE(values
[1]));
125 cl_assert(GIT_ATTR_IS_UNSPECIFIED(values
[2]));
126 cl_assert_equal_s("yes", values
[3]);
129 void test_attr_repo__get_many_in_place(void)
131 const char *vals
[4] = { "repoattr", "rootattr", "missingattr", "subattr" };
133 /* it should be legal to look up values into the same array that has
134 * the attribute names, overwriting each name as the value is found.
137 cl_git_pass(git_attr_get_many(vals
, g_repo
, 0, "sub/subdir_test1", 4, vals
));
139 cl_assert(GIT_ATTR_IS_TRUE(vals
[0]));
140 cl_assert(GIT_ATTR_IS_TRUE(vals
[1]));
141 cl_assert(GIT_ATTR_IS_UNSPECIFIED(vals
[2]));
142 cl_assert_equal_s("yes", vals
[3]);
145 static int count_attrs(
153 *((int *)payload
) += 1;
158 #define CANCEL_VALUE 12345
160 static int cancel_iteration(
168 *((int *)payload
) -= 1;
170 if (*((int *)payload
) < 0)
176 void test_attr_repo__foreach(void)
181 cl_git_pass(git_attr_foreach(
182 g_repo
, 0, "root_test1", &count_attrs
, &count
));
183 cl_assert(count
== 2);
186 cl_git_pass(git_attr_foreach(g_repo
, 0, "sub/subdir_test1",
187 &count_attrs
, &count
));
188 cl_assert(count
== 4); /* repoattr, rootattr, subattr, negattr */
191 cl_git_pass(git_attr_foreach(g_repo
, 0, "sub/subdir_test2.txt",
192 &count_attrs
, &count
));
193 cl_assert(count
== 6); /* repoattr, rootattr, subattr, reposub, negattr, another */
197 CANCEL_VALUE
, git_attr_foreach(
198 g_repo
, 0, "sub/subdir_test1", &cancel_iteration
, &count
)
202 void test_attr_repo__manpage_example(void)
206 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "sub/abc", "foo"));
207 cl_assert(GIT_ATTR_IS_TRUE(value
));
209 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "sub/abc", "bar"));
210 cl_assert(GIT_ATTR_IS_UNSPECIFIED(value
));
212 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "sub/abc", "baz"));
213 cl_assert(GIT_ATTR_IS_FALSE(value
));
215 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "sub/abc", "merge"));
216 cl_assert_equal_s("filfre", value
);
218 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "sub/abc", "frotz"));
219 cl_assert(GIT_ATTR_IS_UNSPECIFIED(value
));
222 #define CONTENT "I'm going to be dynamically processed\r\n" \
223 "And my line endings...\r\n" \
224 "...are going to be\n" \
227 #define GITATTR "* text=auto\n" \
231 static void add_to_workdir(const char *filename
, const char *content
)
233 git_str buf
= GIT_STR_INIT
;
235 cl_git_pass(git_str_joinpath(&buf
, "attr", filename
));
236 cl_git_rewritefile(git_str_cstr(&buf
), content
);
238 git_str_dispose(&buf
);
241 static void assert_proper_normalization(git_index
*index
, const char *filename
, const char *expected_sha
)
244 const git_index_entry
*entry
;
246 add_to_workdir(filename
, CONTENT
);
247 cl_git_pass(git_index_add_bypath(index
, filename
));
249 cl_assert(!git_index_find(&index_pos
, index
, filename
));
251 entry
= git_index_get_byindex(index
, index_pos
);
252 cl_assert_equal_i(0, git_oid_streq(&entry
->id
, expected_sha
));
255 void test_attr_repo__staging_properly_normalizes_line_endings_according_to_gitattributes_directives(void)
259 cl_git_pass(git_repository_index(&index
, g_repo
));
261 add_to_workdir(".gitattributes", GITATTR
);
263 assert_proper_normalization(index
, "text.txt", "22c74203bace3c2e950278c7ab08da0fca9f4e9b");
264 assert_proper_normalization(index
, "huh.dunno", "22c74203bace3c2e950278c7ab08da0fca9f4e9b");
265 assert_proper_normalization(index
, "binary.data", "66eeff1fcbacf589e6d70aa70edd3fce5be2b37c");
267 git_index_free(index
);
270 void test_attr_repo__bare_repo_with_index(void)
272 const char *names
[4] = { "test1", "test2", "test3", "test4" };
273 const char *values
[4];
276 cl_git_pass(git_repository_index(&index
, g_repo
));
279 "attr/.gitattributes",
280 "*.txt test1 test2=foobar -test3\n"
281 "trial.txt -test1 test2=barfoo !test3 test4\n");
282 cl_git_pass(git_index_add_bypath(index
, ".gitattributes"));
283 git_index_free(index
);
285 cl_must_pass(p_unlink("attr/.gitattributes"));
286 cl_assert(!git_fs_path_exists("attr/.gitattributes"));
288 cl_git_pass(git_repository_set_bare(g_repo
));
290 cl_git_pass(git_attr_get_many(values
, g_repo
, 0, "file.txt", 4, names
));
292 cl_assert(GIT_ATTR_IS_TRUE(values
[0]));
293 cl_assert_equal_s("foobar", values
[1]);
294 cl_assert(GIT_ATTR_IS_FALSE(values
[2]));
295 cl_assert(GIT_ATTR_IS_UNSPECIFIED(values
[3]));
297 cl_git_pass(git_attr_get_many(values
, g_repo
, 0, "trial.txt", 4, names
));
299 cl_assert(GIT_ATTR_IS_FALSE(values
[0]));
300 cl_assert_equal_s("barfoo", values
[1]);
301 cl_assert(GIT_ATTR_IS_UNSPECIFIED(values
[2]));
302 cl_assert(GIT_ATTR_IS_TRUE(values
[3]));
304 cl_git_pass(git_attr_get_many(values
, g_repo
, 0, "sub/sub/subdir.txt", 4, names
));
306 cl_assert(GIT_ATTR_IS_TRUE(values
[0]));
307 cl_assert_equal_s("foobar", values
[1]);
308 cl_assert(GIT_ATTR_IS_FALSE(values
[2]));
309 cl_assert(GIT_ATTR_IS_UNSPECIFIED(values
[3]));
312 void test_attr_repo__sysdir(void)
314 git_str sysdir
= GIT_STR_INIT
;
317 cl_git_pass(p_mkdir("system", 0777));
318 cl_git_rewritefile("system/gitattributes", "file merge=foo");
319 cl_git_pass(git_str_joinpath(&sysdir
, clar_sandbox_path(), "system"));
320 cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM
, sysdir
.ptr
));
321 g_repo
= cl_git_sandbox_reopen();
323 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "file", "merge"));
324 cl_assert_equal_s(value
, "foo");
326 cl_git_pass(p_unlink("system/gitattributes"));
327 cl_git_pass(p_rmdir("system"));
328 git_str_dispose(&sysdir
);
331 void test_attr_repo__sysdir_with_session(void)
333 const char *values
[2], *attrs
[2] = { "foo", "bar" };
334 git_str sysdir
= GIT_STR_INIT
;
335 git_attr_session session
;
337 cl_git_pass(p_mkdir("system", 0777));
338 cl_git_rewritefile("system/gitattributes", "file foo=1 bar=2");
339 cl_git_pass(git_str_joinpath(&sysdir
, clar_sandbox_path(), "system"));
340 cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM
, sysdir
.ptr
));
341 g_repo
= cl_git_sandbox_reopen();
343 cl_git_pass(git_attr_session__init(&session
, g_repo
));
344 cl_git_pass(git_attr_get_many_with_session(values
, g_repo
, &session
, NULL
, "file", ARRAY_SIZE(attrs
), attrs
));
346 cl_assert_equal_s(values
[0], "1");
347 cl_assert_equal_s(values
[1], "2");
349 cl_git_pass(p_unlink("system/gitattributes"));
350 cl_git_pass(p_rmdir("system"));
351 git_str_dispose(&sysdir
);
352 git_attr_session__free(&session
);
355 void test_attr_repo__rewrite(void)
359 cl_git_rewritefile("attr/.gitattributes", "file.txt foo=first\n");
360 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "file.txt", "foo"));
361 cl_assert_equal_s(value
, "first");
363 cl_git_rewritefile("attr/.gitattributes", "file.txt foo=second\n");
364 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "file.txt", "foo"));
365 cl_assert_equal_s(value
, "second");
367 cl_git_rewritefile("attr/.gitattributes", "file.txt other=value\n");
368 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "file.txt", "foo"));
369 cl_assert_equal_p(value
, NULL
);
372 void test_attr_repo__rewrite_sysdir(void)
374 git_str sysdir
= GIT_STR_INIT
;
377 cl_git_pass(p_mkdir("system", 0777));
378 cl_git_pass(git_str_joinpath(&sysdir
, clar_sandbox_path(), "system"));
379 cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM
, sysdir
.ptr
));
380 g_repo
= cl_git_sandbox_reopen();
382 cl_git_rewritefile("system/gitattributes", "file foo=first");
383 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "file", "foo"));
384 cl_assert_equal_s(value
, "first");
386 cl_git_rewritefile("system/gitattributes", "file foo=second");
387 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "file", "foo"));
388 cl_assert_equal_s(value
, "second");
390 git_str_dispose(&sysdir
);
393 void test_attr_repo__unlink(void)
397 cl_git_rewritefile("attr/.gitattributes", "file.txt foo=value1\n");
398 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "file.txt", "foo"));
399 cl_assert_equal_s(value
, "value1");
401 cl_git_pass(p_unlink("attr/.gitattributes"));
403 cl_git_pass(git_attr_get(&value
, g_repo
, 0, "file.txt", "foo"));
404 cl_assert_equal_p(value
, NULL
);