Commit ace3508f by Patrick Steinhardt

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.
parent 41019152
......@@ -409,39 +409,25 @@ int git_diff_foreach(
void *payload)
{
int error = 0;
git_xdiff_output xo;
git_diff_delta *delta;
size_t idx;
git_patch_generated patch;
if ((error = diff_required(diff, "git_diff_foreach")) < 0)
return error;
memset(&xo, 0, sizeof(xo));
memset(&patch, 0, sizeof(patch));
diff_output_init(
&xo.output, &diff->opts, file_cb, binary_cb, hunk_cb, data_cb, payload);
git_xdiff_init(&xo, &diff->opts);
git_vector_foreach(&diff->deltas, idx, patch.base.delta) {
git_vector_foreach(&diff->deltas, idx, delta) {
git_patch *patch;
/* check flags against patch status */
if (git_diff_delta__should_skip(&diff->opts, patch.base.delta))
if (git_diff_delta__should_skip(&diff->opts, delta))
continue;
if (binary_cb || hunk_cb || data_cb) {
if ((error = patch_generated_init(&patch, diff, idx)) != 0 ||
(error = patch_generated_load(&patch, &xo.output)) != 0) {
git_patch_free(&patch.base);
return error;
}
}
if ((error = patch_generated_invoke_file_callback(&patch, &xo.output)) == 0) {
if (binary_cb || hunk_cb || data_cb)
error = patch_generated_create(&patch, &xo.output);
}
if ((error = git_patch_from_diff(&patch, diff, idx)) != 0)
break;
git_patch_free(&patch.base);
error = git_patch__invoke_callbacks(patch, file_cb, binary_cb,
hunk_cb, data_cb, payload);
git_patch_free(patch);
if (error)
break;
......
......@@ -196,3 +196,32 @@ void test_diff_parse__get_patch_from_diff(void)
cl_git_sandbox_cleanup();
}
static int file_cb(const git_diff_delta *delta, float progress, void *payload)
{
int *called = (int *) payload;
GIT_UNUSED(delta);
GIT_UNUSED(progress);
(*called)++;
return 0;
}
void test_diff_parse__foreach_works_with_parsed_patch(void)
{
const char patch[] =
"diff --git a/obj1 b/obj2\n"
"index 1234567..7654321 10644\n"
"--- a/obj1\n"
"+++ b/obj2\n"
"@@ -1 +1 @@\n"
"-abcde\n"
"+12345\n";
int called = 0;
git_diff *diff;
cl_git_pass(git_diff_from_buffer(&diff, patch, strlen(patch)));
cl_git_pass(git_diff_foreach(diff, file_cb, NULL, NULL, NULL, &called));
cl_assert_equal_i(called, 1);
git_diff_free(diff);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment