summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-11-28 14:41:58 +0100
committerGitHub <noreply@github.com>2019-11-28 14:41:58 +0100
commitfb439c975a2de33f5b0c317f3fdea49dc94b27dc (patch)
treeae22d26f1bc5d91f947577c291309cb57c2ebd77 /src
parent61176a9b363b1274c101d82f36cbf9cb71a10f74 (diff)
parentece5bb5e7d6e35e50096bac3d7bf17342daaec77 (diff)
downloadlibgit2-fb439c975a2de33f5b0c317f3fdea49dc94b27dc.tar.gz
Merge pull request #5306 from herrerog/patchid
diff: complete support for git patchid
Diffstat (limited to 'src')
-rw-r--r--src/diff.c82
-rw-r--r--src/diff.h3
-rw-r--r--src/diff_print.c26
-rw-r--r--src/patch.c2
-rw-r--r--src/patch_parse.c13
5 files changed, 52 insertions, 74 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)
diff --git a/src/diff.h b/src/diff.h
index 93374b96e..1a4ee47e0 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -57,7 +57,8 @@ extern int git_diff_delta__format_file_header(
const git_diff_delta *delta,
const char *oldpfx,
const char *newpfx,
- int oid_strlen);
+ int oid_strlen,
+ bool print_index);
extern int git_diff_delta__cmp(const void *a, const void *b);
extern int git_diff_delta__casecmp(const void *a, const void *b);
diff --git a/src/diff_print.c b/src/diff_print.c
index f1aac5eb0..369e5c1e6 100644
--- a/src/diff_print.c
+++ b/src/diff_print.c
@@ -269,7 +269,8 @@ static int diff_print_modes(
}
static int diff_print_oid_range(
- git_buf *out, const git_diff_delta *delta, int id_strlen)
+ git_buf *out, const git_diff_delta *delta, int id_strlen,
+ bool print_index)
{
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
@@ -293,8 +294,9 @@ static int diff_print_oid_range(
git_oid_tostr(end_oid, id_strlen + 1, &delta->new_file.id);
if (delta->old_file.mode == delta->new_file.mode) {
- git_buf_printf(out, "index %s..%s %o\n",
- start_oid, end_oid, delta->old_file.mode);
+ if (print_index)
+ git_buf_printf(out, "index %s..%s %o\n",
+ start_oid, end_oid, delta->old_file.mode);
} else {
if (delta->old_file.mode == 0)
git_buf_printf(out, "new file mode %o\n", delta->new_file.mode);
@@ -303,7 +305,8 @@ static int diff_print_oid_range(
else
diff_print_modes(out, delta);
- git_buf_printf(out, "index %s..%s\n", start_oid, end_oid);
+ if (print_index)
+ git_buf_printf(out, "index %s..%s\n", start_oid, end_oid);
}
return git_buf_oom(out) ? -1 : 0;
@@ -400,7 +403,8 @@ int git_diff_delta__format_file_header(
const git_diff_delta *delta,
const char *oldpfx,
const char *newpfx,
- int id_strlen)
+ int id_strlen,
+ bool print_index)
{
git_buf old_path = GIT_BUF_INIT, new_path = GIT_BUF_INIT;
bool unchanged = delta_is_unchanged(delta);
@@ -431,7 +435,8 @@ int git_diff_delta__format_file_header(
}
if (!unchanged) {
- if ((error = diff_print_oid_range(out, delta, id_strlen)) < 0)
+ if ((error = diff_print_oid_range(out, delta,
+ id_strlen, print_index)) < 0)
goto done;
if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0)
@@ -566,6 +571,7 @@ static int diff_print_patch_file(
(pi->flags & GIT_DIFF_FORCE_BINARY);
bool show_binary = !!(pi->flags & GIT_DIFF_SHOW_BINARY);
int id_strlen = pi->id_strlen;
+ bool print_index = (pi->format != GIT_DIFF_FORMAT_PATCH_ID);
if (binary && show_binary)
id_strlen = delta->old_file.id_abbrev ? delta->old_file.id_abbrev :
@@ -582,7 +588,8 @@ static int diff_print_patch_file(
return 0;
if ((error = git_diff_delta__format_file_header(
- pi->buf, delta, oldpfx, newpfx, id_strlen)) < 0)
+ pi->buf, delta, oldpfx, newpfx,
+ id_strlen, print_index)) < 0)
return error;
pi->line.origin = GIT_DIFF_LINE_FILE_HDR;
@@ -670,6 +677,11 @@ int git_diff_print(
print_hunk = diff_print_patch_hunk;
print_line = diff_print_patch_line;
break;
+ case GIT_DIFF_FORMAT_PATCH_ID:
+ print_file = diff_print_patch_file;
+ print_binary = diff_print_patch_binary;
+ print_line = diff_print_patch_line;
+ break;
case GIT_DIFF_FORMAT_PATCH_HEADER:
print_file = diff_print_patch_file;
break;
diff --git a/src/patch.c b/src/patch.c
index d19e6833e..82181bb3d 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -79,7 +79,7 @@ size_t git_patch_size(
git_buf file_header = GIT_BUF_INIT;
if (git_diff_delta__format_file_header(
- &file_header, patch->delta, NULL, NULL, 0) < 0)
+ &file_header, patch->delta, NULL, NULL, 0, true) < 0)
git_error_clear();
else
out += git_buf_len(&file_header);
diff --git a/src/patch_parse.c b/src/patch_parse.c
index 35fd65a0d..dad1813fa 100644
--- a/src/patch_parse.c
+++ b/src/patch_parse.c
@@ -231,9 +231,9 @@ static int parse_header_git_deletedfilemode(
git_patch_parsed *patch,
git_patch_parse_ctx *ctx)
{
- git__free((char *)patch->base.delta->old_file.path);
+ git__free((char *)patch->base.delta->new_file.path);
- patch->base.delta->old_file.path = NULL;
+ patch->base.delta->new_file.path = NULL;
patch->base.delta->status = GIT_DELTA_DELETED;
patch->base.delta->nfiles = 1;
@@ -244,9 +244,9 @@ static int parse_header_git_newfilemode(
git_patch_parsed *patch,
git_patch_parse_ctx *ctx)
{
- git__free((char *)patch->base.delta->new_file.path);
+ git__free((char *)patch->base.delta->old_file.path);
- patch->base.delta->new_file.path = NULL;
+ patch->base.delta->old_file.path = NULL;
patch->base.delta->status = GIT_DELTA_ADDED;
patch->base.delta->nfiles = 1;
@@ -884,6 +884,11 @@ static int parse_patch_binary_nodata(
if (!old || !new)
return git_parse_err("corrupt binary data without paths at line %"PRIuZ, ctx->parse_ctx.line_num);
+ if (patch->base.delta->status == GIT_DELTA_ADDED)
+ old = "/dev/null";
+ else if (patch->base.delta->status == GIT_DELTA_DELETED)
+ new = "/dev/null";
+
if (git_parse_advance_expected_str(&ctx->parse_ctx, "Binary files ") < 0 ||
git_parse_advance_expected_str(&ctx->parse_ctx, old) < 0 ||
git_parse_advance_expected_str(&ctx->parse_ctx, " and ") < 0 ||