diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/diff.h | 7 | ||||
-rw-r--r-- | src/diff_patch.c | 49 | ||||
-rw-r--r-- | src/diff_print.c | 79 |
3 files changed, 87 insertions, 48 deletions
diff --git a/src/diff.h b/src/diff.h index d09a130bc..ff480324f 100644 --- a/src/diff.h +++ b/src/diff.h @@ -81,6 +81,13 @@ extern const char *git_diff_delta__path(const git_diff_delta *delta); extern bool git_diff_delta__should_skip( const git_diff_options *opts, const git_diff_delta *delta); +extern int git_diff_delta__format_file_header( + git_buf *out, + const git_diff_delta *delta, + const char *oldpfx, + const char *newpfx, + int oid_strlen); + extern int git_diff__oid_for_file( git_repository *, const char *, uint16_t, git_off_t, git_oid *); diff --git a/src/diff_patch.c b/src/diff_patch.c index 5febc883c..6f8ea2d3d 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -42,7 +42,7 @@ struct git_diff_patch { git_array_t(diff_patch_hunk) hunks; git_array_t(diff_patch_line) lines; size_t oldno, newno; - size_t content_size, context_size; + size_t content_size, context_size, header_size; git_pool flattened; }; @@ -806,7 +806,11 @@ notfound: return diff_error_outofrange(thing); } -size_t git_diff_patch_size(git_diff_patch *patch, int include_context) +size_t git_diff_patch_size( + git_diff_patch *patch, + int include_context, + int include_hunk_headers, + int include_file_headers) { size_t out; @@ -817,6 +821,21 @@ size_t git_diff_patch_size(git_diff_patch *patch, int include_context) if (!include_context) out -= patch->context_size; + if (include_hunk_headers) + out += patch->header_size; + + if (include_file_headers) { + git_buf file_header = GIT_BUF_INIT; + + if (git_diff_delta__format_file_header( + &file_header, patch->delta, NULL, NULL, 0) < 0) + giterr_clear(); + else + out += git_buf_len(&file_header); + + git_buf_free(&file_header); + } + return out; } @@ -914,6 +933,8 @@ static int diff_patch_hunk_cb( hunk->header[header_len] = '\0'; hunk->header_len = header_len; + patch->header_size += header_len; + hunk->line_start = git_array_size(patch->lines); hunk->line_count = 0; @@ -934,6 +955,7 @@ static int diff_patch_line_cb( git_diff_patch *patch = payload; diff_patch_hunk *hunk; diff_patch_line *line; + const char *content_end = content + content_len; GIT_UNUSED(delta); GIT_UNUSED(range); @@ -948,38 +970,43 @@ static int diff_patch_line_cb( line->len = content_len; line->origin = line_origin; - patch->content_size += content_len + 1; /* +1 for line_origin */ - - if (line_origin == GIT_DIFF_LINE_CONTEXT || - line_origin == GIT_DIFF_LINE_CONTEXT_EOFNL) - patch->context_size += content_len + 1; - /* do some bookkeeping so we can provide old/new line numbers */ - for (line->lines = 0; content_len > 0; --content_len) { + line->lines = 0; + while (content < content_end) if (*content++ == '\n') ++line->lines; - } + + patch->content_size += content_len; switch (line_origin) { case GIT_DIFF_LINE_ADDITION: + patch->content_size += 1; case GIT_DIFF_LINE_DEL_EOFNL: line->oldno = -1; line->newno = patch->newno; patch->newno += line->lines; break; case GIT_DIFF_LINE_DELETION: + patch->content_size += 1; case GIT_DIFF_LINE_ADD_EOFNL: line->oldno = patch->oldno; line->newno = -1; patch->oldno += line->lines; break; - default: + case GIT_DIFF_LINE_CONTEXT: + patch->content_size += 1; + patch->context_size += 1; + case GIT_DIFF_LINE_CONTEXT_EOFNL: + patch->context_size += content_len; line->oldno = patch->oldno; line->newno = patch->newno; patch->oldno += line->lines; patch->newno += line->lines; break; + default: + assert(false); + break; } hunk->line_count++; diff --git a/src/diff_print.c b/src/diff_print.c index 0de548813..cdb813176 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -198,13 +198,13 @@ int git_diff_print_raw( return error; } -static int diff_print_oid_range(diff_print_info *pi, const git_diff_delta *delta) +static int diff_print_oid_range( + git_buf *out, const git_diff_delta *delta, int oid_strlen) { - git_buf *out = pi->buf; char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1]; - git_oid_tostr(start_oid, pi->oid_strlen, &delta->old_file.oid); - git_oid_tostr(end_oid, pi->oid_strlen, &delta->new_file.oid); + git_oid_tostr(start_oid, oid_strlen, &delta->old_file.oid); + git_oid_tostr(end_oid, oid_strlen, &delta->new_file.oid); /* TODO: Match git diff more closely */ if (delta->old_file.mode == delta->new_file.mode) { @@ -228,35 +228,29 @@ static int diff_print_oid_range(diff_print_info *pi, const git_diff_delta *delta return 0; } -static int diff_print_patch_file( - const git_diff_delta *delta, float progress, void *data) +int git_diff_delta__format_file_header( + git_buf *out, + const git_diff_delta *delta, + const char *oldpfx, + const char *newpfx, + int oid_strlen) { - diff_print_info *pi = data; - const char *oldpfx = pi->diff ? pi->diff->opts.old_prefix : NULL; const char *oldpath = delta->old_file.path; - const char *newpfx = pi->diff ? pi->diff->opts.new_prefix : NULL; const char *newpath = delta->new_file.path; - uint32_t opts_flags = pi->diff ? pi->diff->opts.flags : GIT_DIFF_NORMAL; - - GIT_UNUSED(progress); - - if (S_ISDIR(delta->new_file.mode) || - delta->status == GIT_DELTA_UNMODIFIED || - delta->status == GIT_DELTA_IGNORED || - (delta->status == GIT_DELTA_UNTRACKED && - (opts_flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0)) - return 0; if (!oldpfx) oldpfx = DIFF_OLD_PREFIX_DEFAULT; if (!newpfx) newpfx = DIFF_NEW_PREFIX_DEFAULT; + if (!oid_strlen) + oid_strlen = GIT_ABBREV_DEFAULT + 1; - git_buf_clear(pi->buf); - git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", - oldpfx, delta->old_file.path, newpfx, delta->new_file.path); + git_buf_clear(out); + + git_buf_printf(out, "diff --git %s%s %s%s\n", + oldpfx, oldpath, newpfx, newpath); - if (diff_print_oid_range(pi, delta) < 0) + if (diff_print_oid_range(out, delta, oid_strlen) < 0) return -1; if (git_oid_iszero(&delta->old_file.oid)) { @@ -269,28 +263,39 @@ static int diff_print_patch_file( } if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) { - git_buf_printf(pi->buf, "--- %s%s\n", oldpfx, oldpath); - git_buf_printf(pi->buf, "+++ %s%s\n", newpfx, newpath); + git_buf_printf(out, "--- %s%s\n", oldpfx, oldpath); + git_buf_printf(out, "+++ %s%s\n", newpfx, newpath); + } else { + git_buf_printf( + out, "Binary files %s%s and %s%s differ\n", + oldpfx, oldpath, newpfx, newpath); } - if (git_buf_oom(pi->buf)) - return -1; + return git_buf_oom(out) ? -1 : 0; +} - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) - return callback_error(); +static int diff_print_patch_file( + const git_diff_delta *delta, float progress, void *data) +{ + diff_print_info *pi = data; + const char *oldpfx = pi->diff ? pi->diff->opts.old_prefix : NULL; + const char *newpfx = pi->diff ? pi->diff->opts.new_prefix : NULL; + uint32_t opts_flags = pi->diff ? pi->diff->opts.flags : GIT_DIFF_NORMAL; - if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) + GIT_UNUSED(progress); + + if (S_ISDIR(delta->new_file.mode) || + delta->status == GIT_DELTA_UNMODIFIED || + delta->status == GIT_DELTA_IGNORED || + (delta->status == GIT_DELTA_UNTRACKED && + (opts_flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0)) return 0; - git_buf_clear(pi->buf); - git_buf_printf( - pi->buf, "Binary files %s%s and %s%s differ\n", - oldpfx, oldpath, newpfx, newpath); - if (git_buf_oom(pi->buf)) + if (git_diff_delta__format_file_header( + pi->buf, delta, oldpfx, newpfx, pi->oid_strlen) < 0) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_BINARY, + if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) return callback_error(); |