1 #include "clar_libgit2.h"
6 static git_repository
*g_repo
= NULL
;
8 void test_index_filemodes__initialize(void)
10 g_repo
= cl_git_sandbox_init("filemodes");
13 void test_index_filemodes__cleanup(void)
15 cl_git_sandbox_cleanup();
18 void test_index_filemodes__read(void)
22 static bool expected
[6] = { 0, 1, 0, 1, 0, 1 };
24 cl_git_pass(git_repository_index(&index
, g_repo
));
25 cl_assert_equal_i(6, (int)git_index_entrycount(index
));
27 for (i
= 0; i
< 6; ++i
) {
28 const git_index_entry
*entry
= git_index_get_byindex(index
, i
);
29 cl_assert(entry
!= NULL
);
30 cl_assert(((entry
->mode
& 0100) ? 1 : 0) == expected
[i
]);
33 git_index_free(index
);
36 static void replace_file_with_mode(
37 const char *filename
, const char *backup
, unsigned int create_mode
)
39 git_buf path
= GIT_BUF_INIT
, content
= GIT_BUF_INIT
;
41 cl_git_pass(git_buf_joinpath(&path
, "filemodes", filename
));
42 cl_git_pass(git_buf_printf(&content
, "%s as %08u (%d)",
43 filename
, create_mode
, rand()));
45 cl_git_pass(p_rename(path
.ptr
, backup
));
47 path
.ptr
, content
.ptr
, content
.size
,
48 O_WRONLY
|O_CREAT
|O_TRUNC
, create_mode
);
50 git_buf_dispose(&path
);
51 git_buf_dispose(&content
);
54 #define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__LINE__)
56 static void add_and_check_mode_(
57 git_index
*index
, const char *filename
, unsigned int expect_mode
,
58 const char *file
, int line
)
61 const git_index_entry
*entry
;
63 cl_git_pass(git_index_add_bypath(index
, filename
));
65 clar__assert(!git_index_find(&pos
, index
, filename
),
66 file
, line
, "Cannot find index entry", NULL
, 1);
68 entry
= git_index_get_byindex(index
, pos
);
70 clar__assert_equal(file
, line
, "Expected mode does not match index",
71 1, "%07o", (unsigned int)entry
->mode
, (unsigned int)expect_mode
);
74 void test_index_filemodes__untrusted(void)
78 cl_repo_set_bool(g_repo
, "core.filemode", false);
80 cl_git_pass(git_repository_index(&index
, g_repo
));
81 cl_assert((git_index_caps(index
) & GIT_INDEX_CAPABILITY_NO_FILEMODE
) != 0);
83 /* 1 - add 0644 over existing 0644 -> expect 0644 */
84 replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644);
85 add_and_check_mode(index
, "exec_off", GIT_FILEMODE_BLOB
);
87 /* 2 - add 0644 over existing 0755 -> expect 0755 */
88 replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644);
89 add_and_check_mode(index
, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE
);
91 /* 3 - add 0755 over existing 0644 -> expect 0644 */
92 replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755);
93 add_and_check_mode(index
, "exec_off", GIT_FILEMODE_BLOB
);
95 /* 4 - add 0755 over existing 0755 -> expect 0755 */
96 replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755);
97 add_and_check_mode(index
, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE
);
99 /* 5 - add new 0644 -> expect 0644 */
100 cl_git_write2file("filemodes/new_off", "blah", 0,
101 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
102 add_and_check_mode(index
, "new_off", GIT_FILEMODE_BLOB
);
104 /* 6 - add new 0755 -> expect 0644 if core.filemode == false */
105 cl_git_write2file("filemodes/new_on", "blah", 0,
106 O_WRONLY
| O_CREAT
| O_TRUNC
, 0755);
107 add_and_check_mode(index
, "new_on", GIT_FILEMODE_BLOB
);
109 git_index_free(index
);
112 void test_index_filemodes__trusted(void)
116 /* Only run these tests on platforms where I can actually
117 * chmod a file and get the stat results I expect!
119 if (!cl_is_chmod_supported())
122 cl_repo_set_bool(g_repo
, "core.filemode", true);
124 cl_git_pass(git_repository_index(&index
, g_repo
));
125 cl_assert((git_index_caps(index
) & GIT_INDEX_CAPABILITY_NO_FILEMODE
) == 0);
127 /* 1 - add 0644 over existing 0644 -> expect 0644 */
128 replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644);
129 add_and_check_mode(index
, "exec_off", GIT_FILEMODE_BLOB
);
131 /* 2 - add 0644 over existing 0755 -> expect 0644 */
132 replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644);
133 add_and_check_mode(index
, "exec_on", GIT_FILEMODE_BLOB
);
135 /* 3 - add 0755 over existing 0644 -> expect 0755 */
136 replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755);
137 add_and_check_mode(index
, "exec_off", GIT_FILEMODE_BLOB_EXECUTABLE
);
139 /* 4 - add 0755 over existing 0755 -> expect 0755 */
140 replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755);
141 add_and_check_mode(index
, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE
);
143 /* 5 - add new 0644 -> expect 0644 */
144 cl_git_write2file("filemodes/new_off", "blah", 0,
145 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
146 add_and_check_mode(index
, "new_off", GIT_FILEMODE_BLOB
);
148 /* 6 - add 0755 -> expect 0755 */
149 cl_git_write2file("filemodes/new_on", "blah", 0,
150 O_WRONLY
| O_CREAT
| O_TRUNC
, 0755);
151 add_and_check_mode(index
, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE
);
153 git_index_free(index
);
156 #define add_entry_and_check_mode(I,FF,X) add_entry_and_check_mode_(I,FF,X,__FILE__,__LINE__)
158 static void add_entry_and_check_mode_(
159 git_index
*index
, bool from_file
, git_filemode_t mode
,
160 const char *file
, int line
)
163 const git_index_entry
* entry
;
164 git_index_entry new_entry
;
166 /* If old_filename exists, we copy that to the new file, and test
167 * git_index_add(), otherwise create a new entry testing git_index_add_frombuffer
171 clar__assert(!git_index_find(&pos
, index
, "exec_off"),
172 file
, line
, "Cannot find original index entry", NULL
, 1);
174 entry
= git_index_get_byindex(index
, pos
);
176 memcpy(&new_entry
, entry
, sizeof(new_entry
));
179 memset(&new_entry
, 0x0, sizeof(git_index_entry
));
181 new_entry
.path
= "filemodes/explicit_test";
182 new_entry
.mode
= mode
;
186 clar__assert(!git_index_add(index
, &new_entry
),
187 file
, line
, "Cannot add index entry", NULL
, 1);
191 const char *content
= "hey there\n";
192 clar__assert(!git_index_add_frombuffer(index
, &new_entry
, content
, strlen(content
)),
193 file
, line
, "Cannot add index entry from buffer", NULL
, 1);
196 clar__assert(!git_index_find(&pos
, index
, "filemodes/explicit_test"),
197 file
, line
, "Cannot find new index entry", NULL
, 1);
199 entry
= git_index_get_byindex(index
, pos
);
201 clar__assert_equal(file
, line
, "Expected mode does not match index",
202 1, "%07o", (unsigned int)entry
->mode
, (unsigned int)mode
);
205 void test_index_filemodes__explicit(void)
209 /* These tests should run and work everywhere, as the filemode is
210 * given explicitly to git_index_add or git_index_add_frombuffer
212 cl_repo_set_bool(g_repo
, "core.filemode", false);
214 cl_git_pass(git_repository_index(&index
, g_repo
));
216 /* Each of these tests keeps overwriting the same file in the index. */
217 /* 1 - add new 0644 entry */
218 add_entry_and_check_mode(index
, true, GIT_FILEMODE_BLOB
);
220 /* 2 - add 0755 entry over existing 0644 */
221 add_entry_and_check_mode(index
, true, GIT_FILEMODE_BLOB_EXECUTABLE
);
223 /* 3 - add 0644 entry over existing 0755 */
224 add_entry_and_check_mode(index
, true, GIT_FILEMODE_BLOB
);
226 /* 4 - add 0755 buffer entry over existing 0644 */
227 add_entry_and_check_mode(index
, false, GIT_FILEMODE_BLOB_EXECUTABLE
);
229 /* 5 - add 0644 buffer entry over existing 0755 */
230 add_entry_and_check_mode(index
, false, GIT_FILEMODE_BLOB
);
232 git_index_free(index
);
235 void test_index_filemodes__invalid(void)
238 git_index_entry entry
;
239 const git_index_entry
*dummy
;
241 cl_git_pass(git_repository_index(&index
, g_repo
));
243 /* add a dummy file so that we have a valid id */
244 cl_git_mkfile("./filemodes/dummy-file.txt", "new-file\n");
245 cl_git_pass(git_index_add_bypath(index
, "dummy-file.txt"));
246 cl_assert((dummy
= git_index_get_bypath(index
, "dummy-file.txt", 0)));
248 GIT_INDEX_ENTRY_STAGE_SET(&entry
, 0);
250 entry
.mode
= GIT_OBJECT_BLOB
;
251 git_oid_cpy(&entry
.id
, &dummy
->id
);
252 cl_git_fail(git_index_add(index
, &entry
));
254 entry
.mode
= GIT_FILEMODE_BLOB
;
255 cl_git_pass(git_index_add(index
, &entry
));
257 git_index_free(index
);
260 void test_index_filemodes__frombuffer_requires_files(void)
263 git_index_entry new_entry
;
264 const git_index_entry
*ret_entry
;
265 const char *content
= "hey there\n";
267 memset(&new_entry
, 0, sizeof(new_entry
));
268 cl_git_pass(git_repository_index(&index
, g_repo
));
271 new_entry
.path
= "dummy-file.txt";
272 new_entry
.mode
= GIT_FILEMODE_BLOB
;
274 cl_git_pass(git_index_add_frombuffer(index
,
275 &new_entry
, content
, strlen(content
)));
277 cl_assert((ret_entry
= git_index_get_bypath(index
, "dummy-file.txt", 0)));
278 cl_assert_equal_s("dummy-file.txt", ret_entry
->path
);
279 cl_assert_equal_i(GIT_FILEMODE_BLOB
, ret_entry
->mode
);
281 /* executable blob */
282 new_entry
.path
= "dummy-file.txt";
283 new_entry
.mode
= GIT_FILEMODE_BLOB_EXECUTABLE
;
285 cl_git_pass(git_index_add_frombuffer(index
,
286 &new_entry
, content
, strlen(content
)));
288 cl_assert((ret_entry
= git_index_get_bypath(index
, "dummy-file.txt", 0)));
289 cl_assert_equal_s("dummy-file.txt", ret_entry
->path
);
290 cl_assert_equal_i(GIT_FILEMODE_BLOB_EXECUTABLE
, ret_entry
->mode
);
292 /* links are also acceptable */
293 new_entry
.path
= "dummy-link.txt";
294 new_entry
.mode
= GIT_FILEMODE_LINK
;
296 cl_git_pass(git_index_add_frombuffer(index
,
297 &new_entry
, content
, strlen(content
)));
299 cl_assert((ret_entry
= git_index_get_bypath(index
, "dummy-link.txt", 0)));
300 cl_assert_equal_s("dummy-link.txt", ret_entry
->path
);
301 cl_assert_equal_i(GIT_FILEMODE_LINK
, ret_entry
->mode
);
303 /* trees are rejected */
304 new_entry
.path
= "invalid_mode.txt";
305 new_entry
.mode
= GIT_FILEMODE_TREE
;
307 cl_git_fail(git_index_add_frombuffer(index
,
308 &new_entry
, content
, strlen(content
)));
309 cl_assert_equal_p(NULL
, git_index_get_bypath(index
, "invalid_mode.txt", 0));
311 /* submodules are rejected */
312 new_entry
.path
= "invalid_mode.txt";
313 new_entry
.mode
= GIT_FILEMODE_COMMIT
;
315 cl_git_fail(git_index_add_frombuffer(index
,
316 &new_entry
, content
, strlen(content
)));
317 cl_assert_equal_p(NULL
, git_index_get_bypath(index
, "invalid_mode.txt", 0));
319 git_index_free(index
);