]> git.proxmox.com Git - libgit2.git/blame - tests-clar/index/addall.c
Add git_repository_reset_filesystem and fix tests
[libgit2.git] / tests-clar / index / addall.c
CommitLineData
f30fff45
RB
1#include "clar_libgit2.h"
2#include "../status/status_helpers.h"
3#include "posix.h"
c97d407d 4#include "fileops.h"
f30fff45
RB
5
6git_repository *g_repo = NULL;
7
8void test_index_addall__initialize(void)
9{
10}
11
12void test_index_addall__cleanup(void)
13{
14 git_repository_free(g_repo);
15 g_repo = NULL;
16}
17
18#define STATUS_INDEX_FLAGS \
19 (GIT_STATUS_INDEX_NEW | GIT_STATUS_INDEX_MODIFIED | \
20 GIT_STATUS_INDEX_DELETED | GIT_STATUS_INDEX_RENAMED | \
21 GIT_STATUS_INDEX_TYPECHANGE)
22
23#define STATUS_WT_FLAGS \
24 (GIT_STATUS_WT_NEW | GIT_STATUS_WT_MODIFIED | \
25 GIT_STATUS_WT_DELETED | GIT_STATUS_WT_TYPECHANGE | \
26 GIT_STATUS_WT_RENAMED)
27
28typedef struct {
29 size_t index_adds;
30 size_t index_dels;
31 size_t index_mods;
32 size_t wt_adds;
33 size_t wt_dels;
34 size_t wt_mods;
35 size_t ignores;
36} index_status_counts;
37
38static int index_status_cb(
39 const char *path, unsigned int status_flags, void *payload)
40{
41 index_status_counts *vals = payload;
42
43 /* cb_status__print(path, status_flags, NULL); */
44
45 GIT_UNUSED(path);
46
47 if (status_flags & GIT_STATUS_INDEX_NEW)
48 vals->index_adds++;
49 if (status_flags & GIT_STATUS_INDEX_MODIFIED)
50 vals->index_mods++;
51 if (status_flags & GIT_STATUS_INDEX_DELETED)
52 vals->index_dels++;
53 if (status_flags & GIT_STATUS_INDEX_TYPECHANGE)
54 vals->index_mods++;
55
56 if (status_flags & GIT_STATUS_WT_NEW)
57 vals->wt_adds++;
58 if (status_flags & GIT_STATUS_WT_MODIFIED)
59 vals->wt_mods++;
60 if (status_flags & GIT_STATUS_WT_DELETED)
61 vals->wt_dels++;
62 if (status_flags & GIT_STATUS_WT_TYPECHANGE)
63 vals->wt_mods++;
64
65 if (status_flags & GIT_STATUS_IGNORED)
66 vals->ignores++;
67
68 return 0;
69}
70
71static void check_status(
72 git_repository *repo,
73 size_t index_adds, size_t index_dels, size_t index_mods,
74 size_t wt_adds, size_t wt_dels, size_t wt_mods, size_t ignores)
75{
76 index_status_counts vals;
77
78 memset(&vals, 0, sizeof(vals));
79
80 cl_git_pass(git_status_foreach(repo, index_status_cb, &vals));
81
82 cl_assert_equal_sz(index_adds, vals.index_adds);
83 cl_assert_equal_sz(index_dels, vals.index_dels);
84 cl_assert_equal_sz(index_mods, vals.index_mods);
85 cl_assert_equal_sz(wt_adds, vals.wt_adds);
86 cl_assert_equal_sz(wt_dels, vals.wt_dels);
87 cl_assert_equal_sz(wt_mods, vals.wt_mods);
88 cl_assert_equal_sz(ignores, vals.ignores);
89}
90
91static void check_stat_data(git_index *index, const char *path, bool match)
92{
93 const git_index_entry *entry;
94 struct stat st;
95
96 cl_must_pass(p_lstat(path, &st));
97
98 /* skip repo base dir name */
99 while (*path != '/')
100 ++path;
101 ++path;
102
103 entry = git_index_get_bypath(index, path, 0);
104 cl_assert(entry);
105
106 if (match) {
107 cl_assert(st.st_ctime == entry->ctime.seconds);
108 cl_assert(st.st_mtime == entry->mtime.seconds);
109 cl_assert(st.st_size == entry->file_size);
110 cl_assert(st.st_uid == entry->uid);
111 cl_assert(st.st_gid == entry->gid);
c97d407d
RB
112 cl_assert_equal_i_fmt(
113 GIT_MODE_TYPE(st.st_mode), GIT_MODE_TYPE(entry->mode), "%07o");
114 cl_assert_equal_b(
a7fcc44d 115 GIT_PERMS_IS_EXEC(st.st_mode), GIT_PERMS_IS_EXEC(entry->mode));
f30fff45
RB
116 } else {
117 /* most things will still match */
118 cl_assert(st.st_size != entry->file_size);
119 /* would check mtime, but with second resolution it won't work :( */
120 }
121}
122
f30fff45
RB
123void test_index_addall__repo_lifecycle(void)
124{
125 int error;
126 git_index *index;
127 git_strarray paths = { NULL, 0 };
128 char *strs[1];
129
130 cl_git_pass(git_repository_init(&g_repo, "addall", false));
131 check_status(g_repo, 0, 0, 0, 0, 0, 0, 0);
132
133 cl_git_pass(git_repository_index(&index, g_repo));
134
135 cl_git_mkfile("addall/file.foo", "a file");
136 check_status(g_repo, 0, 0, 0, 1, 0, 0, 0);
137
138 cl_git_mkfile("addall/.gitignore", "*.foo\n");
139 check_status(g_repo, 0, 0, 0, 1, 0, 0, 1);
140
141 cl_git_mkfile("addall/file.bar", "another file");
142 check_status(g_repo, 0, 0, 0, 2, 0, 0, 1);
143
144 strs[0] = "file.*";
145 paths.strings = strs;
146 paths.count = 1;
147
148 cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL));
149 check_stat_data(index, "addall/file.bar", true);
150 check_status(g_repo, 1, 0, 0, 1, 0, 0, 1);
151
152 cl_git_rewritefile("addall/file.bar", "new content for file");
153 check_stat_data(index, "addall/file.bar", false);
154 check_status(g_repo, 1, 0, 0, 1, 0, 1, 1);
155
156 cl_git_mkfile("addall/file.zzz", "yet another one");
157 cl_git_mkfile("addall/other.zzz", "yet another one");
158 cl_git_mkfile("addall/more.zzz", "yet another one");
159 check_status(g_repo, 1, 0, 0, 4, 0, 1, 1);
160
161 cl_git_pass(git_index_update_all(index, NULL, NULL, NULL));
162 check_stat_data(index, "addall/file.bar", true);
163 check_status(g_repo, 1, 0, 0, 4, 0, 0, 1);
164
165 cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL));
166 check_stat_data(index, "addall/file.zzz", true);
167 check_status(g_repo, 2, 0, 0, 3, 0, 0, 1);
168
155fa234 169 cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "first commit");
f30fff45
RB
170 check_status(g_repo, 0, 0, 0, 3, 0, 0, 1);
171
172 /* attempt to add an ignored file - does nothing */
173 strs[0] = "file.foo";
174 cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL));
175 check_status(g_repo, 0, 0, 0, 3, 0, 0, 1);
176
177 /* add with check - should generate error */
178 error = git_index_add_all(
179 index, &paths, GIT_INDEX_ADD_CHECK_PATHSPEC, NULL, NULL);
180 cl_assert_equal_i(GIT_EINVALIDSPEC, error);
181 check_status(g_repo, 0, 0, 0, 3, 0, 0, 1);
182
183 /* add with force - should allow */
184 cl_git_pass(git_index_add_all(
185 index, &paths, GIT_INDEX_ADD_FORCE, NULL, NULL));
186 check_stat_data(index, "addall/file.foo", true);
187 check_status(g_repo, 1, 0, 0, 3, 0, 0, 0);
188
189 /* now it's in the index, so regular add should work */
190 cl_git_rewritefile("addall/file.foo", "new content for file");
191 check_stat_data(index, "addall/file.foo", false);
192 check_status(g_repo, 1, 0, 0, 3, 0, 1, 0);
193
194 cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL));
195 check_stat_data(index, "addall/file.foo", true);
196 check_status(g_repo, 1, 0, 0, 3, 0, 0, 0);
197
198 cl_git_pass(git_index_add_bypath(index, "more.zzz"));
199 check_stat_data(index, "addall/more.zzz", true);
200 check_status(g_repo, 2, 0, 0, 2, 0, 0, 0);
201
202 cl_git_rewritefile("addall/file.zzz", "new content for file");
203 check_status(g_repo, 2, 0, 0, 2, 0, 1, 0);
204
205 cl_git_pass(git_index_add_bypath(index, "file.zzz"));
206 check_stat_data(index, "addall/file.zzz", true);
207 check_status(g_repo, 2, 0, 1, 2, 0, 0, 0);
208
209 strs[0] = "*.zzz";
210 cl_git_pass(git_index_remove_all(index, &paths, NULL, NULL));
211 check_status(g_repo, 1, 1, 0, 4, 0, 0, 0);
212
213 cl_git_pass(git_index_add_bypath(index, "file.zzz"));
214 check_status(g_repo, 1, 0, 1, 3, 0, 0, 0);
215
155fa234 216 cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "second commit");
f30fff45
RB
217 check_status(g_repo, 0, 0, 0, 3, 0, 0, 0);
218
219 cl_must_pass(p_unlink("addall/file.zzz"));
220 check_status(g_repo, 0, 0, 0, 3, 1, 0, 0);
221
222 /* update_all should be able to remove entries */
223 cl_git_pass(git_index_update_all(index, NULL, NULL, NULL));
224 check_status(g_repo, 0, 1, 0, 3, 0, 0, 0);
225
7863523a
RB
226 strs[0] = "*";
227 cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL));
228 check_status(g_repo, 3, 1, 0, 0, 0, 0, 0);
229
230 /* must be able to remove at any position while still updating other files */
231 cl_must_pass(p_unlink("addall/.gitignore"));
232 cl_git_rewritefile("addall/file.zzz", "reconstructed file");
233 cl_git_rewritefile("addall/more.zzz", "altered file reality");
234 check_status(g_repo, 3, 1, 0, 1, 1, 1, 0);
235
236 cl_git_pass(git_index_update_all(index, NULL, NULL, NULL));
237 check_status(g_repo, 2, 1, 0, 1, 0, 0, 0);
238 /* this behavior actually matches 'git add -u' where "file.zzz" has
239 * been removed from the index, so when you go to update, even though
240 * it exists in the HEAD, it is not re-added to the index, leaving it
241 * as a DELETE when comparing HEAD to index and as an ADD comparing
242 * index to worktree
243 */
244
f30fff45
RB
245 git_index_free(index);
246}