1 #include "clar_libgit2.h"
5 static git_repository
*g_repo
= NULL
;
7 void test_index_filemodes__initialize(void)
9 g_repo
= cl_git_sandbox_init("filemodes");
12 void test_index_filemodes__cleanup(void)
14 cl_git_sandbox_cleanup();
17 void test_index_filemodes__read(void)
21 static bool expected
[6] = { 0, 1, 0, 1, 0, 1 };
23 cl_git_pass(git_repository_index(&index
, g_repo
));
24 cl_assert_equal_i(6, (int)git_index_entrycount(index
));
26 for (i
= 0; i
< 6; ++i
) {
27 const git_index_entry
*entry
= git_index_get_byindex(index
, i
);
28 cl_assert(entry
!= NULL
);
29 cl_assert(((entry
->mode
& 0100) ? 1 : 0) == expected
[i
]);
32 git_index_free(index
);
35 static void replace_file_with_mode(
36 const char *filename
, const char *backup
, unsigned int create_mode
)
38 git_str path
= GIT_STR_INIT
, content
= GIT_STR_INIT
;
40 cl_git_pass(git_str_joinpath(&path
, "filemodes", filename
));
41 cl_git_pass(git_str_printf(&content
, "%s as %08u (%d)",
42 filename
, create_mode
, rand()));
44 cl_git_pass(p_rename(path
.ptr
, backup
));
46 path
.ptr
, content
.ptr
, content
.size
,
47 O_WRONLY
|O_CREAT
|O_TRUNC
, create_mode
);
49 git_str_dispose(&path
);
50 git_str_dispose(&content
);
53 #define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__func__,__LINE__)
55 static void add_and_check_mode_(
56 git_index
*index
, const char *filename
, unsigned int expect_mode
,
57 const char *file
, const char *func
, int line
)
60 const git_index_entry
*entry
;
62 cl_git_pass(git_index_add_bypath(index
, filename
));
64 clar__assert(!git_index_find(&pos
, index
, filename
),
65 file
, func
, line
, "Cannot find index entry", NULL
, 1);
67 entry
= git_index_get_byindex(index
, pos
);
69 clar__assert_equal(file
, func
, line
, "Expected mode does not match index",
70 1, "%07o", (unsigned int)entry
->mode
, (unsigned int)expect_mode
);
73 void test_index_filemodes__untrusted(void)
77 cl_repo_set_bool(g_repo
, "core.filemode", false);
79 cl_git_pass(git_repository_index(&index
, g_repo
));
80 cl_assert((git_index_caps(index
) & GIT_INDEX_CAPABILITY_NO_FILEMODE
) != 0);
82 /* 1 - add 0644 over existing 0644 -> expect 0644 */
83 replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644);
84 add_and_check_mode(index
, "exec_off", GIT_FILEMODE_BLOB
);
86 /* 2 - add 0644 over existing 0755 -> expect 0755 */
87 replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644);
88 add_and_check_mode(index
, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE
);
90 /* 3 - add 0755 over existing 0644 -> expect 0644 */
91 replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755);
92 add_and_check_mode(index
, "exec_off", GIT_FILEMODE_BLOB
);
94 /* 4 - add 0755 over existing 0755 -> expect 0755 */
95 replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755);
96 add_and_check_mode(index
, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE
);
98 /* 5 - add new 0644 -> expect 0644 */
99 cl_git_write2file("filemodes/new_off", "blah", 0,
100 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
101 add_and_check_mode(index
, "new_off", GIT_FILEMODE_BLOB
);
103 /* 6 - add new 0755 -> expect 0644 if core.filemode == false */
104 cl_git_write2file("filemodes/new_on", "blah", 0,
105 O_WRONLY
| O_CREAT
| O_TRUNC
, 0755);
106 add_and_check_mode(index
, "new_on", GIT_FILEMODE_BLOB
);
108 git_index_free(index
);
111 void test_index_filemodes__trusted(void)
115 /* Only run these tests on platforms where I can actually
116 * chmod a file and get the stat results I expect!
118 if (!cl_is_chmod_supported())
121 cl_repo_set_bool(g_repo
, "core.filemode", true);
123 cl_git_pass(git_repository_index(&index
, g_repo
));
124 cl_assert((git_index_caps(index
) & GIT_INDEX_CAPABILITY_NO_FILEMODE
) == 0);
126 /* 1 - add 0644 over existing 0644 -> expect 0644 */
127 replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644);
128 add_and_check_mode(index
, "exec_off", GIT_FILEMODE_BLOB
);
130 /* 2 - add 0644 over existing 0755 -> expect 0644 */
131 replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644);
132 add_and_check_mode(index
, "exec_on", GIT_FILEMODE_BLOB
);
134 /* 3 - add 0755 over existing 0644 -> expect 0755 */
135 replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755);
136 add_and_check_mode(index
, "exec_off", GIT_FILEMODE_BLOB_EXECUTABLE
);
138 /* 4 - add 0755 over existing 0755 -> expect 0755 */
139 replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755);
140 add_and_check_mode(index
, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE
);
142 /* 5 - add new 0644 -> expect 0644 */
143 cl_git_write2file("filemodes/new_off", "blah", 0,
144 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
145 add_and_check_mode(index
, "new_off", GIT_FILEMODE_BLOB
);
147 /* 6 - add 0755 -> expect 0755 */
148 cl_git_write2file("filemodes/new_on", "blah", 0,
149 O_WRONLY
| O_CREAT
| O_TRUNC
, 0755);
150 add_and_check_mode(index
, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE
);
152 git_index_free(index
);
155 #define add_entry_and_check_mode(I,FF,X) add_entry_and_check_mode_(I,FF,X,__FILE__,__func__,__LINE__)
157 static void add_entry_and_check_mode_(
158 git_index
*index
, bool from_file
, git_filemode_t mode
,
159 const char *file
, const char *func
, int line
)
162 const git_index_entry
* entry
;
163 git_index_entry new_entry
;
165 /* If old_filename exists, we copy that to the new file, and test
166 * git_index_add(), otherwise create a new entry testing git_index_add_from_buffer
170 clar__assert(!git_index_find(&pos
, index
, "exec_off"),
171 file
, func
, line
, "Cannot find original index entry", NULL
, 1);
173 entry
= git_index_get_byindex(index
, pos
);
175 memcpy(&new_entry
, entry
, sizeof(new_entry
));
178 memset(&new_entry
, 0x0, sizeof(git_index_entry
));
180 new_entry
.path
= "filemodes/explicit_test";
181 new_entry
.mode
= mode
;
185 clar__assert(!git_index_add(index
, &new_entry
),
186 file
, func
, line
, "Cannot add index entry", NULL
, 1);
190 const char *content
= "hey there\n";
191 clar__assert(!git_index_add_from_buffer(index
, &new_entry
, content
, strlen(content
)),
192 file
, func
, line
, "Cannot add index entry from buffer", NULL
, 1);
195 clar__assert(!git_index_find(&pos
, index
, "filemodes/explicit_test"),
196 file
, func
, line
, "Cannot find new index entry", NULL
, 1);
198 entry
= git_index_get_byindex(index
, pos
);
200 clar__assert_equal(file
, func
, line
, "Expected mode does not match index",
201 1, "%07o", (unsigned int)entry
->mode
, (unsigned int)mode
);
204 void test_index_filemodes__explicit(void)
208 /* These tests should run and work everywhere, as the filemode is
209 * given explicitly to git_index_add or git_index_add_from_buffer
211 cl_repo_set_bool(g_repo
, "core.filemode", false);
213 cl_git_pass(git_repository_index(&index
, g_repo
));
215 /* Each of these tests keeps overwriting the same file in the index. */
216 /* 1 - add new 0644 entry */
217 add_entry_and_check_mode(index
, true, GIT_FILEMODE_BLOB
);
219 /* 2 - add 0755 entry over existing 0644 */
220 add_entry_and_check_mode(index
, true, GIT_FILEMODE_BLOB_EXECUTABLE
);
222 /* 3 - add 0644 entry over existing 0755 */
223 add_entry_and_check_mode(index
, true, GIT_FILEMODE_BLOB
);
225 /* 4 - add 0755 buffer entry over existing 0644 */
226 add_entry_and_check_mode(index
, false, GIT_FILEMODE_BLOB_EXECUTABLE
);
228 /* 5 - add 0644 buffer entry over existing 0755 */
229 add_entry_and_check_mode(index
, false, GIT_FILEMODE_BLOB
);
231 git_index_free(index
);
234 void test_index_filemodes__invalid(void)
237 git_index_entry entry
;
238 const git_index_entry
*dummy
;
240 cl_git_pass(git_repository_index(&index
, g_repo
));
242 /* add a dummy file so that we have a valid id */
243 cl_git_mkfile("./filemodes/dummy-file.txt", "new-file\n");
244 cl_git_pass(git_index_add_bypath(index
, "dummy-file.txt"));
245 cl_assert((dummy
= git_index_get_bypath(index
, "dummy-file.txt", 0)));
247 GIT_INDEX_ENTRY_STAGE_SET(&entry
, 0);
249 entry
.mode
= GIT_OBJECT_BLOB
;
250 git_oid_cpy(&entry
.id
, &dummy
->id
);
251 cl_git_fail(git_index_add(index
, &entry
));
253 entry
.mode
= GIT_FILEMODE_BLOB
;
254 cl_git_pass(git_index_add(index
, &entry
));
256 git_index_free(index
);
259 void test_index_filemodes__frombuffer_requires_files(void)
262 git_index_entry new_entry
;
263 const git_index_entry
*ret_entry
;
264 const char *content
= "hey there\n";
266 memset(&new_entry
, 0, sizeof(new_entry
));
267 cl_git_pass(git_repository_index(&index
, g_repo
));
270 new_entry
.path
= "dummy-file.txt";
271 new_entry
.mode
= GIT_FILEMODE_BLOB
;
273 cl_git_pass(git_index_add_from_buffer(index
,
274 &new_entry
, content
, strlen(content
)));
276 cl_assert((ret_entry
= git_index_get_bypath(index
, "dummy-file.txt", 0)));
277 cl_assert_equal_s("dummy-file.txt", ret_entry
->path
);
278 cl_assert_equal_i(GIT_FILEMODE_BLOB
, ret_entry
->mode
);
280 /* executable blob */
281 new_entry
.path
= "dummy-file.txt";
282 new_entry
.mode
= GIT_FILEMODE_BLOB_EXECUTABLE
;
284 cl_git_pass(git_index_add_from_buffer(index
,
285 &new_entry
, content
, strlen(content
)));
287 cl_assert((ret_entry
= git_index_get_bypath(index
, "dummy-file.txt", 0)));
288 cl_assert_equal_s("dummy-file.txt", ret_entry
->path
);
289 cl_assert_equal_i(GIT_FILEMODE_BLOB_EXECUTABLE
, ret_entry
->mode
);
291 /* links are also acceptable */
292 new_entry
.path
= "dummy-link.txt";
293 new_entry
.mode
= GIT_FILEMODE_LINK
;
295 cl_git_pass(git_index_add_from_buffer(index
,
296 &new_entry
, content
, strlen(content
)));
298 cl_assert((ret_entry
= git_index_get_bypath(index
, "dummy-link.txt", 0)));
299 cl_assert_equal_s("dummy-link.txt", ret_entry
->path
);
300 cl_assert_equal_i(GIT_FILEMODE_LINK
, ret_entry
->mode
);
302 /* trees are rejected */
303 new_entry
.path
= "invalid_mode.txt";
304 new_entry
.mode
= GIT_FILEMODE_TREE
;
306 cl_git_fail(git_index_add_from_buffer(index
,
307 &new_entry
, content
, strlen(content
)));
308 cl_assert_equal_p(NULL
, git_index_get_bypath(index
, "invalid_mode.txt", 0));
310 /* submodules are rejected */
311 new_entry
.path
= "invalid_mode.txt";
312 new_entry
.mode
= GIT_FILEMODE_COMMIT
;
314 cl_git_fail(git_index_add_from_buffer(index
,
315 &new_entry
, content
, strlen(content
)));
316 cl_assert_equal_p(NULL
, git_index_get_bypath(index
, "invalid_mode.txt", 0));
318 git_index_free(index
);