summaryrefslogtreecommitdiff
path: root/src/diff.c
diff options
context:
space:
mode:
authorGregory Herrero <gregory.herrero@oracle.com>2019-11-07 14:10:00 +0100
committerGregory Herrero <gregory.herrero@oracle.com>2019-11-28 14:17:50 +0100
commitece5bb5e7d6e35e50096bac3d7bf17342daaec77 (patch)
tree27f42b0b9f8fd8ac067bbfb2b780f4e72d3bae9a /src/diff.c
parent048e94adbba3c21b9ad739640cce11a8b387df48 (diff)
downloadlibgit2-ece5bb5e7d6e35e50096bac3d7bf17342daaec77.tar.gz
diff: make patchid computation work with all types of commits.
Current implementation of patchid is not computing a correct patchid when given a patch where, for example, a new file is added or removed. Some more corner cases need to be handled to have same behavior as git patch-id command. Add some more tests to cover those corner cases. Signed-off-by: Gregory Herrero <gregory.herrero@oracle.com>
Diffstat (limited to 'src/diff.c')
-rw-r--r--src/diff.c82
1 files changed, 21 insertions, 61 deletions
diff --git a/src/diff.c b/src/diff.c
index 15a32ed48..47f49d949 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -426,81 +426,38 @@ static void strip_spaces(git_buf *buf)
git_buf_truncate(buf, len);
}
-static int file_cb(
+int git_diff_patchid_print_callback__to_buf(
const git_diff_delta *delta,
- float progress,
+ const git_diff_hunk *hunk,
+ const git_diff_line *line,
void *payload)
{
struct patch_id_args *args = (struct patch_id_args *) payload;
git_buf buf = GIT_BUF_INIT;
- int error;
-
- GIT_UNUSED(progress);
+ int error = 0;
- if (!args->first_file &&
- (error = flush_hunk(&args->result, &args->ctx)) < 0)
- goto out;
- args->first_file = 0;
-
- if ((error = git_buf_printf(&buf,
- "diff--gita/%sb/%s---a/%s+++b/%s",
- delta->old_file.path,
- delta->new_file.path,
- delta->old_file.path,
- delta->new_file.path)) < 0)
+ if (line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL ||
+ line->origin == GIT_DIFF_LINE_ADD_EOFNL ||
+ line->origin == GIT_DIFF_LINE_DEL_EOFNL)
goto out;
- strip_spaces(&buf);
-
- if ((error = git_hash_update(&args->ctx, buf.ptr, buf.size)) < 0)
+ if ((error = git_diff_print_callback__to_buf(delta, hunk,
+ line, &buf)) < 0)
goto out;
-out:
- git_buf_dispose(&buf);
- return error;
-}
-
-static int patchid_line_cb(
- const git_diff_delta *delta,
- const git_diff_hunk *hunk,
- const git_diff_line *line,
- void *payload)
-{
- struct patch_id_args *args = (struct patch_id_args *) payload;
- git_buf buf = GIT_BUF_INIT;
- int error;
-
- GIT_UNUSED(delta);
- GIT_UNUSED(hunk);
-
- switch (line->origin) {
- case GIT_DIFF_LINE_ADDITION:
- git_buf_putc(&buf, '+');
- break;
- case GIT_DIFF_LINE_DELETION:
- git_buf_putc(&buf, '-');
- break;
- case GIT_DIFF_LINE_CONTEXT:
- break;
- case GIT_DIFF_LINE_CONTEXT_EOFNL:
- case GIT_DIFF_LINE_ADD_EOFNL:
- case GIT_DIFF_LINE_DEL_EOFNL:
- /*
- * Ignore EOF without newlines for patch IDs as whitespace is
- * not supposed to be significant.
- */
- return 0;
- default:
- git_error_set(GIT_ERROR_PATCH, "invalid line origin for patch");
- return -1;
- }
-
- git_buf_put(&buf, line->content, line->content_len);
strip_spaces(&buf);
+ if (line->origin == GIT_DIFF_LINE_FILE_HDR &&
+ !args->first_file &&
+ (error = flush_hunk(&args->result, &args->ctx) < 0))
+ goto out;
+
if ((error = git_hash_update(&args->ctx, buf.ptr, buf.size)) < 0)
goto out;
+ if (line->origin == GIT_DIFF_LINE_FILE_HDR && args->first_file)
+ args->first_file = 0;
+
out:
git_buf_dispose(&buf);
return error;
@@ -526,7 +483,10 @@ int git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opt
if ((error = git_hash_ctx_init(&args.ctx)) < 0)
goto out;
- if ((error = git_diff_foreach(diff, file_cb, NULL, NULL, patchid_line_cb, &args)) < 0)
+ if ((error = git_diff_print(diff,
+ GIT_DIFF_FORMAT_PATCH_ID,
+ git_diff_patchid_print_callback__to_buf,
+ &args)) < 0)
goto out;
if ((error = (flush_hunk(&args.result, &args.ctx))) < 0)