]>
Commit | Line | Data |
---|---|---|
74fa4bfa RB |
1 | #include "clar_libgit2.h" |
2 | #include "diff_helpers.h" | |
c2e43fb1 | 3 | #include "repository.h" |
9c8ed499 | 4 | #include "git2/sys/diff.h" |
240f4af3 | 5 | |
74fa4bfa RB |
6 | static git_repository *g_repo = NULL; |
7 | ||
74fa4bfa RB |
8 | void test_diff_workdir__cleanup(void) |
9 | { | |
854eccbb | 10 | cl_git_sandbox_cleanup(); |
74fa4bfa RB |
11 | } |
12 | ||
13 | void test_diff_workdir__to_index(void) | |
14 | { | |
2f8d30be | 15 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
3ff1d123 | 16 | git_diff *diff = NULL; |
74fa4bfa | 17 | diff_expects exp; |
f335ecd6 | 18 | int use_iterator; |
74fa4bfa | 19 | |
0abd7244 RB |
20 | g_repo = cl_git_sandbox_init("status"); |
21 | ||
74fa4bfa RB |
22 | opts.context_lines = 3; |
23 | opts.interhunk_lines = 1; | |
24 | opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; | |
25 | ||
56c72b75 | 26 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
74fa4bfa | 27 | |
f335ecd6 RB |
28 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
29 | memset(&exp, 0, sizeof(exp)); | |
30 | ||
31 | if (use_iterator) | |
32 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 33 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
34 | else |
35 | cl_git_pass(git_diff_foreach( | |
793c4385 | 36 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
37 | |
38 | /* to generate these values: | |
39 | * - cd to tests/resources/status, | |
40 | * - mv .gitted .git | |
41 | * - git diff --name-status | |
42 | * - git diff | |
43 | * - mv .git .gitted | |
44 | */ | |
45 | cl_assert_equal_i(13, exp.files); | |
b4f5bb07 RB |
46 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
47 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); | |
48 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); | |
49 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
50 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); | |
f335ecd6 RB |
51 | |
52 | cl_assert_equal_i(8, exp.hunks); | |
53 | ||
54 | cl_assert_equal_i(14, exp.lines); | |
55 | cl_assert_equal_i(5, exp.line_ctxt); | |
56 | cl_assert_equal_i(4, exp.line_adds); | |
57 | cl_assert_equal_i(5, exp.line_dels); | |
9c8ed499 | 58 | } |
240f4af3 | 59 | |
9c8ed499 RB |
60 | { |
61 | git_diff_perfdata perf = GIT_DIFF_PERFDATA_INIT; | |
62 | cl_git_pass(git_diff_get_perfdata(&perf, diff)); | |
240f4af3 | 63 | cl_assert_equal_sz( |
9c8ed499 RB |
64 | 13 /* in root */ + 3 /* in subdir */, perf.stat_calls); |
65 | cl_assert_equal_sz(5, perf.oid_calculations); | |
f335ecd6 | 66 | } |
74fa4bfa | 67 | |
3ff1d123 | 68 | git_diff_free(diff); |
74fa4bfa RB |
69 | } |
70 | ||
3e57069e RB |
71 | void test_diff_workdir__to_index_with_assume_unchanged(void) |
72 | { | |
73 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
74 | git_diff *diff = NULL; | |
75 | git_index *idx = NULL; | |
76 | diff_expects exp; | |
77 | const git_index_entry *iep; | |
78 | git_index_entry ie; | |
79 | ||
80 | g_repo = cl_git_sandbox_init("status"); | |
81 | ||
82 | /* do initial diff */ | |
83 | ||
84 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
85 | memset(&exp, 0, sizeof(exp)); | |
86 | cl_git_pass(git_diff_foreach( | |
87 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
88 | cl_assert_equal_i(8, exp.files); | |
89 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
90 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); | |
91 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); | |
92 | git_diff_free(diff); | |
93 | ||
94 | /* mark a couple of entries with ASSUME_UNCHANGED */ | |
95 | ||
96 | cl_git_pass(git_repository_index(&idx, g_repo)); | |
97 | ||
98 | cl_assert((iep = git_index_get_bypath(idx, "modified_file", 0)) != NULL); | |
99 | memcpy(&ie, iep, sizeof(ie)); | |
100 | ie.flags |= GIT_IDXENTRY_VALID; | |
101 | cl_git_pass(git_index_add(idx, &ie)); | |
102 | ||
103 | cl_assert((iep = git_index_get_bypath(idx, "file_deleted", 0)) != NULL); | |
104 | memcpy(&ie, iep, sizeof(ie)); | |
105 | ie.flags |= GIT_IDXENTRY_VALID; | |
106 | cl_git_pass(git_index_add(idx, &ie)); | |
107 | ||
108 | cl_git_pass(git_index_write(idx)); | |
109 | git_index_free(idx); | |
110 | ||
111 | /* redo diff and see that entries are skipped */ | |
112 | ||
113 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
114 | memset(&exp, 0, sizeof(exp)); | |
115 | cl_git_pass(git_diff_foreach( | |
116 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
117 | cl_assert_equal_i(6, exp.files); | |
118 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
119 | cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); | |
120 | cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); | |
121 | git_diff_free(diff); | |
122 | ||
123 | } | |
124 | ||
74fa4bfa RB |
125 | void test_diff_workdir__to_tree(void) |
126 | { | |
127 | /* grabbed a couple of commit oids from the history of the attr repo */ | |
128 | const char *a_commit = "26a125ee1bf"; /* the current HEAD */ | |
129 | const char *b_commit = "0017bd4ab1ec3"; /* the start */ | |
0abd7244 | 130 | git_tree *a, *b; |
2f8d30be | 131 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
3ff1d123 RB |
132 | git_diff *diff = NULL; |
133 | git_diff *diff2 = NULL; | |
74fa4bfa | 134 | diff_expects exp; |
f335ecd6 | 135 | int use_iterator; |
74fa4bfa | 136 | |
0abd7244 RB |
137 | g_repo = cl_git_sandbox_init("status"); |
138 | ||
139 | a = resolve_commit_oid_to_tree(g_repo, a_commit); | |
140 | b = resolve_commit_oid_to_tree(g_repo, b_commit); | |
141 | ||
74fa4bfa RB |
142 | opts.context_lines = 3; |
143 | opts.interhunk_lines = 1; | |
144 | opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; | |
145 | ||
56c72b75 | 146 | /* You can't really generate the equivalent of git_diff_tree_to_workdir() |
74fa4bfa RB |
147 | * using C git. It really wants to interpose the index into the diff. |
148 | * | |
149 | * To validate the following results with command line git, I ran the | |
150 | * following: | |
151 | * - git ls-tree 26a125 | |
152 | * - find . ! -path ./.git/\* -a -type f | git hash-object --stdin-paths | |
153 | * The results are documented at the bottom of this file in the | |
154 | * long comment entitled "PREPARATION OF TEST DATA". | |
155 | */ | |
56c72b75 | 156 | cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); |
74fa4bfa | 157 | |
f335ecd6 RB |
158 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
159 | memset(&exp, 0, sizeof(exp)); | |
74fa4bfa | 160 | |
f335ecd6 RB |
161 | if (use_iterator) |
162 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 163 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
164 | else |
165 | cl_git_pass(git_diff_foreach( | |
793c4385 | 166 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
167 | |
168 | cl_assert_equal_i(14, exp.files); | |
b4f5bb07 RB |
169 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
170 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); | |
171 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); | |
172 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
173 | cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNTRACKED]); | |
f335ecd6 | 174 | } |
74fa4bfa RB |
175 | |
176 | /* Since there is no git diff equivalent, let's just assume that the | |
177 | * text diffs produced by git_diff_foreach are accurate here. We will | |
178 | * do more apples-to-apples test comparison below. | |
179 | */ | |
180 | ||
3ff1d123 | 181 | git_diff_free(diff); |
74fa4bfa RB |
182 | diff = NULL; |
183 | memset(&exp, 0, sizeof(exp)); | |
184 | ||
185 | /* This is a compatible emulation of "git diff <sha>" which looks like | |
186 | * a workdir to tree diff (even though it is not really). This is what | |
187 | * you would get from "git diff --name-status 26a125ee1bf" | |
188 | */ | |
56c72b75 RB |
189 | cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); |
190 | cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); | |
74fa4bfa | 191 | cl_git_pass(git_diff_merge(diff, diff2)); |
3ff1d123 | 192 | git_diff_free(diff2); |
74fa4bfa | 193 | |
f335ecd6 RB |
194 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
195 | memset(&exp, 0, sizeof(exp)); | |
196 | ||
197 | if (use_iterator) | |
198 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 199 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
200 | else |
201 | cl_git_pass(git_diff_foreach( | |
793c4385 | 202 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
74fa4bfa | 203 | |
f335ecd6 | 204 | cl_assert_equal_i(15, exp.files); |
b4f5bb07 RB |
205 | cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); |
206 | cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]); | |
207 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); | |
208 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
209 | cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); | |
74fa4bfa | 210 | |
f335ecd6 | 211 | cl_assert_equal_i(11, exp.hunks); |
74fa4bfa | 212 | |
f335ecd6 RB |
213 | cl_assert_equal_i(17, exp.lines); |
214 | cl_assert_equal_i(4, exp.line_ctxt); | |
215 | cl_assert_equal_i(8, exp.line_adds); | |
216 | cl_assert_equal_i(5, exp.line_dels); | |
217 | } | |
74fa4bfa | 218 | |
3ff1d123 | 219 | git_diff_free(diff); |
74fa4bfa RB |
220 | diff = NULL; |
221 | memset(&exp, 0, sizeof(exp)); | |
222 | ||
223 | /* Again, emulating "git diff <sha>" for testing purposes using | |
224 | * "git diff --name-status 0017bd4ab1ec3" instead. | |
225 | */ | |
56c72b75 RB |
226 | cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); |
227 | cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); | |
74fa4bfa | 228 | cl_git_pass(git_diff_merge(diff, diff2)); |
3ff1d123 | 229 | git_diff_free(diff2); |
74fa4bfa | 230 | |
f335ecd6 RB |
231 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
232 | memset(&exp, 0, sizeof(exp)); | |
74fa4bfa | 233 | |
f335ecd6 RB |
234 | if (use_iterator) |
235 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 236 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
237 | else |
238 | cl_git_pass(git_diff_foreach( | |
793c4385 | 239 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
74fa4bfa | 240 | |
f335ecd6 | 241 | cl_assert_equal_i(16, exp.files); |
b4f5bb07 RB |
242 | cl_assert_equal_i(5, exp.file_status[GIT_DELTA_ADDED]); |
243 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); | |
244 | cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); | |
245 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
246 | cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); | |
74fa4bfa | 247 | |
f335ecd6 RB |
248 | cl_assert_equal_i(12, exp.hunks); |
249 | ||
250 | cl_assert_equal_i(19, exp.lines); | |
251 | cl_assert_equal_i(3, exp.line_ctxt); | |
252 | cl_assert_equal_i(12, exp.line_adds); | |
253 | cl_assert_equal_i(4, exp.line_dels); | |
254 | } | |
74fa4bfa | 255 | |
3ff1d123 | 256 | git_diff_free(diff); |
c19bc93c | 257 | |
e7c85120 RB |
258 | /* Let's try that once more with a reversed diff */ |
259 | ||
260 | opts.flags |= GIT_DIFF_REVERSE; | |
261 | ||
262 | cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); | |
263 | cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); | |
264 | cl_git_pass(git_diff_merge(diff, diff2)); | |
265 | git_diff_free(diff2); | |
266 | ||
267 | memset(&exp, 0, sizeof(exp)); | |
268 | ||
269 | cl_git_pass(git_diff_foreach( | |
270 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
271 | ||
272 | cl_assert_equal_i(16, exp.files); | |
273 | cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]); | |
274 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_ADDED]); | |
275 | cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); | |
276 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
277 | cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); | |
278 | ||
279 | cl_assert_equal_i(12, exp.hunks); | |
280 | ||
281 | cl_assert_equal_i(19, exp.lines); | |
282 | cl_assert_equal_i(3, exp.line_ctxt); | |
283 | cl_assert_equal_i(12, exp.line_dels); | |
284 | cl_assert_equal_i(4, exp.line_adds); | |
285 | ||
286 | git_diff_free(diff); | |
287 | ||
288 | /* all done now */ | |
289 | ||
74fa4bfa RB |
290 | git_tree_free(a); |
291 | git_tree_free(b); | |
292 | } | |
293 | ||
14a513e0 RB |
294 | void test_diff_workdir__to_index_with_pathspec(void) |
295 | { | |
2f8d30be | 296 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
3ff1d123 | 297 | git_diff *diff = NULL; |
14a513e0 RB |
298 | diff_expects exp; |
299 | char *pathspec = NULL; | |
f335ecd6 | 300 | int use_iterator; |
14a513e0 | 301 | |
0abd7244 RB |
302 | g_repo = cl_git_sandbox_init("status"); |
303 | ||
14a513e0 RB |
304 | opts.context_lines = 3; |
305 | opts.interhunk_lines = 1; | |
306 | opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; | |
307 | opts.pathspec.strings = &pathspec; | |
308 | opts.pathspec.count = 1; | |
309 | ||
56c72b75 | 310 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
14a513e0 | 311 | |
f335ecd6 RB |
312 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
313 | memset(&exp, 0, sizeof(exp)); | |
314 | ||
315 | if (use_iterator) | |
316 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 317 | diff, diff_file_cb, NULL, NULL, &exp)); |
f335ecd6 | 318 | else |
793c4385 | 319 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); |
f335ecd6 RB |
320 | |
321 | cl_assert_equal_i(13, exp.files); | |
b4f5bb07 RB |
322 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
323 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); | |
324 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); | |
325 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
326 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); | |
f335ecd6 | 327 | } |
14a513e0 | 328 | |
3ff1d123 | 329 | git_diff_free(diff); |
14a513e0 | 330 | |
14a513e0 RB |
331 | pathspec = "modified_file"; |
332 | ||
56c72b75 | 333 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
14a513e0 | 334 | |
f335ecd6 RB |
335 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
336 | memset(&exp, 0, sizeof(exp)); | |
337 | ||
338 | if (use_iterator) | |
339 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 340 | diff, diff_file_cb, NULL, NULL, &exp)); |
f335ecd6 | 341 | else |
793c4385 | 342 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); |
f335ecd6 RB |
343 | |
344 | cl_assert_equal_i(1, exp.files); | |
b4f5bb07 RB |
345 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
346 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); | |
347 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
348 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); | |
349 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]); | |
f335ecd6 | 350 | } |
14a513e0 | 351 | |
3ff1d123 | 352 | git_diff_free(diff); |
14a513e0 | 353 | |
14a513e0 RB |
354 | pathspec = "subdir"; |
355 | ||
56c72b75 | 356 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
14a513e0 | 357 | |
f335ecd6 RB |
358 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
359 | memset(&exp, 0, sizeof(exp)); | |
360 | ||
361 | if (use_iterator) | |
362 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 363 | diff, diff_file_cb, NULL, NULL, &exp)); |
f335ecd6 | 364 | else |
793c4385 | 365 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); |
f335ecd6 RB |
366 | |
367 | cl_assert_equal_i(3, exp.files); | |
b4f5bb07 RB |
368 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
369 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); | |
370 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
371 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); | |
372 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); | |
f335ecd6 | 373 | } |
14a513e0 | 374 | |
3ff1d123 | 375 | git_diff_free(diff); |
14a513e0 | 376 | |
14a513e0 RB |
377 | pathspec = "*_deleted"; |
378 | ||
56c72b75 | 379 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
14a513e0 | 380 | |
f335ecd6 RB |
381 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
382 | memset(&exp, 0, sizeof(exp)); | |
383 | ||
384 | if (use_iterator) | |
385 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 386 | diff, diff_file_cb, NULL, NULL, &exp)); |
f335ecd6 | 387 | else |
793c4385 | 388 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); |
f335ecd6 RB |
389 | |
390 | cl_assert_equal_i(2, exp.files); | |
b4f5bb07 RB |
391 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
392 | cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); | |
393 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); | |
394 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); | |
395 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]); | |
f335ecd6 | 396 | } |
14a513e0 | 397 | |
3ff1d123 | 398 | git_diff_free(diff); |
14a513e0 RB |
399 | } |
400 | ||
0abd7244 RB |
401 | void test_diff_workdir__filemode_changes(void) |
402 | { | |
3ff1d123 | 403 | git_diff *diff = NULL; |
0abd7244 | 404 | diff_expects exp; |
f335ecd6 | 405 | int use_iterator; |
0abd7244 RB |
406 | |
407 | if (!cl_is_chmod_supported()) | |
408 | return; | |
409 | ||
410 | g_repo = cl_git_sandbox_init("issue_592"); | |
411 | ||
1323c6d1 | 412 | cl_repo_set_bool(g_repo, "core.filemode", true); |
0abd7244 RB |
413 | |
414 | /* test once with no mods */ | |
415 | ||
56c72b75 | 416 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); |
0abd7244 | 417 | |
f335ecd6 RB |
418 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
419 | memset(&exp, 0, sizeof(exp)); | |
0abd7244 | 420 | |
f335ecd6 RB |
421 | if (use_iterator) |
422 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 423 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
424 | else |
425 | cl_git_pass(git_diff_foreach( | |
793c4385 | 426 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
427 | |
428 | cl_assert_equal_i(0, exp.files); | |
b4f5bb07 | 429 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); |
f335ecd6 RB |
430 | cl_assert_equal_i(0, exp.hunks); |
431 | } | |
0abd7244 | 432 | |
3ff1d123 | 433 | git_diff_free(diff); |
0abd7244 RB |
434 | |
435 | /* chmod file and test again */ | |
436 | ||
437 | cl_assert(cl_toggle_filemode("issue_592/a.txt")); | |
438 | ||
56c72b75 | 439 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); |
0abd7244 | 440 | |
f335ecd6 RB |
441 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
442 | memset(&exp, 0, sizeof(exp)); | |
0abd7244 | 443 | |
f335ecd6 RB |
444 | if (use_iterator) |
445 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 446 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
447 | else |
448 | cl_git_pass(git_diff_foreach( | |
793c4385 | 449 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
450 | |
451 | cl_assert_equal_i(1, exp.files); | |
b4f5bb07 | 452 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); |
f335ecd6 RB |
453 | cl_assert_equal_i(0, exp.hunks); |
454 | } | |
0abd7244 | 455 | |
3ff1d123 | 456 | git_diff_free(diff); |
0abd7244 RB |
457 | |
458 | cl_assert(cl_toggle_filemode("issue_592/a.txt")); | |
0abd7244 RB |
459 | } |
460 | ||
461 | void test_diff_workdir__filemode_changes_with_filemode_false(void) | |
462 | { | |
3ff1d123 | 463 | git_diff *diff = NULL; |
0abd7244 RB |
464 | diff_expects exp; |
465 | ||
466 | if (!cl_is_chmod_supported()) | |
467 | return; | |
468 | ||
469 | g_repo = cl_git_sandbox_init("issue_592"); | |
470 | ||
1323c6d1 | 471 | cl_repo_set_bool(g_repo, "core.filemode", false); |
0abd7244 RB |
472 | |
473 | /* test once with no mods */ | |
474 | ||
56c72b75 | 475 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); |
0abd7244 RB |
476 | |
477 | memset(&exp, 0, sizeof(exp)); | |
478 | cl_git_pass(git_diff_foreach( | |
793c4385 | 479 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
0abd7244 RB |
480 | |
481 | cl_assert_equal_i(0, exp.files); | |
b4f5bb07 | 482 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); |
0abd7244 RB |
483 | cl_assert_equal_i(0, exp.hunks); |
484 | ||
3ff1d123 | 485 | git_diff_free(diff); |
0abd7244 RB |
486 | |
487 | /* chmod file and test again */ | |
488 | ||
489 | cl_assert(cl_toggle_filemode("issue_592/a.txt")); | |
490 | ||
56c72b75 | 491 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); |
0abd7244 RB |
492 | |
493 | memset(&exp, 0, sizeof(exp)); | |
494 | cl_git_pass(git_diff_foreach( | |
793c4385 | 495 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
0abd7244 RB |
496 | |
497 | cl_assert_equal_i(0, exp.files); | |
b4f5bb07 | 498 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); |
0abd7244 RB |
499 | cl_assert_equal_i(0, exp.hunks); |
500 | ||
3ff1d123 | 501 | git_diff_free(diff); |
0abd7244 RB |
502 | |
503 | cl_assert(cl_toggle_filemode("issue_592/a.txt")); | |
0abd7244 RB |
504 | } |
505 | ||
145e696b RB |
506 | void test_diff_workdir__head_index_and_workdir_all_differ(void) |
507 | { | |
2f8d30be | 508 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
3ff1d123 | 509 | git_diff *diff_i2t = NULL, *diff_w2i = NULL; |
145e696b RB |
510 | diff_expects exp; |
511 | char *pathspec = "staged_changes_modified_file"; | |
512 | git_tree *tree; | |
f335ecd6 | 513 | int use_iterator; |
145e696b RB |
514 | |
515 | /* For this file, | |
516 | * - head->index diff has 1 line of context, 1 line of diff | |
517 | * - index->workdir diff has 2 lines of context, 1 line of diff | |
518 | * but | |
519 | * - head->workdir diff has 1 line of context, 2 lines of diff | |
520 | * Let's make sure the right one is returned from each fn. | |
521 | */ | |
522 | ||
523 | g_repo = cl_git_sandbox_init("status"); | |
524 | ||
525 | tree = resolve_commit_oid_to_tree(g_repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f"); | |
526 | ||
527 | opts.pathspec.strings = &pathspec; | |
528 | opts.pathspec.count = 1; | |
529 | ||
56c72b75 RB |
530 | cl_git_pass(git_diff_tree_to_index(&diff_i2t, g_repo, tree, NULL, &opts)); |
531 | cl_git_pass(git_diff_index_to_workdir(&diff_w2i, g_repo, NULL, &opts)); | |
145e696b | 532 | |
f335ecd6 RB |
533 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
534 | memset(&exp, 0, sizeof(exp)); | |
535 | ||
536 | if (use_iterator) | |
537 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 538 | diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
539 | else |
540 | cl_git_pass(git_diff_foreach( | |
793c4385 | 541 | diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
542 | |
543 | cl_assert_equal_i(1, exp.files); | |
b4f5bb07 RB |
544 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
545 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); | |
546 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
f335ecd6 RB |
547 | cl_assert_equal_i(1, exp.hunks); |
548 | cl_assert_equal_i(2, exp.lines); | |
549 | cl_assert_equal_i(1, exp.line_ctxt); | |
550 | cl_assert_equal_i(1, exp.line_adds); | |
551 | cl_assert_equal_i(0, exp.line_dels); | |
552 | } | |
553 | ||
554 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { | |
555 | memset(&exp, 0, sizeof(exp)); | |
556 | ||
557 | if (use_iterator) | |
558 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 559 | diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
560 | else |
561 | cl_git_pass(git_diff_foreach( | |
793c4385 | 562 | diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
563 | |
564 | cl_assert_equal_i(1, exp.files); | |
b4f5bb07 RB |
565 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
566 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); | |
567 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
f335ecd6 RB |
568 | cl_assert_equal_i(1, exp.hunks); |
569 | cl_assert_equal_i(3, exp.lines); | |
570 | cl_assert_equal_i(2, exp.line_ctxt); | |
571 | cl_assert_equal_i(1, exp.line_adds); | |
572 | cl_assert_equal_i(0, exp.line_dels); | |
573 | } | |
145e696b RB |
574 | |
575 | cl_git_pass(git_diff_merge(diff_i2t, diff_w2i)); | |
576 | ||
f335ecd6 RB |
577 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
578 | memset(&exp, 0, sizeof(exp)); | |
579 | ||
580 | if (use_iterator) | |
581 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 582 | diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
583 | else |
584 | cl_git_pass(git_diff_foreach( | |
793c4385 | 585 | diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
586 | |
587 | cl_assert_equal_i(1, exp.files); | |
b4f5bb07 RB |
588 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
589 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); | |
590 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
f335ecd6 RB |
591 | cl_assert_equal_i(1, exp.hunks); |
592 | cl_assert_equal_i(3, exp.lines); | |
593 | cl_assert_equal_i(1, exp.line_ctxt); | |
594 | cl_assert_equal_i(2, exp.line_adds); | |
595 | cl_assert_equal_i(0, exp.line_dels); | |
596 | } | |
145e696b | 597 | |
3ff1d123 RB |
598 | git_diff_free(diff_i2t); |
599 | git_diff_free(diff_w2i); | |
cdca82c7 CMN |
600 | |
601 | git_tree_free(tree); | |
145e696b RB |
602 | } |
603 | ||
604 | void test_diff_workdir__eof_newline_changes(void) | |
605 | { | |
2f8d30be | 606 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
3ff1d123 | 607 | git_diff *diff = NULL; |
145e696b RB |
608 | diff_expects exp; |
609 | char *pathspec = "current_file"; | |
f335ecd6 | 610 | int use_iterator; |
145e696b RB |
611 | |
612 | g_repo = cl_git_sandbox_init("status"); | |
613 | ||
614 | opts.pathspec.strings = &pathspec; | |
615 | opts.pathspec.count = 1; | |
616 | ||
56c72b75 | 617 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
145e696b | 618 | |
f335ecd6 RB |
619 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
620 | memset(&exp, 0, sizeof(exp)); | |
621 | ||
622 | if (use_iterator) | |
623 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 624 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
625 | else |
626 | cl_git_pass(git_diff_foreach( | |
793c4385 | 627 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
628 | |
629 | cl_assert_equal_i(0, exp.files); | |
b4f5bb07 RB |
630 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
631 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); | |
632 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); | |
f335ecd6 RB |
633 | cl_assert_equal_i(0, exp.hunks); |
634 | cl_assert_equal_i(0, exp.lines); | |
635 | cl_assert_equal_i(0, exp.line_ctxt); | |
636 | cl_assert_equal_i(0, exp.line_adds); | |
637 | cl_assert_equal_i(0, exp.line_dels); | |
638 | } | |
145e696b | 639 | |
3ff1d123 | 640 | git_diff_free(diff); |
145e696b RB |
641 | |
642 | cl_git_append2file("status/current_file", "\n"); | |
643 | ||
56c72b75 | 644 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
145e696b | 645 | |
f335ecd6 RB |
646 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
647 | memset(&exp, 0, sizeof(exp)); | |
648 | ||
649 | if (use_iterator) | |
650 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 651 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
652 | else |
653 | cl_git_pass(git_diff_foreach( | |
793c4385 | 654 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
655 | |
656 | cl_assert_equal_i(1, exp.files); | |
b4f5bb07 RB |
657 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
658 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); | |
659 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
f335ecd6 RB |
660 | cl_assert_equal_i(1, exp.hunks); |
661 | cl_assert_equal_i(2, exp.lines); | |
662 | cl_assert_equal_i(1, exp.line_ctxt); | |
663 | cl_assert_equal_i(1, exp.line_adds); | |
664 | cl_assert_equal_i(0, exp.line_dels); | |
665 | } | |
145e696b | 666 | |
3ff1d123 | 667 | git_diff_free(diff); |
145e696b RB |
668 | |
669 | cl_git_rewritefile("status/current_file", "current_file"); | |
670 | ||
56c72b75 | 671 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
145e696b | 672 | |
f335ecd6 RB |
673 | for (use_iterator = 0; use_iterator <= 1; use_iterator++) { |
674 | memset(&exp, 0, sizeof(exp)); | |
675 | ||
676 | if (use_iterator) | |
677 | cl_git_pass(diff_foreach_via_iterator( | |
793c4385 | 678 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
679 | else |
680 | cl_git_pass(git_diff_foreach( | |
793c4385 | 681 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
f335ecd6 RB |
682 | |
683 | cl_assert_equal_i(1, exp.files); | |
b4f5bb07 RB |
684 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
685 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); | |
686 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
f335ecd6 RB |
687 | cl_assert_equal_i(1, exp.hunks); |
688 | cl_assert_equal_i(3, exp.lines); | |
689 | cl_assert_equal_i(0, exp.line_ctxt); | |
690 | cl_assert_equal_i(1, exp.line_adds); | |
691 | cl_assert_equal_i(2, exp.line_dels); | |
692 | } | |
145e696b | 693 | |
3ff1d123 | 694 | git_diff_free(diff); |
145e696b RB |
695 | } |
696 | ||
74fa4bfa RB |
697 | /* PREPARATION OF TEST DATA |
698 | * | |
56c72b75 | 699 | * Since there is no command line equivalent of git_diff_tree_to_workdir, |
74fa4bfa RB |
700 | * it was a bit of a pain to confirm that I was getting the expected |
701 | * results in the first part of this tests. Here is what I ended up | |
702 | * doing to set my expectation for the file counts and results: | |
703 | * | |
704 | * Running "git ls-tree 26a125" and "git ls-tree aa27a6" shows: | |
705 | * | |
706 | * A a0de7e0ac200c489c41c59dfa910154a70264e6e current_file | |
707 | * B 5452d32f1dd538eb0405e8a83cc185f79e25e80f file_deleted | |
708 | * C 452e4244b5d083ddf0460acf1ecc74db9dcfa11a modified_file | |
709 | * D 32504b727382542f9f089e24fddac5e78533e96c staged_changes | |
710 | * E 061d42a44cacde5726057b67558821d95db96f19 staged_changes_file_deleted | |
711 | * F 70bd9443ada07063e7fbf0b3ff5c13f7494d89c2 staged_changes_modified_file | |
712 | * G e9b9107f290627c04d097733a10055af941f6bca staged_delete_file_deleted | |
713 | * H dabc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 staged_delete_modified_file | |
714 | * I 53ace0d1cc1145a5f4fe4f78a186a60263190733 subdir/current_file | |
715 | * J 1888c805345ba265b0ee9449b8877b6064592058 subdir/deleted_file | |
716 | * K a6191982709b746d5650e93c2acf34ef74e11504 subdir/modified_file | |
717 | * L e8ee89e15bbe9b20137715232387b3de5b28972e subdir.txt | |
718 | * | |
719 | * -------- | |
720 | * | |
721 | * find . ! -path ./.git/\* -a -type f | git hash-object --stdin-paths | |
722 | * | |
723 | * A a0de7e0ac200c489c41c59dfa910154a70264e6e current_file | |
724 | * M 6a79f808a9c6bc9531ac726c184bbcd9351ccf11 ignored_file | |
725 | * C 0a539630525aca2e7bc84975958f92f10a64c9b6 modified_file | |
726 | * N d4fa8600b4f37d7516bef4816ae2c64dbf029e3a new_file | |
727 | * D 55d316c9ba708999f1918e9677d01dfcae69c6b9 staged_changes | |
728 | * F 011c3440d5c596e21d836aa6d7b10eb581f68c49 staged_changes_modified_file | |
729 | * H dabc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 staged_delete_modified_file | |
730 | * O 529a16e8e762d4acb7b9636ff540a00831f9155a staged_new_file | |
731 | * P 8b090c06d14ffa09c4e880088ebad33893f921d1 staged_new_file_modified_file | |
732 | * I 53ace0d1cc1145a5f4fe4f78a186a60263190733 subdir/current_file | |
733 | * K 57274b75eeb5f36fd55527806d567b2240a20c57 subdir/modified_file | |
734 | * Q 80a86a6931b91bc01c2dbf5ca55bdd24ad1ef466 subdir/new_file | |
735 | * L e8ee89e15bbe9b20137715232387b3de5b28972e subdir.txt | |
736 | * | |
737 | * -------- | |
738 | * | |
739 | * A - current_file (UNMODIFIED) -> not in results | |
740 | * B D file_deleted | |
741 | * M I ignored_file (IGNORED) | |
742 | * C M modified_file | |
743 | * N U new_file (UNTRACKED) | |
744 | * D M staged_changes | |
745 | * E D staged_changes_file_deleted | |
746 | * F M staged_changes_modified_file | |
747 | * G D staged_delete_file_deleted | |
748 | * H - staged_delete_modified_file (UNMODIFIED) -> not in results | |
749 | * O U staged_new_file | |
750 | * P U staged_new_file_modified_file | |
751 | * I - subdir/current_file (UNMODIFIED) -> not in results | |
752 | * J D subdir/deleted_file | |
753 | * K M subdir/modified_file | |
754 | * Q U subdir/new_file | |
755 | * L - subdir.txt (UNMODIFIED) -> not in results | |
756 | * | |
757 | * Expect 13 files, 0 ADD, 4 DEL, 4 MOD, 1 IGN, 4 UNTR | |
758 | */ | |
49d34c1c RB |
759 | |
760 | ||
761 | void test_diff_workdir__larger_hunks(void) | |
762 | { | |
763 | const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69"; | |
764 | const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; | |
765 | git_tree *a, *b; | |
2f8d30be | 766 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
3b5f7954 | 767 | size_t i, d, num_d, h, num_h, l, num_l; |
49d34c1c RB |
768 | |
769 | g_repo = cl_git_sandbox_init("diff"); | |
770 | ||
771 | cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); | |
772 | cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); | |
773 | ||
774 | opts.context_lines = 1; | |
775 | opts.interhunk_lines = 0; | |
776 | ||
777 | for (i = 0; i <= 2; ++i) { | |
3ff1d123 RB |
778 | git_diff *diff = NULL; |
779 | git_patch *patch; | |
3b5f7954 RB |
780 | const git_diff_hunk *hunk; |
781 | const git_diff_line *line; | |
49d34c1c RB |
782 | |
783 | /* okay, this is a bit silly, but oh well */ | |
784 | switch (i) { | |
785 | case 0: | |
56c72b75 | 786 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
49d34c1c RB |
787 | break; |
788 | case 1: | |
56c72b75 | 789 | cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); |
49d34c1c RB |
790 | break; |
791 | case 2: | |
56c72b75 | 792 | cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, b, &opts)); |
49d34c1c RB |
793 | break; |
794 | } | |
795 | ||
5f69a31f RB |
796 | num_d = git_diff_num_deltas(diff); |
797 | cl_assert_equal_i(2, (int)num_d); | |
49d34c1c | 798 | |
5f69a31f | 799 | for (d = 0; d < num_d; ++d) { |
10672e3e | 800 | cl_git_pass(git_patch_from_diff(&patch, diff, d)); |
5f69a31f | 801 | cl_assert(patch); |
49d34c1c | 802 | |
3ff1d123 | 803 | num_h = git_patch_num_hunks(patch); |
5f69a31f | 804 | for (h = 0; h < num_h; h++) { |
3b5f7954 | 805 | cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); |
49d34c1c | 806 | |
5f69a31f | 807 | for (l = 0; l < num_l; ++l) { |
3b5f7954 RB |
808 | cl_git_pass( |
809 | git_patch_get_line_in_hunk(&line, patch, h, l)); | |
5f69a31f | 810 | cl_assert(line); |
49d34c1c RB |
811 | } |
812 | ||
5f69a31f | 813 | /* confirm fail after the last item */ |
3b5f7954 RB |
814 | cl_git_fail( |
815 | git_patch_get_line_in_hunk(&line, patch, h, num_l)); | |
49d34c1c RB |
816 | } |
817 | ||
5f69a31f | 818 | /* confirm fail after the last item */ |
3b5f7954 | 819 | cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h)); |
49d34c1c | 820 | |
3ff1d123 | 821 | git_patch_free(patch); |
5f69a31f | 822 | } |
49d34c1c | 823 | |
3ff1d123 | 824 | git_diff_free(diff); |
49d34c1c RB |
825 | } |
826 | ||
827 | git_tree_free(a); | |
828 | git_tree_free(b); | |
829 | } | |
5d1308f2 RB |
830 | |
831 | /* Set up a test that exercises this code. The easiest test using existing | |
832 | * test data is probably to create a sandbox of submod2 and then run a | |
56c72b75 | 833 | * git_diff_tree_to_workdir against tree |
5d1308f2 RB |
834 | * 873585b94bdeabccea991ea5e3ec1a277895b698. As for what you should actually |
835 | * test, you can start by just checking that the number of lines of diff | |
836 | * content matches the actual output of git diff. That will at least | |
837 | * demonstrate that the submodule content is being used to generate somewhat | |
838 | * comparable outputs. It is a test that would fail without this code and | |
839 | * will succeed with it. | |
840 | */ | |
841 | ||
842 | #include "../submodule/submodule_helpers.h" | |
843 | ||
844 | void test_diff_workdir__submodules(void) | |
845 | { | |
846 | const char *a_commit = "873585b94bdeabccea991ea5e3ec1a277895b698"; | |
847 | git_tree *a; | |
2f8d30be | 848 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
3ff1d123 | 849 | git_diff *diff = NULL; |
5d1308f2 RB |
850 | diff_expects exp; |
851 | ||
14997dc5 | 852 | g_repo = setup_fixture_submod2(); |
5d1308f2 RB |
853 | |
854 | a = resolve_commit_oid_to_tree(g_repo, a_commit); | |
855 | ||
856 | opts.flags = | |
857 | GIT_DIFF_INCLUDE_UNTRACKED | | |
125655fe | 858 | GIT_DIFF_INCLUDE_IGNORED | |
5d1308f2 | 859 | GIT_DIFF_RECURSE_UNTRACKED_DIRS | |
10672e3e | 860 | GIT_DIFF_SHOW_UNTRACKED_CONTENT; |
5d1308f2 | 861 | |
56c72b75 | 862 | cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); |
5d1308f2 RB |
863 | |
864 | /* diff_print(stderr, diff); */ | |
865 | ||
866 | /* essentially doing: git diff 873585b94bdeabccea991ea5e3ec1a277895b698 */ | |
867 | ||
868 | memset(&exp, 0, sizeof(exp)); | |
65025cb8 | 869 | |
5d1308f2 | 870 | cl_git_pass(git_diff_foreach( |
793c4385 | 871 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); |
5d1308f2 | 872 | |
ccfa6805 RB |
873 | /* so "git diff 873585" returns: |
874 | * M .gitmodules | |
875 | * A just_a_dir/contents | |
876 | * A just_a_file | |
877 | * A sm_added_and_uncommited | |
878 | * A sm_changed_file | |
879 | * A sm_changed_head | |
880 | * A sm_changed_index | |
881 | * A sm_changed_untracked_file | |
882 | * M sm_missing_commits | |
883 | * A sm_unchanged | |
884 | * which is a little deceptive because of the difference between the | |
885 | * "git diff <treeish>" results from "git_diff_tree_to_workdir". The | |
886 | * only significant difference is that those Added items will show up | |
887 | * as Untracked items in the pure libgit2 diff. | |
888 | * | |
d3bc95fd | 889 | * Then add in the two extra untracked items "not" and "not-submodule" |
ccfa6805 | 890 | * to get the 12 files reported here. |
5d1308f2 RB |
891 | */ |
892 | ||
ccfa6805 | 893 | cl_assert_equal_i(12, exp.files); |
5d1308f2 | 894 | |
b4f5bb07 RB |
895 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); |
896 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); | |
ccfa6805 | 897 | cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); |
d3bc95fd RB |
898 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); |
899 | cl_assert_equal_i(10, exp.file_status[GIT_DELTA_UNTRACKED]); | |
5d1308f2 RB |
900 | |
901 | /* the following numbers match "git diff 873585" exactly */ | |
902 | ||
903 | cl_assert_equal_i(9, exp.hunks); | |
904 | ||
905 | cl_assert_equal_i(33, exp.lines); | |
906 | cl_assert_equal_i(2, exp.line_ctxt); | |
907 | cl_assert_equal_i(30, exp.line_adds); | |
908 | cl_assert_equal_i(1, exp.line_dels); | |
909 | ||
3ff1d123 | 910 | git_diff_free(diff); |
5d1308f2 RB |
911 | git_tree_free(a); |
912 | } | |
c2e43fb1 | 913 | |
914 | void test_diff_workdir__cannot_diff_against_a_bare_repository(void) | |
915 | { | |
2f8d30be | 916 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
3ff1d123 | 917 | git_diff *diff = NULL; |
c2e43fb1 | 918 | git_tree *tree; |
919 | ||
920 | g_repo = cl_git_sandbox_init("testrepo.git"); | |
921 | ||
5735bf5e | 922 | cl_assert_equal_i( |
56c72b75 | 923 | GIT_EBAREREPO, git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
c2e43fb1 | 924 | |
925 | cl_git_pass(git_repository_head_tree(&tree, g_repo)); | |
5735bf5e RB |
926 | |
927 | cl_assert_equal_i( | |
56c72b75 | 928 | GIT_EBAREREPO, git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); |
c2e43fb1 | 929 | |
930 | git_tree_free(tree); | |
931 | } | |
59a0d772 | 932 | |
933 | void test_diff_workdir__to_null_tree(void) | |
934 | { | |
3ff1d123 | 935 | git_diff *diff; |
59a0d772 | 936 | diff_expects exp; |
2f8d30be | 937 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
59a0d772 | 938 | |
939 | opts.flags = GIT_DIFF_INCLUDE_UNTRACKED | | |
940 | GIT_DIFF_RECURSE_UNTRACKED_DIRS; | |
941 | ||
942 | g_repo = cl_git_sandbox_init("status"); | |
943 | ||
56c72b75 | 944 | cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts)); |
59a0d772 | 945 | |
946 | memset(&exp, 0, sizeof(exp)); | |
947 | ||
948 | cl_git_pass(git_diff_foreach( | |
949 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
950 | ||
951 | cl_assert_equal_i(exp.files, exp.file_status[GIT_DELTA_UNTRACKED]); | |
952 | ||
3ff1d123 | 953 | git_diff_free(diff); |
59a0d772 | 954 | } |
2f8d30be BS |
955 | |
956 | void test_diff_workdir__checks_options_version(void) | |
957 | { | |
3ff1d123 | 958 | git_diff *diff; |
2f8d30be BS |
959 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; |
960 | const git_error *err; | |
961 | ||
962 | g_repo = cl_git_sandbox_init("status"); | |
963 | ||
964 | opts.version = 0; | |
56c72b75 | 965 | cl_git_fail(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts)); |
2f8d30be BS |
966 | err = giterr_last(); |
967 | cl_assert_equal_i(GITERR_INVALID, err->klass); | |
968 | ||
969 | giterr_clear(); | |
970 | opts.version = 1024; | |
56c72b75 | 971 | cl_git_fail(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts)); |
2f8d30be BS |
972 | err = giterr_last(); |
973 | cl_assert_equal_i(GITERR_INVALID, err->klass); | |
974 | } | |
de590550 RB |
975 | |
976 | void test_diff_workdir__can_diff_empty_file(void) | |
977 | { | |
3ff1d123 | 978 | git_diff *diff; |
de590550 RB |
979 | git_tree *tree; |
980 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
981 | struct stat st; | |
3ff1d123 | 982 | git_patch *patch; |
de590550 RB |
983 | |
984 | g_repo = cl_git_sandbox_init("attr_index"); | |
985 | ||
986 | tree = resolve_commit_oid_to_tree(g_repo, "3812cfef3661"); /* HEAD */ | |
987 | ||
988 | /* baseline - make sure there are no outstanding diffs */ | |
989 | ||
990 | cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); | |
991 | cl_assert_equal_i(2, (int)git_diff_num_deltas(diff)); | |
3ff1d123 | 992 | git_diff_free(diff); |
de590550 RB |
993 | |
994 | /* empty contents of file */ | |
995 | ||
996 | cl_git_rewritefile("attr_index/README.txt", ""); | |
997 | cl_git_pass(git_path_lstat("attr_index/README.txt", &st)); | |
998 | cl_assert_equal_i(0, (int)st.st_size); | |
999 | ||
1000 | cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); | |
1001 | cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); | |
1002 | /* diffs are: .gitattributes, README.txt, sub/sub/.gitattributes */ | |
10672e3e | 1003 | cl_git_pass(git_patch_from_diff(&patch, diff, 1)); |
3ff1d123 RB |
1004 | git_patch_free(patch); |
1005 | git_diff_free(diff); | |
de590550 RB |
1006 | |
1007 | /* remove a file altogether */ | |
1008 | ||
1009 | cl_git_pass(p_unlink("attr_index/README.txt")); | |
1010 | cl_assert(!git_path_exists("attr_index/README.txt")); | |
1011 | ||
1012 | cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); | |
1013 | cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); | |
10672e3e | 1014 | cl_git_pass(git_patch_from_diff(&patch, diff, 1)); |
3ff1d123 RB |
1015 | git_patch_free(patch); |
1016 | git_diff_free(diff); | |
8842c75f VM |
1017 | |
1018 | git_tree_free(tree); | |
de590550 | 1019 | } |
b8acb775 | 1020 | |
b8acb775 SS |
1021 | void test_diff_workdir__to_index_issue_1397(void) |
1022 | { | |
1023 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
3ff1d123 | 1024 | git_diff *diff = NULL; |
b8acb775 | 1025 | diff_expects exp; |
b8acb775 SS |
1026 | |
1027 | g_repo = cl_git_sandbox_init("issue_1397"); | |
1028 | ||
1098cfae | 1029 | cl_repo_set_bool(g_repo, "core.autocrlf", true); |
b8acb775 SS |
1030 | |
1031 | opts.context_lines = 3; | |
1032 | opts.interhunk_lines = 1; | |
1033 | ||
1034 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1035 | ||
1098cfae RB |
1036 | memset(&exp, 0, sizeof(exp)); |
1037 | cl_git_pass(git_diff_foreach( | |
1038 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
b8acb775 | 1039 | |
1098cfae RB |
1040 | cl_assert_equal_i(0, exp.files); |
1041 | cl_assert_equal_i(0, exp.hunks); | |
1042 | cl_assert_equal_i(0, exp.lines); | |
b8acb775 | 1043 | |
3ff1d123 | 1044 | git_diff_free(diff); |
b8acb775 | 1045 | diff = NULL; |
b8acb775 | 1046 | |
1098cfae RB |
1047 | cl_git_rewritefile("issue_1397/crlf_file.txt", |
1048 | "first line\r\nsecond line modified\r\nboth with crlf"); | |
b8acb775 SS |
1049 | |
1050 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1051 | ||
1098cfae RB |
1052 | memset(&exp, 0, sizeof(exp)); |
1053 | cl_git_pass(git_diff_foreach( | |
1054 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
b8acb775 | 1055 | |
1098cfae RB |
1056 | cl_assert_equal_i(1, exp.files); |
1057 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
b8acb775 | 1058 | |
1098cfae | 1059 | cl_assert_equal_i(1, exp.hunks); |
b8acb775 | 1060 | |
1098cfae RB |
1061 | cl_assert_equal_i(5, exp.lines); |
1062 | cl_assert_equal_i(3, exp.line_ctxt); | |
1063 | cl_assert_equal_i(1, exp.line_adds); | |
1064 | cl_assert_equal_i(1, exp.line_dels); | |
b8acb775 | 1065 | |
3ff1d123 | 1066 | git_diff_free(diff); |
b8acb775 SS |
1067 | } |
1068 | ||
1069 | void test_diff_workdir__to_tree_issue_1397(void) | |
1070 | { | |
1098cfae | 1071 | const char *a_commit = "7f483a738"; /* the current HEAD */ |
b8acb775 SS |
1072 | git_tree *a; |
1073 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
3ff1d123 RB |
1074 | git_diff *diff = NULL; |
1075 | git_diff *diff2 = NULL; | |
b8acb775 | 1076 | diff_expects exp; |
b8acb775 SS |
1077 | |
1078 | g_repo = cl_git_sandbox_init("issue_1397"); | |
1079 | ||
1098cfae | 1080 | cl_repo_set_bool(g_repo, "core.autocrlf", true); |
b8acb775 SS |
1081 | |
1082 | a = resolve_commit_oid_to_tree(g_repo, a_commit); | |
1083 | ||
1084 | opts.context_lines = 3; | |
1085 | opts.interhunk_lines = 1; | |
1086 | ||
1087 | cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); | |
1088 | ||
1098cfae RB |
1089 | memset(&exp, 0, sizeof(exp)); |
1090 | cl_git_pass(git_diff_foreach( | |
1091 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
b8acb775 | 1092 | |
1098cfae RB |
1093 | cl_assert_equal_i(0, exp.files); |
1094 | cl_assert_equal_i(0, exp.hunks); | |
1095 | cl_assert_equal_i(0, exp.lines); | |
b8acb775 | 1096 | |
3ff1d123 | 1097 | git_diff_free(diff); |
b8acb775 | 1098 | diff = NULL; |
b8acb775 | 1099 | |
b8acb775 SS |
1100 | cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); |
1101 | cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); | |
1102 | cl_git_pass(git_diff_merge(diff, diff2)); | |
3ff1d123 | 1103 | git_diff_free(diff2); |
b8acb775 | 1104 | |
1098cfae RB |
1105 | memset(&exp, 0, sizeof(exp)); |
1106 | cl_git_pass(git_diff_foreach( | |
1107 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
b8acb775 | 1108 | |
1098cfae RB |
1109 | cl_assert_equal_i(0, exp.files); |
1110 | cl_assert_equal_i(0, exp.hunks); | |
1111 | cl_assert_equal_i(0, exp.lines); | |
b8acb775 | 1112 | |
3ff1d123 | 1113 | git_diff_free(diff); |
b8acb775 SS |
1114 | git_tree_free(a); |
1115 | } | |
a66c4bc8 RB |
1116 | |
1117 | void test_diff_workdir__untracked_directory_scenarios(void) | |
1118 | { | |
1119 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
3ff1d123 | 1120 | git_diff *diff = NULL; |
a66c4bc8 RB |
1121 | diff_expects exp; |
1122 | char *pathspec = NULL; | |
1123 | static const char *files0[] = { | |
1124 | "subdir/deleted_file", | |
1125 | "subdir/modified_file", | |
1126 | "subdir/new_file", | |
1127 | NULL | |
1128 | }; | |
1129 | static const char *files1[] = { | |
1130 | "subdir/deleted_file", | |
1131 | "subdir/directory/", | |
1132 | "subdir/modified_file", | |
1133 | "subdir/new_file", | |
1134 | NULL | |
1135 | }; | |
1136 | static const char *files2[] = { | |
1137 | "subdir/deleted_file", | |
1138 | "subdir/directory/more/notignored", | |
1139 | "subdir/modified_file", | |
1140 | "subdir/new_file", | |
1141 | NULL | |
1142 | }; | |
1143 | ||
1144 | g_repo = cl_git_sandbox_init("status"); | |
1145 | cl_git_mkfile("status/.gitignore", "ignored\n"); | |
1146 | ||
1147 | opts.context_lines = 3; | |
1148 | opts.interhunk_lines = 1; | |
1149 | opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; | |
1150 | opts.pathspec.strings = &pathspec; | |
1151 | opts.pathspec.count = 1; | |
1152 | pathspec = "subdir"; | |
1153 | ||
1154 | /* baseline for "subdir" pathspec */ | |
1155 | ||
1156 | memset(&exp, 0, sizeof(exp)); | |
1157 | exp.names = files0; | |
1158 | ||
1159 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1160 | ||
1161 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); | |
1162 | ||
1163 | cl_assert_equal_i(3, exp.files); | |
1164 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1165 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); | |
1166 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
1167 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); | |
1168 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1169 | ||
3ff1d123 | 1170 | git_diff_free(diff); |
a66c4bc8 RB |
1171 | |
1172 | /* empty directory */ | |
1173 | ||
1174 | cl_git_pass(p_mkdir("status/subdir/directory", 0777)); | |
1175 | ||
1176 | memset(&exp, 0, sizeof(exp)); | |
1177 | exp.names = files1; | |
1178 | ||
94ef2a35 RB |
1179 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
1180 | ||
1181 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); | |
1182 | ||
1183 | cl_assert_equal_i(4, exp.files); | |
1184 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1185 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); | |
1186 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
1187 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
1188 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1189 | ||
3ff1d123 | 1190 | git_diff_free(diff); |
94ef2a35 RB |
1191 | |
1192 | /* empty directory in empty directory */ | |
1193 | ||
1194 | cl_git_pass(p_mkdir("status/subdir/directory/empty", 0777)); | |
1195 | ||
1196 | memset(&exp, 0, sizeof(exp)); | |
1197 | exp.names = files1; | |
1198 | ||
a66c4bc8 RB |
1199 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); |
1200 | ||
1201 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); | |
1202 | ||
1203 | cl_assert_equal_i(4, exp.files); | |
1204 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1205 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); | |
1206 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
1207 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
1208 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1209 | ||
3ff1d123 | 1210 | git_diff_free(diff); |
a66c4bc8 RB |
1211 | |
1212 | /* directory with only ignored files */ | |
1213 | ||
1214 | cl_git_pass(p_mkdir("status/subdir/directory/deeper", 0777)); | |
1215 | cl_git_mkfile("status/subdir/directory/deeper/ignored", "ignore me\n"); | |
1216 | ||
1217 | cl_git_pass(p_mkdir("status/subdir/directory/another", 0777)); | |
1218 | cl_git_mkfile("status/subdir/directory/another/ignored", "ignore me\n"); | |
1219 | ||
1220 | memset(&exp, 0, sizeof(exp)); | |
1221 | exp.names = files1; | |
1222 | ||
1223 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1224 | ||
1225 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); | |
1226 | ||
1227 | cl_assert_equal_i(4, exp.files); | |
1228 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1229 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); | |
1230 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
1231 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
1232 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1233 | ||
3ff1d123 | 1234 | git_diff_free(diff); |
a66c4bc8 RB |
1235 | |
1236 | /* directory with ignored directory (contents irrelevant) */ | |
1237 | ||
1238 | cl_git_pass(p_mkdir("status/subdir/directory/more", 0777)); | |
1239 | cl_git_pass(p_mkdir("status/subdir/directory/more/ignored", 0777)); | |
1240 | cl_git_mkfile("status/subdir/directory/more/ignored/notignored", | |
1241 | "inside ignored dir\n"); | |
1242 | ||
1243 | memset(&exp, 0, sizeof(exp)); | |
1244 | exp.names = files1; | |
1245 | ||
1246 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1247 | ||
1248 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); | |
1249 | ||
1250 | cl_assert_equal_i(4, exp.files); | |
1251 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1252 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); | |
1253 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
1254 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
1255 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1256 | ||
3ff1d123 | 1257 | git_diff_free(diff); |
a66c4bc8 RB |
1258 | |
1259 | /* quick version avoids directory scan */ | |
1260 | ||
10672e3e | 1261 | opts.flags = opts.flags | GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS; |
a66c4bc8 RB |
1262 | |
1263 | memset(&exp, 0, sizeof(exp)); | |
1264 | exp.names = files1; | |
1265 | ||
1266 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1267 | ||
1268 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); | |
1269 | ||
1270 | cl_assert_equal_i(4, exp.files); | |
1271 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1272 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); | |
1273 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
1274 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); | |
1275 | cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1276 | ||
3ff1d123 | 1277 | git_diff_free(diff); |
a66c4bc8 RB |
1278 | |
1279 | /* directory with nested non-ignored content */ | |
1280 | ||
10672e3e | 1281 | opts.flags = opts.flags & ~GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS; |
a66c4bc8 RB |
1282 | |
1283 | cl_git_mkfile("status/subdir/directory/more/notignored", | |
1284 | "not ignored deep under untracked\n"); | |
1285 | ||
1286 | memset(&exp, 0, sizeof(exp)); | |
1287 | exp.names = files1; | |
1288 | ||
1289 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1290 | ||
1291 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); | |
1292 | ||
1293 | cl_assert_equal_i(4, exp.files); | |
1294 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1295 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); | |
1296 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
1297 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); | |
1298 | cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1299 | ||
3ff1d123 | 1300 | git_diff_free(diff); |
a66c4bc8 RB |
1301 | |
1302 | /* use RECURSE_UNTRACKED_DIRS to get actual untracked files (no ignores) */ | |
1303 | ||
1304 | opts.flags = opts.flags & ~GIT_DIFF_INCLUDE_IGNORED; | |
1305 | opts.flags = opts.flags | GIT_DIFF_RECURSE_UNTRACKED_DIRS; | |
1306 | ||
1307 | memset(&exp, 0, sizeof(exp)); | |
1308 | exp.names = files2; | |
1309 | ||
1310 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1311 | ||
1312 | cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); | |
1313 | ||
1314 | cl_assert_equal_i(4, exp.files); | |
1315 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1316 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); | |
1317 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); | |
1318 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); | |
1319 | cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1320 | ||
3ff1d123 | 1321 | git_diff_free(diff); |
a66c4bc8 | 1322 | } |
79ef3be4 RB |
1323 | |
1324 | ||
1325 | void test_diff_workdir__untracked_directory_comes_last(void) | |
1326 | { | |
1327 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
3ff1d123 | 1328 | git_diff *diff = NULL; |
79ef3be4 RB |
1329 | |
1330 | g_repo = cl_git_sandbox_init("renames"); | |
1331 | ||
1332 | cl_git_mkfile("renames/.gitignore", "*.ign\n"); | |
1333 | cl_git_pass(p_mkdir("renames/zzz_untracked", 0777)); | |
1334 | cl_git_mkfile("renames/zzz_untracked/an.ign", "ignore me please"); | |
1335 | cl_git_mkfile("renames/zzz_untracked/skip.ign", "ignore me really"); | |
1336 | cl_git_mkfile("renames/zzz_untracked/test.ign", "ignore me now"); | |
1337 | ||
1338 | opts.context_lines = 3; | |
1339 | opts.interhunk_lines = 1; | |
1340 | opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; | |
1341 | ||
1342 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1343 | ||
1344 | cl_assert(diff != NULL); | |
1345 | ||
3ff1d123 | 1346 | git_diff_free(diff); |
79ef3be4 | 1347 | } |
634f10f6 RB |
1348 | |
1349 | void test_diff_workdir__untracked_with_bom(void) | |
1350 | { | |
1351 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
3ff1d123 | 1352 | git_diff *diff = NULL; |
634f10f6 RB |
1353 | const git_diff_delta *delta; |
1354 | ||
1355 | g_repo = cl_git_sandbox_init("empty_standard_repo"); | |
1356 | cl_repo_set_bool(g_repo, "core.autocrlf", true); | |
1357 | ||
1358 | cl_git_write2file("empty_standard_repo/bom.txt", | |
1359 | "\xFF\xFE\x31\x00\x32\x00\x33\x00\x34\x00", 10, O_WRONLY|O_CREAT, 0664); | |
1360 | ||
1361 | opts.flags = | |
10672e3e | 1362 | GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT; |
634f10f6 RB |
1363 | |
1364 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1365 | ||
1366 | cl_assert_equal_i(1, git_diff_num_deltas(diff)); | |
10672e3e | 1367 | cl_assert((delta = git_diff_get_delta(diff, 0)) != NULL); |
634f10f6 | 1368 | cl_assert_equal_i(GIT_DELTA_UNTRACKED, delta->status); |
10672e3e RB |
1369 | |
1370 | /* not known at this point | |
1371 | * cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); | |
1372 | */ | |
634f10f6 | 1373 | |
3ff1d123 | 1374 | git_diff_free(diff); |
634f10f6 | 1375 | } |
5de4ec81 RB |
1376 | |
1377 | void test_diff_workdir__patience_diff(void) | |
1378 | { | |
1379 | git_index *index; | |
1380 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
1381 | git_diff *diff = NULL; | |
1382 | git_patch *patch = NULL; | |
c05cd792 | 1383 | git_buf buf = GIT_BUF_INIT; |
5de4ec81 RB |
1384 | const char *expected_normal = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n-how to create\n-a patience diff\n I did not know\n how to create\n+a patience diff\n another problem\n-I did not know\n-how to create\n a minimal diff\n"; |
1385 | const char *expected_patience = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n+I did not know\n how to create\n a patience diff\n-I did not know\n-how to create\n another problem\n-I did not know\n-how to create\n a minimal diff\n"; | |
1386 | ||
1387 | g_repo = cl_git_sandbox_init("empty_standard_repo"); | |
1388 | cl_repo_set_bool(g_repo, "core.autocrlf", true); | |
1389 | cl_git_pass(git_repository_index(&index, g_repo)); | |
1390 | ||
1391 | cl_git_mkfile( | |
1392 | "empty_standard_repo/test.txt", | |
1393 | "When I wrote this\nI did not know\nhow to create\na patience diff\nI did not know\nhow to create\nanother problem\nI did not know\nhow to create\na minimal diff\n"); | |
1394 | cl_git_pass(git_index_add_bypath(index, "test.txt")); | |
1395 | cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "Base"); | |
187009e2 | 1396 | git_index_free(index); |
5de4ec81 RB |
1397 | |
1398 | cl_git_rewritefile( | |
1399 | "empty_standard_repo/test.txt", | |
1400 | "When I wrote this\nI did not know\nI did not know\nhow to create\na patience diff\nanother problem\na minimal diff\n"); | |
1401 | ||
1402 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1403 | cl_assert_equal_i(1, git_diff_num_deltas(diff)); | |
1404 | cl_git_pass(git_patch_from_diff(&patch, diff, 0)); | |
c05cd792 | 1405 | cl_git_pass(git_patch_to_buf(&buf, patch)); |
5de4ec81 | 1406 | |
c05cd792 NH |
1407 | cl_assert_equal_s(expected_normal, buf.ptr); |
1408 | git_buf_clear(&buf); | |
5de4ec81 RB |
1409 | git_patch_free(patch); |
1410 | git_diff_free(diff); | |
1411 | ||
1412 | opts.flags |= GIT_DIFF_PATIENCE; | |
1413 | ||
1414 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1415 | cl_assert_equal_i(1, git_diff_num_deltas(diff)); | |
1416 | cl_git_pass(git_patch_from_diff(&patch, diff, 0)); | |
c05cd792 | 1417 | cl_git_pass(git_patch_to_buf(&buf, patch)); |
5de4ec81 | 1418 | |
c05cd792 NH |
1419 | cl_assert_equal_s(expected_patience, buf.ptr); |
1420 | git_buf_clear(&buf); | |
1421 | ||
1422 | git_buf_free(&buf); | |
5de4ec81 RB |
1423 | git_patch_free(patch); |
1424 | git_diff_free(diff); | |
1425 | } | |
4bf630b6 RB |
1426 | |
1427 | void test_diff_workdir__with_stale_index(void) | |
1428 | { | |
1429 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
1430 | git_diff *diff = NULL; | |
1431 | git_index *idx = NULL; | |
1432 | diff_expects exp; | |
1433 | ||
1434 | g_repo = cl_git_sandbox_init("status"); | |
1435 | cl_git_pass(git_repository_index(&idx, g_repo)); | |
1436 | ||
1437 | /* make the in-memory index invalid */ | |
1438 | { | |
1439 | git_repository *r2; | |
1440 | git_index *idx2; | |
1441 | cl_git_pass(git_repository_open(&r2, "status")); | |
1442 | cl_git_pass(git_repository_index(&idx2, r2)); | |
1443 | cl_git_pass(git_index_add_bypath(idx2, "new_file")); | |
1444 | cl_git_pass(git_index_add_bypath(idx2, "subdir/new_file")); | |
1445 | cl_git_pass(git_index_remove_bypath(idx2, "staged_new_file")); | |
1446 | cl_git_pass(git_index_remove_bypath(idx2, "staged_changes_file_deleted")); | |
1447 | cl_git_pass(git_index_write(idx2)); | |
1448 | git_index_free(idx2); | |
1449 | git_repository_free(r2); | |
1450 | } | |
1451 | ||
1452 | opts.context_lines = 3; | |
1453 | opts.interhunk_lines = 1; | |
1454 | opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNMODIFIED; | |
1455 | ||
1456 | /* first try with index pointer which should prevent reload */ | |
1457 | ||
1458 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, idx, &opts)); | |
1459 | ||
1460 | memset(&exp, 0, sizeof(exp)); | |
1461 | ||
1462 | cl_git_pass(git_diff_foreach( | |
1463 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
1464 | ||
1465 | cl_assert_equal_i(17, exp.files); | |
1466 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1467 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); | |
1468 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); | |
1469 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1470 | cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNMODIFIED]); | |
1471 | ||
1472 | git_diff_free(diff); | |
1473 | ||
1474 | /* now let's try without the index pointer which should trigger reload */ | |
1475 | ||
1476 | /* two files that were UNTRACKED should have become UNMODIFIED */ | |
1477 | /* one file that was UNMODIFIED should now have become UNTRACKED */ | |
1478 | /* one file that was DELETED should now be gone completely */ | |
1479 | ||
1480 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); | |
1481 | ||
1482 | memset(&exp, 0, sizeof(exp)); | |
1483 | ||
1484 | cl_git_pass(git_diff_foreach( | |
1485 | diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
1486 | ||
61080a95 | 1487 | git_diff_free(diff); |
1488 | ||
4bf630b6 RB |
1489 | cl_assert_equal_i(16, exp.files); |
1490 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1491 | cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); | |
1492 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); | |
1493 | cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1494 | cl_assert_equal_i(6, exp.file_status[GIT_DELTA_UNMODIFIED]); | |
1495 | ||
1496 | git_index_free(idx); | |
1497 | } | |
94fb4aad RB |
1498 | |
1499 | static int touch_file(void *payload, git_buf *path) | |
1500 | { | |
1501 | int fd; | |
1502 | char b; | |
1503 | ||
1504 | GIT_UNUSED(payload); | |
1505 | if (git_path_isdir(path->ptr)) | |
1506 | return 0; | |
1507 | ||
1508 | cl_assert((fd = p_open(path->ptr, O_RDWR)) >= 0); | |
1509 | cl_assert_equal_i(1, p_read(fd, &b, 1)); | |
1510 | cl_must_pass(p_lseek(fd, 0, SEEK_SET)); | |
1511 | cl_must_pass(p_write(fd, &b, 1)); | |
1512 | cl_must_pass(p_close(fd)); | |
1513 | ||
1514 | return 0; | |
1515 | } | |
1516 | ||
1517 | static void basic_diff_status(git_diff **out, const git_diff_options *opts) | |
1518 | { | |
1519 | diff_expects exp; | |
1520 | ||
1521 | cl_git_pass(git_diff_index_to_workdir(out, g_repo, NULL, opts)); | |
1522 | ||
1523 | memset(&exp, 0, sizeof(exp)); | |
1524 | ||
1525 | cl_git_pass(git_diff_foreach( | |
1526 | *out, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); | |
1527 | ||
1528 | cl_assert_equal_i(13, exp.files); | |
1529 | cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); | |
1530 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); | |
1531 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); | |
1532 | cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); | |
1533 | cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); | |
1534 | } | |
1535 | ||
1536 | void test_diff_workdir__can_update_index(void) | |
1537 | { | |
1538 | git_diff_options opts = GIT_DIFF_OPTIONS_INIT; | |
1539 | git_diff *diff = NULL; | |
9c8ed499 | 1540 | git_diff_perfdata perf = GIT_DIFF_PERFDATA_INIT; |
94fb4aad RB |
1541 | |
1542 | g_repo = cl_git_sandbox_init("status"); | |
1543 | ||
1544 | /* touch all the files so stat times are different */ | |
1545 | { | |
1546 | git_buf path = GIT_BUF_INIT; | |
1547 | cl_git_pass(git_buf_sets(&path, "status")); | |
1548 | cl_git_pass(git_path_direach(&path, 0, touch_file, NULL)); | |
1549 | git_buf_free(&path); | |
1550 | } | |
1551 | ||
1552 | opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; | |
1553 | ||
1554 | basic_diff_status(&diff, &opts); | |
9c8ed499 RB |
1555 | |
1556 | cl_git_pass(git_diff_get_perfdata(&perf, diff)); | |
1557 | cl_assert_equal_sz(13 + 3, perf.stat_calls); | |
1558 | cl_assert_equal_sz(5, perf.oid_calculations); | |
94fb4aad RB |
1559 | |
1560 | git_diff_free(diff); | |
1561 | ||
1562 | /* now allow diff to update stat cache */ | |
1563 | opts.flags |= GIT_DIFF_UPDATE_INDEX; | |
1564 | ||
1565 | basic_diff_status(&diff, &opts); | |
9c8ed499 RB |
1566 | |
1567 | cl_git_pass(git_diff_get_perfdata(&perf, diff)); | |
1568 | cl_assert_equal_sz(13 + 3, perf.stat_calls); | |
1569 | cl_assert_equal_sz(5, perf.oid_calculations); | |
94fb4aad RB |
1570 | |
1571 | git_diff_free(diff); | |
1572 | ||
1573 | /* now if we do it again, we should see fewer OID calculations */ | |
1574 | ||
1575 | basic_diff_status(&diff, &opts); | |
9c8ed499 RB |
1576 | |
1577 | cl_git_pass(git_diff_get_perfdata(&perf, diff)); | |
1578 | cl_assert_equal_sz(13 + 3, perf.stat_calls); | |
1579 | cl_assert_equal_sz(0, perf.oid_calculations); | |
94fb4aad RB |
1580 | |
1581 | git_diff_free(diff); | |
1582 | } | |
8af4966d RB |
1583 | |
1584 | #define STR7 "0123456" | |
1585 | #define STR8 "01234567" | |
1586 | #define STR40 STR8 STR8 STR8 STR8 STR8 | |
1587 | #define STR200 STR40 STR40 STR40 STR40 STR40 | |
1588 | #define STR999Z STR200 STR200 STR200 STR200 STR40 STR40 STR40 STR40 \ | |
1589 | STR8 STR8 STR8 STR8 STR7 "\0" | |
1590 | #define STR1000 STR200 STR200 STR200 STR200 STR200 | |
1591 | #define STR3999Z STR1000 STR1000 STR1000 STR999Z | |
1592 | #define STR4000 STR1000 STR1000 STR1000 STR1000 | |
1593 | ||
1594 | static void assert_delta_binary(git_diff *diff, size_t idx, int is_binary) | |
1595 | { | |
1596 | git_patch *patch; | |
1597 | const git_diff_delta *delta; | |
1598 | ||
1599 | cl_git_pass(git_patch_from_diff(&patch, diff, idx)); | |
1600 | delta = git_patch_get_delta(patch); | |
1601 | cl_assert_equal_b((delta->flags & GIT_DIFF_FLAG_BINARY), is_binary); | |
1602 | git_patch_free(patch); | |
1603 | } | |
1604 | ||
1605 | void test_diff_workdir__binary_detection(void) | |
1606 | { | |
1607 | git_index *idx; | |
1608 | git_diff *diff = NULL; | |
1609 | git_buf b = GIT_BUF_INIT; | |
1610 | int i; | |
1611 | git_buf data[10] = { | |
1612 | { "1234567890", 0, 0 }, /* 0 - all ascii text control */ | |
1613 | { "Åü†HøπΩ", 0, 0 }, /* 1 - UTF-8 multibyte text */ | |
1614 | { "\xEF\xBB\xBFÜ⤒ƒ8£€", 0, 0 }, /* 2 - UTF-8 with BOM */ | |
1615 | { STR999Z, 0, 1000 }, /* 3 - ASCII with NUL at 1000 */ | |
1616 | { STR3999Z, 0, 4000 }, /* 4 - ASCII with NUL at 4000 */ | |
1617 | { STR4000 STR3999Z "x", 0, 8001 }, /* 5 - ASCII with NUL at 8000 */ | |
1618 | { STR4000 STR4000 "\0", 0, 8001 }, /* 6 - ASCII with NUL at 8001 */ | |
1619 | { "\x00\xDC\x00\x6E\x21\x39\xFE\x0E\x00\x63\x00\xF8" | |
1620 | "\x00\x64\x00\x65\x20\x48", 0, 18 }, /* 7 - UTF-16 text */ | |
1621 | { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d" | |
1622 | "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d", | |
1623 | 0, 26 }, /* 8 - All non-printable characters (no NUL) */ | |
1624 | { "Hello \x01\x02\x03\x04\x05\x06 World!\x01\x02\x03\x04" | |
1625 | "\x05\x06\x07", 0, 26 }, /* 9 - 50-50 non-printable (no NUL) */ | |
1626 | }; | |
1627 | ||
1628 | g_repo = cl_git_sandbox_init("empty_standard_repo"); | |
1629 | cl_git_pass(git_repository_index(&idx, g_repo)); | |
1630 | ||
1631 | /* We start with ASCII in index and test data in workdir, | |
1632 | * then we will try with test data in index and ASCII in workdir. | |
1633 | */ | |
1634 | ||
1635 | cl_git_pass(git_buf_sets(&b, "empty_standard_repo/0")); | |
1636 | for (i = 0; i < 10; ++i) { | |
1637 | b.ptr[b.size - 1] = '0' + i; | |
1638 | cl_git_mkfile(b.ptr, "baseline"); | |
1639 | cl_git_pass(git_index_add_bypath(idx, &b.ptr[b.size - 1])); | |
1640 | ||
1641 | if (data[i].size == 0) | |
1642 | data[i].size = strlen(data[i].ptr); | |
1643 | cl_git_write2file( | |
1644 | b.ptr, data[i].ptr, data[i].size, O_WRONLY|O_TRUNC, 0664); | |
1645 | } | |
1646 | git_index_write(idx); | |
1647 | ||
1648 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); | |
1649 | ||
1650 | cl_assert_equal_i(10, git_diff_num_deltas(diff)); | |
1651 | ||
1652 | /* using diff binary detection (i.e. looking for NUL byte) */ | |
1653 | assert_delta_binary(diff, 0, false); | |
1654 | assert_delta_binary(diff, 1, false); | |
1655 | assert_delta_binary(diff, 2, false); | |
1656 | assert_delta_binary(diff, 3, true); | |
1657 | assert_delta_binary(diff, 4, true); | |
1658 | assert_delta_binary(diff, 5, true); | |
1659 | assert_delta_binary(diff, 6, false); | |
1660 | assert_delta_binary(diff, 7, true); | |
1661 | assert_delta_binary(diff, 8, false); | |
1662 | assert_delta_binary(diff, 9, false); | |
1663 | /* The above have been checked to match command-line Git */ | |
1664 | ||
1665 | git_diff_free(diff); | |
1666 | ||
1667 | cl_git_pass(git_buf_sets(&b, "empty_standard_repo/0")); | |
1668 | for (i = 0; i < 10; ++i) { | |
1669 | b.ptr[b.size - 1] = '0' + i; | |
1670 | cl_git_pass(git_index_add_bypath(idx, &b.ptr[b.size - 1])); | |
1671 | ||
1672 | cl_git_write2file(b.ptr, "baseline\n", 9, O_WRONLY|O_TRUNC, 0664); | |
1673 | } | |
1674 | git_index_write(idx); | |
1675 | ||
1676 | cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); | |
1677 | ||
1678 | cl_assert_equal_i(10, git_diff_num_deltas(diff)); | |
1679 | ||
1680 | /* using diff binary detection (i.e. looking for NUL byte) */ | |
1681 | assert_delta_binary(diff, 0, false); | |
1682 | assert_delta_binary(diff, 1, false); | |
1683 | assert_delta_binary(diff, 2, false); | |
1684 | assert_delta_binary(diff, 3, true); | |
1685 | assert_delta_binary(diff, 4, true); | |
1686 | assert_delta_binary(diff, 5, true); | |
1687 | assert_delta_binary(diff, 6, false); | |
1688 | assert_delta_binary(diff, 7, true); | |
1689 | assert_delta_binary(diff, 8, false); | |
1690 | assert_delta_binary(diff, 9, false); | |
1691 | ||
1692 | git_diff_free(diff); | |
1693 | ||
1694 | git_index_free(idx); | |
1695 | git_buf_free(&b); | |
1696 | } |