]>
Commit | Line | Data |
---|---|---|
aa13bf05 RB |
1 | #include "clar_libgit2.h" |
2 | #include "posix.h" | |
3 | #include "path.h" | |
4 | #include "submodule_helpers.h" | |
22a2d3d5 | 5 | #include "futils.h" |
65025cb8 | 6 | #include "iterator.h" |
aa13bf05 RB |
7 | |
8 | static git_repository *g_repo = NULL; | |
9 | ||
10 | void test_submodule_status__initialize(void) | |
11 | { | |
125655fe | 12 | g_repo = setup_fixture_submod2(); |
aa13bf05 RB |
13 | } |
14 | ||
15 | void test_submodule_status__cleanup(void) | |
16 | { | |
aa13bf05 RB |
17 | } |
18 | ||
19 | void test_submodule_status__unchanged(void) | |
20 | { | |
a15c7802 RB |
21 | unsigned int status = get_submodule_status(g_repo, "sm_unchanged"); |
22 | unsigned int expected = | |
23 | GIT_SUBMODULE_STATUS_IN_HEAD | | |
5f4a61ae RB |
24 | GIT_SUBMODULE_STATUS_IN_INDEX | |
25 | GIT_SUBMODULE_STATUS_IN_CONFIG | | |
26 | GIT_SUBMODULE_STATUS_IN_WD; | |
27 | ||
a15c7802 RB |
28 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
29 | cl_assert(expected == status); | |
30 | } | |
31 | ||
32 | static void rm_submodule(const char *name) | |
33 | { | |
e579e0f7 MB |
34 | git_str path = GIT_STR_INIT; |
35 | cl_git_pass(git_str_joinpath(&path, git_repository_workdir(g_repo), name)); | |
a15c7802 | 36 | cl_git_pass(git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)); |
e579e0f7 | 37 | git_str_dispose(&path); |
a15c7802 RB |
38 | } |
39 | ||
40 | static void add_submodule_to_index(const char *name) | |
41 | { | |
42 | git_submodule *sm; | |
43 | cl_git_pass(git_submodule_lookup(&sm, g_repo, name)); | |
44 | cl_git_pass(git_submodule_add_to_index(sm, true)); | |
45 | git_submodule_free(sm); | |
46 | } | |
47 | ||
48 | static void rm_submodule_from_index(const char *name) | |
49 | { | |
50 | git_index *index; | |
51 | size_t pos; | |
52 | ||
53 | cl_git_pass(git_repository_index(&index, g_repo)); | |
54 | cl_assert(!git_index_find(&pos, index, name)); | |
55 | cl_git_pass(git_index_remove(index, name, 0)); | |
56 | cl_git_pass(git_index_write(index)); | |
57 | git_index_free(index); | |
aa13bf05 RB |
58 | } |
59 | ||
5f4a61ae RB |
60 | /* 4 values of GIT_SUBMODULE_IGNORE to check */ |
61 | ||
62 | void test_submodule_status__ignore_none(void) | |
aa13bf05 | 63 | { |
5f4a61ae | 64 | unsigned int status; |
5f4a61ae | 65 | |
a15c7802 | 66 | rm_submodule("sm_unchanged"); |
5f4a61ae | 67 | |
a15c7802 RB |
68 | refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); |
69 | refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); | |
70 | refute_submodule_exists(g_repo, "not", GIT_EEXISTS); | |
5f4a61ae | 71 | |
a15c7802 | 72 | status = get_submodule_status(g_repo, "sm_changed_index"); |
5f4a61ae RB |
73 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0); |
74 | ||
a15c7802 | 75 | status = get_submodule_status(g_repo, "sm_changed_head"); |
5f4a61ae RB |
76 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); |
77 | ||
a15c7802 | 78 | status = get_submodule_status(g_repo, "sm_changed_file"); |
5f4a61ae RB |
79 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0); |
80 | ||
a15c7802 | 81 | status = get_submodule_status(g_repo, "sm_changed_untracked_file"); |
5f4a61ae RB |
82 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNTRACKED) != 0); |
83 | ||
a15c7802 | 84 | status = get_submodule_status(g_repo, "sm_missing_commits"); |
5f4a61ae RB |
85 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); |
86 | ||
a15c7802 | 87 | status = get_submodule_status(g_repo, "sm_added_and_uncommited"); |
5f4a61ae RB |
88 | cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); |
89 | ||
90 | /* removed sm_unchanged for deleted workdir */ | |
a15c7802 | 91 | status = get_submodule_status(g_repo, "sm_unchanged"); |
5f4a61ae RB |
92 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); |
93 | ||
94 | /* now mkdir sm_unchanged to test uninitialized */ | |
ac2fba0e | 95 | cl_git_pass(git_futils_mkdir_relative("sm_unchanged", "submod2", 0755, 0, NULL)); |
a15c7802 | 96 | status = get_submodule_status(g_repo, "sm_unchanged"); |
5f4a61ae RB |
97 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); |
98 | ||
99 | /* update sm_changed_head in index */ | |
a15c7802 RB |
100 | add_submodule_to_index("sm_changed_head"); |
101 | status = get_submodule_status(g_repo, "sm_changed_head"); | |
5f4a61ae RB |
102 | cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); |
103 | ||
104 | /* remove sm_changed_head from index */ | |
a15c7802 RB |
105 | rm_submodule_from_index("sm_changed_head"); |
106 | status = get_submodule_status(g_repo, "sm_changed_head"); | |
5f4a61ae | 107 | cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_DELETED) != 0); |
aa13bf05 RB |
108 | } |
109 | ||
5f4a61ae RB |
110 | void test_submodule_status__ignore_untracked(void) |
111 | { | |
112 | unsigned int status; | |
5f4a61ae RB |
113 | git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_UNTRACKED; |
114 | ||
a15c7802 | 115 | rm_submodule("sm_unchanged"); |
5f4a61ae | 116 | |
a15c7802 RB |
117 | refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); |
118 | refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); | |
119 | refute_submodule_exists(g_repo, "not", GIT_EEXISTS); | |
5f4a61ae | 120 | |
c6f489c9 | 121 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_index", ign)); |
5f4a61ae RB |
122 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0); |
123 | ||
c6f489c9 | 124 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_head", ign)); |
5f4a61ae RB |
125 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); |
126 | ||
c6f489c9 | 127 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_file", ign)); |
5f4a61ae RB |
128 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0); |
129 | ||
c6f489c9 | 130 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_untracked_file", ign)); |
5f4a61ae RB |
131 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
132 | ||
c6f489c9 | 133 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_missing_commits", ign)); |
5f4a61ae RB |
134 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); |
135 | ||
c6f489c9 | 136 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_added_and_uncommited", ign)); |
5f4a61ae RB |
137 | cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); |
138 | ||
139 | /* removed sm_unchanged for deleted workdir */ | |
c6f489c9 | 140 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_unchanged", ign)); |
5f4a61ae RB |
141 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); |
142 | ||
143 | /* now mkdir sm_unchanged to test uninitialized */ | |
ac2fba0e | 144 | cl_git_pass(git_futils_mkdir_relative("sm_unchanged", "submod2", 0755, 0, NULL)); |
c6f489c9 | 145 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_unchanged", ign)); |
5f4a61ae RB |
146 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); |
147 | ||
148 | /* update sm_changed_head in index */ | |
a15c7802 | 149 | add_submodule_to_index("sm_changed_head"); |
c6f489c9 | 150 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_head", ign)); |
5f4a61ae | 151 | cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); |
5f4a61ae RB |
152 | } |
153 | ||
154 | void test_submodule_status__ignore_dirty(void) | |
155 | { | |
156 | unsigned int status; | |
5f4a61ae RB |
157 | git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_DIRTY; |
158 | ||
a15c7802 | 159 | rm_submodule("sm_unchanged"); |
5f4a61ae | 160 | |
a15c7802 RB |
161 | refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); |
162 | refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); | |
163 | refute_submodule_exists(g_repo, "not", GIT_EEXISTS); | |
5f4a61ae | 164 | |
c6f489c9 | 165 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_index", ign)); |
5f4a61ae RB |
166 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
167 | ||
c6f489c9 | 168 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_head", ign)); |
5f4a61ae RB |
169 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); |
170 | ||
c6f489c9 | 171 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_file", ign)); |
5f4a61ae RB |
172 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
173 | ||
c6f489c9 | 174 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_untracked_file", ign)); |
5f4a61ae RB |
175 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
176 | ||
c6f489c9 | 177 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_missing_commits", ign)); |
5f4a61ae RB |
178 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); |
179 | ||
c6f489c9 | 180 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_added_and_uncommited", ign)); |
5f4a61ae RB |
181 | cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); |
182 | ||
183 | /* removed sm_unchanged for deleted workdir */ | |
c6f489c9 | 184 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_unchanged", ign)); |
5f4a61ae RB |
185 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); |
186 | ||
187 | /* now mkdir sm_unchanged to test uninitialized */ | |
ac2fba0e | 188 | cl_git_pass(git_futils_mkdir_relative("sm_unchanged", "submod2", 0755, 0, NULL)); |
c6f489c9 | 189 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_unchanged", ign)); |
5f4a61ae RB |
190 | cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); |
191 | ||
192 | /* update sm_changed_head in index */ | |
a15c7802 | 193 | add_submodule_to_index("sm_changed_head"); |
c6f489c9 | 194 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_head", ign)); |
5f4a61ae | 195 | cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); |
5f4a61ae RB |
196 | } |
197 | ||
198 | void test_submodule_status__ignore_all(void) | |
199 | { | |
200 | unsigned int status; | |
5f4a61ae RB |
201 | git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_ALL; |
202 | ||
a15c7802 | 203 | rm_submodule("sm_unchanged"); |
5f4a61ae | 204 | |
a15c7802 RB |
205 | refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); |
206 | refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); | |
207 | refute_submodule_exists(g_repo, "not", GIT_EEXISTS); | |
5f4a61ae | 208 | |
c6f489c9 | 209 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_index", ign)); |
5f4a61ae RB |
210 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
211 | ||
c6f489c9 | 212 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_head", ign)); |
5f4a61ae RB |
213 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
214 | ||
c6f489c9 | 215 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_file", ign)); |
5f4a61ae RB |
216 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
217 | ||
c6f489c9 | 218 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_untracked_file", ign)); |
5f4a61ae RB |
219 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
220 | ||
c6f489c9 | 221 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_missing_commits", ign)); |
5f4a61ae RB |
222 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
223 | ||
c6f489c9 | 224 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_added_and_uncommited", ign)); |
5f4a61ae RB |
225 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
226 | ||
227 | /* removed sm_unchanged for deleted workdir */ | |
c6f489c9 | 228 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_unchanged", ign)); |
5f4a61ae RB |
229 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
230 | ||
231 | /* now mkdir sm_unchanged to test uninitialized */ | |
ac2fba0e | 232 | cl_git_pass(git_futils_mkdir_relative("sm_unchanged", "submod2", 0755, 0, NULL)); |
c6f489c9 | 233 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_unchanged", ign)); |
5f4a61ae RB |
234 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
235 | ||
236 | /* update sm_changed_head in index */ | |
a15c7802 | 237 | add_submodule_to_index("sm_changed_head"); |
c6f489c9 | 238 | cl_git_pass(git_submodule_status(&status, g_repo,"sm_changed_head", ign)); |
5f4a61ae | 239 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
5f4a61ae | 240 | } |
65025cb8 RB |
241 | |
242 | typedef struct { | |
243 | size_t counter; | |
244 | const char **paths; | |
125655fe | 245 | int *statuses; |
65025cb8 RB |
246 | } submodule_expectations; |
247 | ||
248 | static int confirm_submodule_status( | |
249 | const char *path, unsigned int status_flags, void *payload) | |
250 | { | |
251 | submodule_expectations *exp = payload; | |
252 | ||
d3bc95fd | 253 | while (exp->statuses[exp->counter] < 0) |
65025cb8 RB |
254 | exp->counter++; |
255 | ||
125655fe | 256 | cl_assert_equal_i(exp->statuses[exp->counter], (int)status_flags); |
65025cb8 RB |
257 | cl_assert_equal_s(exp->paths[exp->counter++], path); |
258 | ||
259 | GIT_UNUSED(status_flags); | |
260 | ||
261 | return 0; | |
262 | } | |
263 | ||
264 | void test_submodule_status__iterator(void) | |
265 | { | |
266 | git_iterator *iter; | |
ed1c6446 | 267 | git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT; |
65025cb8 RB |
268 | const git_index_entry *entry; |
269 | size_t i; | |
270 | static const char *expected[] = { | |
271 | ".gitmodules", | |
272 | "just_a_dir/", | |
273 | "just_a_dir/contents", | |
274 | "just_a_file", | |
d3bc95fd RB |
275 | "not-submodule/", |
276 | "not-submodule/README.txt", | |
277 | "not/", | |
278 | "not/README.txt", | |
65025cb8 RB |
279 | "README.txt", |
280 | "sm_added_and_uncommited", | |
281 | "sm_changed_file", | |
282 | "sm_changed_head", | |
283 | "sm_changed_index", | |
284 | "sm_changed_untracked_file", | |
285 | "sm_missing_commits", | |
286 | "sm_unchanged", | |
287 | NULL | |
288 | }; | |
125655fe RB |
289 | static int expected_flags[] = { |
290 | GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED, /* ".gitmodules" */ | |
d3bc95fd | 291 | -1, /* "just_a_dir/" will be skipped */ |
125655fe RB |
292 | GIT_STATUS_CURRENT, /* "just_a_dir/contents" */ |
293 | GIT_STATUS_CURRENT, /* "just_a_file" */ | |
d3bc95fd RB |
294 | GIT_STATUS_WT_NEW, /* "not-submodule/" untracked item */ |
295 | -1, /* "not-submodule/README.txt" */ | |
296 | GIT_STATUS_WT_NEW, /* "not/" untracked item */ | |
297 | -1, /* "not/README.txt" */ | |
125655fe RB |
298 | GIT_STATUS_CURRENT, /* "README.txt */ |
299 | GIT_STATUS_INDEX_NEW, /* "sm_added_and_uncommited" */ | |
300 | GIT_STATUS_WT_MODIFIED, /* "sm_changed_file" */ | |
301 | GIT_STATUS_WT_MODIFIED, /* "sm_changed_head" */ | |
302 | GIT_STATUS_WT_MODIFIED, /* "sm_changed_index" */ | |
303 | GIT_STATUS_WT_MODIFIED, /* "sm_changed_untracked_file" */ | |
304 | GIT_STATUS_WT_MODIFIED, /* "sm_missing_commits" */ | |
305 | GIT_STATUS_CURRENT, /* "sm_unchanged" */ | |
306 | 0 | |
307 | }; | |
308 | submodule_expectations exp = { 0, expected, expected_flags }; | |
65025cb8 | 309 | git_status_options opts = GIT_STATUS_OPTIONS_INIT; |
62a617dc | 310 | git_index *index; |
65025cb8 | 311 | |
ed1c6446 ET |
312 | iter_opts.flags = GIT_ITERATOR_IGNORE_CASE | GIT_ITERATOR_INCLUDE_TREES; |
313 | ||
62a617dc | 314 | cl_git_pass(git_repository_index(&index, g_repo)); |
ed1c6446 | 315 | cl_git_pass(git_iterator_for_workdir(&iter, g_repo, index, NULL, &iter_opts)); |
65025cb8 | 316 | |
cee695ae | 317 | for (i = 0; !git_iterator_advance(&entry, iter); ++i) |
65025cb8 | 318 | cl_assert_equal_s(expected[i], entry->path); |
65025cb8 RB |
319 | |
320 | git_iterator_free(iter); | |
62a617dc | 321 | git_index_free(index); |
65025cb8 | 322 | |
351888cf RB |
323 | opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | |
324 | GIT_STATUS_OPT_INCLUDE_UNMODIFIED | | |
125655fe | 325 | GIT_STATUS_OPT_INCLUDE_IGNORED | |
d5e83627 RB |
326 | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS | |
327 | GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY; | |
65025cb8 | 328 | |
351888cf RB |
329 | cl_git_pass(git_status_foreach_ext( |
330 | g_repo, &opts, confirm_submodule_status, &exp)); | |
65025cb8 | 331 | } |
e26b14c0 RB |
332 | |
333 | void test_submodule_status__untracked_dirs_containing_ignored_files(void) | |
334 | { | |
e26b14c0 | 335 | unsigned int status, expected; |
e26b14c0 | 336 | |
a15c7802 RB |
337 | cl_git_append2file( |
338 | "submod2/.git/modules/sm_unchanged/info/exclude", "\n*.ignored\n"); | |
e26b14c0 | 339 | |
a15c7802 | 340 | cl_git_pass( |
ac2fba0e | 341 | git_futils_mkdir_relative("sm_unchanged/directory", "submod2", 0755, 0, NULL)); |
a15c7802 RB |
342 | cl_git_mkfile( |
343 | "submod2/sm_unchanged/directory/i_am.ignored", | |
344 | "ignore this file, please\n"); | |
e26b14c0 | 345 | |
a15c7802 | 346 | status = get_submodule_status(g_repo, "sm_unchanged"); |
e26b14c0 RB |
347 | cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); |
348 | ||
349 | expected = GIT_SUBMODULE_STATUS_IN_HEAD | | |
350 | GIT_SUBMODULE_STATUS_IN_INDEX | | |
351 | GIT_SUBMODULE_STATUS_IN_CONFIG | | |
352 | GIT_SUBMODULE_STATUS_IN_WD; | |
e26b14c0 RB |
353 | cl_assert(status == expected); |
354 | } |