Skip to content

Commit ace3508

Browse files
committed
patch_generate: fix git_diff_foreach only working with generated diffs
The current logic of `git_diff_foreach` makes the assumption that all diffs passed in are actually derived from generated diffs. With these assumptions we try to derive the actual diff by inspecting either the working directory files or blobs of a repository. This obviously cannot work for diffs parsed from a file, where we do not necessarily have a repository at hand. Since the introduced split of parsed and generated patches, there are multiple functions which help us to handle patches generically, being indifferent from where they stem from. Use these functions and remove the old logic specific to generated patches. This allows re-using the same code for invoking the callbacks on the deltas.
1 parent 4101915 commit ace3508

File tree

2 files changed

+38
-23
lines changed

2 files changed

+38
-23
lines changed

src/patch_generate.c

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -409,39 +409,25 @@ int git_diff_foreach(
409409
void *payload)
410410
{
411411
int error = 0;
412-
git_xdiff_output xo;
412+
git_diff_delta *delta;
413413
size_t idx;
414-
git_patch_generated patch;
415414

416415
if ((error = diff_required(diff, "git_diff_foreach")) < 0)
417416
return error;
418417

419-
memset(&xo, 0, sizeof(xo));
420-
memset(&patch, 0, sizeof(patch));
421-
diff_output_init(
422-
&xo.output, &diff->opts, file_cb, binary_cb, hunk_cb, data_cb, payload);
423-
git_xdiff_init(&xo, &diff->opts);
424-
425-
git_vector_foreach(&diff->deltas, idx, patch.base.delta) {
418+
git_vector_foreach(&diff->deltas, idx, delta) {
419+
git_patch *patch;
426420

427421
/* check flags against patch status */
428-
if (git_diff_delta__should_skip(&diff->opts, patch.base.delta))
422+
if (git_diff_delta__should_skip(&diff->opts, delta))
429423
continue;
430424

431-
if (binary_cb || hunk_cb || data_cb) {
432-
if ((error = patch_generated_init(&patch, diff, idx)) != 0 ||
433-
(error = patch_generated_load(&patch, &xo.output)) != 0) {
434-
git_patch_free(&patch.base);
435-
return error;
436-
}
437-
}
438-
439-
if ((error = patch_generated_invoke_file_callback(&patch, &xo.output)) == 0) {
440-
if (binary_cb || hunk_cb || data_cb)
441-
error = patch_generated_create(&patch, &xo.output);
442-
}
425+
if ((error = git_patch_from_diff(&patch, diff, idx)) != 0)
426+
break;
443427

444-
git_patch_free(&patch.base);
428+
error = git_patch__invoke_callbacks(patch, file_cb, binary_cb,
429+
hunk_cb, data_cb, payload);
430+
git_patch_free(patch);
445431

446432
if (error)
447433
break;

tests/diff/parse.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,32 @@ void test_diff_parse__get_patch_from_diff(void)
196196

197197
cl_git_sandbox_cleanup();
198198
}
199+
200+
static int file_cb(const git_diff_delta *delta, float progress, void *payload)
201+
{
202+
int *called = (int *) payload;
203+
GIT_UNUSED(delta);
204+
GIT_UNUSED(progress);
205+
(*called)++;
206+
return 0;
207+
}
208+
209+
void test_diff_parse__foreach_works_with_parsed_patch(void)
210+
{
211+
const char patch[] =
212+
"diff --git a/obj1 b/obj2\n"
213+
"index 1234567..7654321 10644\n"
214+
"--- a/obj1\n"
215+
"+++ b/obj2\n"
216+
"@@ -1 +1 @@\n"
217+
"-abcde\n"
218+
"+12345\n";
219+
int called = 0;
220+
git_diff *diff;
221+
222+
cl_git_pass(git_diff_from_buffer(&diff, patch, strlen(patch)));
223+
cl_git_pass(git_diff_foreach(diff, file_cb, NULL, NULL, NULL, &called));
224+
cl_assert_equal_i(called, 1);
225+
226+
git_diff_free(diff);
227+
}

0 commit comments

Comments
 (0)