]> git.proxmox.com Git - libgit2.git/blame - tests/libgit2/submodule/status.c
Merge https://salsa.debian.org/debian/libgit2 into proxmox/bullseye
[libgit2.git] / tests / libgit2 / submodule / status.c
CommitLineData
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
8static git_repository *g_repo = NULL;
9
10void test_submodule_status__initialize(void)
11{
125655fe 12 g_repo = setup_fixture_submod2();
aa13bf05
RB
13}
14
15void test_submodule_status__cleanup(void)
16{
aa13bf05
RB
17}
18
19void 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
32static 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
40static 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
48static 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
62void 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
110void 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
154void 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
198void 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
242typedef struct {
243 size_t counter;
244 const char **paths;
125655fe 245 int *statuses;
65025cb8
RB
246} submodule_expectations;
247
248static 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
264void 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
333void 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}