From cb8a79617b15e347f26d21cedde0f2b8670c1876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicent=20Mart=C3=AD?= Date: Wed, 7 Mar 2012 00:02:55 +0100 Subject: error-handling: Repository This also includes droping `git_buf_lasterror` because it makes no sense in the new system. Note that in most of the places were it has been dropped, the code needs cleanup. I.e. GIT_ENOMEM is going away, so instead it should return a generic `-1` and obviously not throw anything. --- src/diff_output.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'src/diff_output.c') diff --git a/src/diff_output.c b/src/diff_output.c index 5e7486ab8..9c34dcf71 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -482,8 +482,8 @@ static int print_compact(void *data, git_diff_delta *delta, float progress) else git_buf_printf(pi->buf, "%c\t%s\n", code, delta->old.path); - if (git_buf_lasterror(pi->buf) != GIT_SUCCESS) - return git_buf_lasterror(pi->buf); + if (git_buf_oom(pi->buf) == true) + return GIT_ENOMEM; return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr); } @@ -534,7 +534,10 @@ static int print_oid_range(diff_print_info *pi, git_diff_delta *delta) git_buf_printf(pi->buf, "index %s..%s\n", start_oid, end_oid); } - return git_buf_lasterror(pi->buf); + if (git_buf_oom(pi->buf)) + return GIT_ENOMEM; + + return 0; } static int print_patch_file(void *data, git_diff_delta *delta, float progress) @@ -567,8 +570,8 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress) git_buf_printf(pi->buf, "+++ %s%s\n", newpfx, newpath); } - if (git_buf_lasterror(pi->buf) != GIT_SUCCESS) - return git_buf_lasterror(pi->buf); + if (git_buf_oom(pi->buf)) + return GIT_ENOMEM; error = pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr); if (error != GIT_SUCCESS || delta->binary != 1) @@ -578,8 +581,8 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress) git_buf_printf( pi->buf, "Binary files %s%s and %s%s differ\n", oldpfx, oldpath, newpfx, newpath); - if (git_buf_lasterror(pi->buf) != GIT_SUCCESS) - return git_buf_lasterror(pi->buf); + if (git_buf_oom(pi->buf)) + return GIT_ENOMEM; return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_BINARY, pi->buf->ptr); } @@ -601,7 +604,7 @@ static int print_patch_hunk( if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) == GIT_SUCCESS) return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_HUNK_HDR, pi->buf->ptr); else - return git_buf_lasterror(pi->buf); + return GIT_ENOMEM; } static int print_patch_line( @@ -624,8 +627,8 @@ static int print_patch_line( else if (content_len > 0) git_buf_printf(pi->buf, "%.*s", (int)content_len, content); - if (git_buf_lasterror(pi->buf) != GIT_SUCCESS) - return git_buf_lasterror(pi->buf); + if (git_buf_oom(pi->buf)) + return GIT_ENOMEM; return pi->print_cb(pi->cb_data, line_origin, pi->buf->ptr); } -- cgit v1.2.1 From ae9e29fde7e7d1c0c3e95bdabbb5c96fc71b1c71 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 6 Mar 2012 16:14:31 -0800 Subject: Migrating diff to new error handling Ended up migrating a bunch of upstream functions as well including vector, attr_file, and odb in order to get this to work right. --- src/diff_output.c | 181 +++++++++++++++++++++++++++--------------------------- 1 file changed, 92 insertions(+), 89 deletions(-) (limited to 'src/diff_output.c') diff --git a/src/diff_output.c b/src/diff_output.c index 9c34dcf71..638cabca5 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -34,31 +34,39 @@ static int read_next_int(const char **str, int *value) v = (v * 10) + (*scan - '0'); *str = scan; *value = v; - return (digits > 0) ? GIT_SUCCESS : GIT_ENOTFOUND; + return (digits > 0) ? 0 : -1; } static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) { - int err = GIT_SUCCESS; diff_output_info *info = priv; if (len == 1 && info->hunk_cb) { git_diff_range range = { -1, 0, -1, 0 }; + const char *scan = bufs[0].ptr; /* expect something of the form "@@ -%d[,%d] +%d[,%d] @@" */ - if (bufs[0].ptr[0] == '@') { - const char *scan = bufs[0].ptr; - if (!(err = read_next_int(&scan, &range.old_start)) && *scan == ',') - err = read_next_int(&scan, &range.old_lines); - if (!err && - !(err = read_next_int(&scan, &range.new_start)) && *scan == ',') - err = read_next_int(&scan, &range.new_lines); - if (!err && range.old_start >= 0 && range.new_start >= 0) - err = info->hunk_cb( - info->cb_data, info->delta, &range, bufs[0].ptr, bufs[0].size); - } + if (*scan != '@') + return -1; + + if (read_next_int(&scan, &range.old_start) < 0) + return -1; + if (*scan == ',' && read_next_int(&scan, &range.old_lines) < 0) + return -1; + + if (read_next_int(&scan, &range.new_start) < 0) + return -1; + if (*scan == ',' && read_next_int(&scan, &range.new_lines) < 0) + return -1; + + if (range.old_start < 0 || range.new_start < 0) + return -1; + + return info->hunk_cb( + info->cb_data, info->delta, &range, bufs[0].ptr, bufs[0].size); } - else if ((len == 2 || len == 3) && info->line_cb) { + + if ((len == 2 || len == 3) && info->line_cb) { int origin; /* expect " "/"-"/"+", then data, then maybe newline */ @@ -67,41 +75,43 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION : GIT_DIFF_LINE_CONTEXT; - err = info->line_cb( - info->cb_data, info->delta, origin, bufs[1].ptr, bufs[1].size); + if (info->line_cb( + info->cb_data, info->delta, origin, bufs[1].ptr, bufs[1].size) < 0) + return -1; /* deal with adding and removing newline at EOF */ - if (err == GIT_SUCCESS && len == 3) { + if (len == 3) { if (origin == GIT_DIFF_LINE_ADDITION) origin = GIT_DIFF_LINE_ADD_EOFNL; else origin = GIT_DIFF_LINE_DEL_EOFNL; - err = info->line_cb( + return info->line_cb( info->cb_data, info->delta, origin, bufs[2].ptr, bufs[2].size); } } - return err; + return 0; } #define BINARY_DIFF_FLAGS (GIT_DIFF_FILE_BINARY|GIT_DIFF_FILE_NOT_BINARY) -static int set_file_is_binary_by_attr(git_repository *repo, git_diff_file *file) +static int update_file_is_binary_by_attr(git_repository *repo, git_diff_file *file) { const char *value; - int error = git_attr_get(repo, file->path, "diff", &value); - if (error != GIT_SUCCESS) - return error; + if (git_attr_get(repo, file->path, "diff", &value) < 0) + return -1; + if (GIT_ATTR_FALSE(value)) file->flags |= GIT_DIFF_FILE_BINARY; else if (GIT_ATTR_TRUE(value)) file->flags |= GIT_DIFF_FILE_NOT_BINARY; /* otherwise leave file->flags alone */ - return error; + + return 0; } -static void set_delta_is_binary(git_diff_delta *delta) +static void update_delta_is_binary(git_diff_delta *delta) { if ((delta->old.flags & GIT_DIFF_FILE_BINARY) != 0 || (delta->new.flags & GIT_DIFF_FILE_BINARY) != 0) @@ -116,7 +126,7 @@ static int file_is_binary_by_attr( git_diff_list *diff, git_diff_delta *delta) { - int error, mirror_new; + int error = 0, mirror_new; delta->binary = -1; @@ -127,7 +137,7 @@ static int file_is_binary_by_attr( delta->old.flags |= GIT_DIFF_FILE_BINARY; delta->new.flags |= GIT_DIFF_FILE_BINARY; delta->binary = 1; - return GIT_SUCCESS; + return 0; } /* check if user is forcing us to text diff these files */ @@ -135,22 +145,21 @@ static int file_is_binary_by_attr( delta->old.flags |= GIT_DIFF_FILE_NOT_BINARY; delta->new.flags |= GIT_DIFF_FILE_NOT_BINARY; delta->binary = 0; - return GIT_SUCCESS; + return 0; } /* check diff attribute +, -, or 0 */ - error = set_file_is_binary_by_attr(diff->repo, &delta->old); - if (error != GIT_SUCCESS) - return error; + if (update_file_is_binary_by_attr(diff->repo, &delta->old) < 0) + return -1; mirror_new = (delta->new.path == delta->old.path || strcmp(delta->new.path, delta->old.path) == 0); if (mirror_new) delta->new.flags &= (delta->old.flags & BINARY_DIFF_FLAGS); else - error = set_file_is_binary_by_attr(diff->repo, &delta->new); + error = update_file_is_binary_by_attr(diff->repo, &delta->new); - set_delta_is_binary(delta); + update_delta_is_binary(delta); return error; } @@ -179,11 +188,11 @@ static int file_is_binary_by_content( delta->new.flags |= GIT_DIFF_FILE_NOT_BINARY; } - set_delta_is_binary(delta); + update_delta_is_binary(delta); /* TODO: if value != NULL, implement diff drivers */ - return GIT_SUCCESS; + return 0; } static void setup_xdiff_options( @@ -214,17 +223,15 @@ static int get_blob_content( git_map *map, git_blob **blob) { - int error; - if (git_oid_iszero(oid)) - return GIT_SUCCESS; + return 0; - if ((error = git_blob_lookup(blob, repo, oid)) == GIT_SUCCESS) { - map->data = (void *)git_blob_rawcontent(*blob); - map->len = git_blob_rawsize(*blob); - } + if (git_blob_lookup(blob, repo, oid) < 0) + return -1; - return error; + map->data = (void *)git_blob_rawcontent(*blob); + map->len = git_blob_rawsize(*blob); + return 0; } static int get_workdir_content( @@ -232,35 +239,33 @@ static int get_workdir_content( git_diff_file *file, git_map *map) { - git_buf full_path = GIT_BUF_INIT; - int error = git_buf_joinpath( - &full_path, git_repository_workdir(repo), file->path); - if (error != GIT_SUCCESS) - return error; + int error = 0; + git_buf path = GIT_BUF_INIT; + + if (git_buf_joinpath(&path, git_repository_workdir(repo), file->path) < 0) + return -1; if (S_ISLNK(file->mode)) { + ssize_t read_len; + file->flags |= GIT_DIFF_FILE_FREE_DATA; file->flags |= GIT_DIFF_FILE_BINARY; map->data = git__malloc((size_t)file->size + 1); - if (map->data == NULL) - error = GIT_ENOMEM; - else { - ssize_t read_len = - p_readlink(full_path.ptr, map->data, (size_t)file->size + 1); - if (read_len != (ssize_t)file->size) - error = git__throw( - GIT_EOSERR, "Failed to read symlink %s", file->path); - else - map->len = read_len; - - } + GITERR_CHECK_ALLOC(map->data); + + read_len = p_readlink(path.ptr, map->data, (size_t)file->size + 1); + if (read_len != (ssize_t)file->size) { + giterr_set(GITERR_OS, "Failed to read symlink '%s'", file->path); + error = -1; + } else + map->len = read_len; } else { - error = git_futils_mmap_ro_file(map, full_path.ptr); + error = git_futils_mmap_ro_file(map, path.ptr); file->flags |= GIT_DIFF_FILE_UNMAP_DATA; } - git_buf_free(&full_path); + git_buf_free(&path); return error; } @@ -288,7 +293,7 @@ int git_diff_foreach( git_diff_hunk_fn hunk_cb, git_diff_line_fn line_cb) { - int error = GIT_SUCCESS; + int error = 0; diff_output_info info; git_diff_delta *delta; xpparam_t xdiff_params; @@ -320,8 +325,7 @@ int git_diff_foreach( (diff->opts.flags & GIT_DIFF_INCLUDE_UNTRACKED) == 0) continue; - error = file_is_binary_by_attr(diff, delta); - if (error < GIT_SUCCESS) + if ((error = file_is_binary_by_attr(diff, delta)) < 0) goto cleanup; old_data.data = ""; @@ -345,7 +349,7 @@ int git_diff_foreach( else error = get_blob_content( diff->repo, &delta->old.oid, &old_data, &old_blob); - if (error != GIT_SUCCESS) + if (error < 0) goto cleanup; } @@ -359,13 +363,13 @@ int git_diff_foreach( else error = get_blob_content( diff->repo, &delta->new.oid, &new_data, &new_blob); - if (error != GIT_SUCCESS) + if (error < 0) goto cleanup; if ((delta->new.flags | GIT_DIFF_FILE_VALID_OID) == 0) { error = git_odb_hash( &delta->new.oid, new_data.data, new_data.len, GIT_OBJ_BLOB); - if (error != GIT_SUCCESS) + if (error < 0) goto cleanup; /* since we did not have the definitive oid, we may have @@ -384,7 +388,7 @@ int git_diff_foreach( if (delta->binary == -1) { error = file_is_binary_by_content( diff, delta, &old_data, &new_data); - if (error < GIT_SUCCESS) + if (error < 0) goto cleanup; } @@ -394,7 +398,7 @@ int git_diff_foreach( if (file_cb != NULL) { error = file_cb(data, delta, (float)info.index / diff->deltas.length); - if (error != GIT_SUCCESS) + if (error < 0) goto cleanup; } @@ -417,7 +421,7 @@ cleanup: release_content(&delta->old, &old_data, old_blob); release_content(&delta->new, &new_data, new_blob); - if (error != GIT_SUCCESS) + if (error < 0) break; } @@ -462,7 +466,7 @@ static int print_compact(void *data, git_diff_delta *delta, float progress) } if (!code) - return GIT_SUCCESS; + return 0; old_suffix = pick_suffix(delta->old.mode); new_suffix = pick_suffix(delta->new.mode); @@ -482,8 +486,8 @@ static int print_compact(void *data, git_diff_delta *delta, float progress) else git_buf_printf(pi->buf, "%c\t%s\n", code, delta->old.path); - if (git_buf_oom(pi->buf) == true) - return GIT_ENOMEM; + if (git_buf_oom(pi->buf)) + return -1; return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr); } @@ -535,14 +539,13 @@ static int print_oid_range(diff_print_info *pi, git_diff_delta *delta) } if (git_buf_oom(pi->buf)) - return GIT_ENOMEM; + return -1; return 0; } static int print_patch_file(void *data, git_diff_delta *delta, float progress) { - int error; diff_print_info *pi = data; const char *oldpfx = pi->diff->opts.src_prefix; const char *oldpath = delta->old.path; @@ -553,8 +556,9 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress) git_buf_clear(pi->buf); git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", oldpfx, delta->old.path, newpfx, delta->new.path); - if ((error = print_oid_range(pi, delta)) < GIT_SUCCESS) - return error; + + if (print_oid_range(pi, delta) < 0) + return -1; if (git_oid_iszero(&delta->old.oid)) { oldpfx = ""; @@ -571,18 +575,18 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress) } if (git_buf_oom(pi->buf)) - return GIT_ENOMEM; + return -1; - error = pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr); - if (error != GIT_SUCCESS || delta->binary != 1) - return error; + if (pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr) < 0 || + delta->binary != 1) + return -1; 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)) - return GIT_ENOMEM; + return -1; return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_BINARY, pi->buf->ptr); } @@ -600,11 +604,10 @@ static int print_patch_hunk( GIT_UNUSED(r); git_buf_clear(pi->buf); + if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0) + return -1; - if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) == GIT_SUCCESS) - return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_HUNK_HDR, pi->buf->ptr); - else - return GIT_ENOMEM; + return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_HUNK_HDR, pi->buf->ptr); } static int print_patch_line( @@ -628,7 +631,7 @@ static int print_patch_line( git_buf_printf(pi->buf, "%.*s", (int)content_len, content); if (git_buf_oom(pi->buf)) - return GIT_ENOMEM; + return -1; return pi->print_cb(pi->cb_data, line_origin, pi->buf->ptr); } @@ -721,5 +724,5 @@ int git_diff_blobs( xdl_diff(&old, &new, &xdiff_params, &xdiff_config, &xdiff_callback); - return GIT_SUCCESS; + return 0; } -- cgit v1.2.1 From 66142ae03134ef8a45e6bd304c6106a1685c3c99 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 22 Mar 2012 10:44:36 -0700 Subject: New status fixes This adds support for roughly-right tracking of submodules (although it does not recurse into submodules to detect internal modifications a la core git), and it adds support for including unmodified files in diff iteration if requested. --- src/diff_output.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/diff_output.c') diff --git a/src/diff_output.c b/src/diff_output.c index 638cabca5..f4c214314 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -314,7 +314,8 @@ int git_diff_foreach( git_blob *old_blob = NULL, *new_blob = NULL; git_map old_data, new_data; - if (delta->status == GIT_DELTA_UNMODIFIED) + if (delta->status == GIT_DELTA_UNMODIFIED && + (diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0) continue; if (delta->status == GIT_DELTA_IGNORED && @@ -377,7 +378,8 @@ int git_diff_foreach( */ if (git_oid_cmp(&delta->old.oid, &delta->new.oid) == 0) { delta->status = GIT_DELTA_UNMODIFIED; - goto cleanup; + if ((diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0) + goto cleanup; } } } -- cgit v1.2.1 From eb3d71a5bcd78cb4840e62194e8998141508af88 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Wed, 25 Apr 2012 22:23:35 +0200 Subject: diff: fix generation of the header of a removal patch --- src/diff_output.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/diff_output.c') diff --git a/src/diff_output.c b/src/diff_output.c index f4c214314..7c5b6f276 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -553,9 +553,16 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress) const char *oldpath = delta->old.path; const char *newpfx = pi->diff->opts.dst_prefix; const char *newpath = delta->new.path; + int result; GIT_UNUSED(progress); + if (!oldpfx) + oldpfx = DIFF_SRC_PREFIX_DEFAULT; + + if (!newpfx) + newpfx = DIFF_DST_PREFIX_DEFAULT; + git_buf_clear(pi->buf); git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", oldpfx, delta->old.path, newpfx, delta->new.path); @@ -567,8 +574,8 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress) oldpath = "/dev/null"; } if (git_oid_iszero(&delta->new.oid)) { - oldpfx = ""; - oldpath = "/dev/null"; + newpfx = ""; + newpath = "/dev/null"; } if (delta->binary != 1) { @@ -579,9 +586,12 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress) if (git_buf_oom(pi->buf)) return -1; - if (pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr) < 0 || - delta->binary != 1) - return -1; + result = pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr); + if (result < 0) + return result; + + if (delta->binary != 1) + return 0; git_buf_clear(pi->buf); git_buf_printf( -- cgit v1.2.1 From 1d2dd864add4835c49744a566c226a1c7da04e99 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sun, 29 Apr 2012 19:42:51 +0200 Subject: diff: provide more context to the consumer of the callbacks Update the callback to provide some information related to the file change being processed and the range of the hunk, when applicable. --- src/diff_output.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'src/diff_output.c') diff --git a/src/diff_output.c b/src/diff_output.c index 7c5b6f276..a5a11395f 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -18,9 +18,10 @@ typedef struct { git_diff_list *diff; void *cb_data; git_diff_hunk_fn hunk_cb; - git_diff_line_fn line_cb; + git_diff_data_fn line_cb; unsigned int index; git_diff_delta *delta; + git_diff_range range; } diff_output_info; static int read_next_int(const char **str, int *value) @@ -62,6 +63,8 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) if (range.old_start < 0 || range.new_start < 0) return -1; + memcpy(&info->range, &range, sizeof(git_diff_range)); + return info->hunk_cb( info->cb_data, info->delta, &range, bufs[0].ptr, bufs[0].size); } @@ -76,7 +79,7 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) GIT_DIFF_LINE_CONTEXT; if (info->line_cb( - info->cb_data, info->delta, origin, bufs[1].ptr, bufs[1].size) < 0) + info->cb_data, info->delta, &info->range, origin, bufs[1].ptr, bufs[1].size) < 0) return -1; /* deal with adding and removing newline at EOF */ @@ -87,7 +90,7 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) origin = GIT_DIFF_LINE_DEL_EOFNL; return info->line_cb( - info->cb_data, info->delta, origin, bufs[2].ptr, bufs[2].size); + info->cb_data, info->delta, &info->range, origin, bufs[2].ptr, bufs[2].size); } } @@ -291,7 +294,7 @@ int git_diff_foreach( void *data, git_diff_file_fn file_cb, git_diff_hunk_fn hunk_cb, - git_diff_line_fn line_cb) + git_diff_data_fn line_cb) { int error = 0; diff_output_info info; @@ -433,7 +436,7 @@ cleanup: typedef struct { git_diff_list *diff; - git_diff_output_fn print_cb; + git_diff_data_fn print_cb; void *cb_data; git_buf *buf; } diff_print_info; @@ -491,13 +494,13 @@ static int print_compact(void *data, git_diff_delta *delta, float progress) if (git_buf_oom(pi->buf)) return -1; - return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr); + return pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf)); } int git_diff_print_compact( git_diff_list *diff, void *cb_data, - git_diff_output_fn print_cb) + git_diff_data_fn print_cb) { int error; git_buf buf = GIT_BUF_INIT; @@ -586,7 +589,7 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress) if (git_buf_oom(pi->buf)) return -1; - result = pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr); + result = pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf)); if (result < 0) return result; @@ -600,7 +603,7 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress) if (git_buf_oom(pi->buf)) return -1; - return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_BINARY, pi->buf->ptr); + return pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_BINARY, git_buf_cstr(pi->buf), git_buf_len(pi->buf)); } static int print_patch_hunk( @@ -612,27 +615,23 @@ static int print_patch_hunk( { diff_print_info *pi = data; - GIT_UNUSED(d); - GIT_UNUSED(r); - git_buf_clear(pi->buf); if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0) return -1; - return pi->print_cb(pi->cb_data, GIT_DIFF_LINE_HUNK_HDR, pi->buf->ptr); + return pi->print_cb(pi->cb_data, d, r, GIT_DIFF_LINE_HUNK_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf)); } static int print_patch_line( void *data, git_diff_delta *delta, + git_diff_range *range, char line_origin, /* GIT_DIFF_LINE value from above */ const char *content, size_t content_len) { diff_print_info *pi = data; - GIT_UNUSED(delta); - git_buf_clear(pi->buf); if (line_origin == GIT_DIFF_LINE_ADDITION || @@ -645,13 +644,13 @@ static int print_patch_line( if (git_buf_oom(pi->buf)) return -1; - return pi->print_cb(pi->cb_data, line_origin, pi->buf->ptr); + return pi->print_cb(pi->cb_data, delta, range, line_origin, git_buf_cstr(pi->buf), git_buf_len(pi->buf)); } int git_diff_print_patch( git_diff_list *diff, void *cb_data, - git_diff_output_fn print_cb) + git_diff_data_fn print_cb) { int error; git_buf buf = GIT_BUF_INIT; @@ -678,7 +677,7 @@ int git_diff_blobs( git_diff_options *options, void *cb_data, git_diff_hunk_fn hunk_cb, - git_diff_line_fn line_cb) + git_diff_data_fn line_cb) { diff_output_info info; git_diff_delta delta; -- cgit v1.2.1 From 16b83019af63d837b6934bcf1b71b8697d5d94c8 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sun, 4 Mar 2012 23:28:36 -0800 Subject: Fix usage of "new" for fieldname in public header This should restore the ability to include libgit2 headers in C++ projects. Cherry picked 2de60205dfea2c4a422b2108a5e8605f97c2e895 from development into new-error-handling. --- src/diff_output.c | 158 +++++++++++++++++++++++++++--------------------------- 1 file changed, 79 insertions(+), 79 deletions(-) (limited to 'src/diff_output.c') diff --git a/src/diff_output.c b/src/diff_output.c index a5a11395f..a6d75f60f 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -116,11 +116,11 @@ static int update_file_is_binary_by_attr(git_repository *repo, git_diff_file *fi static void update_delta_is_binary(git_diff_delta *delta) { - if ((delta->old.flags & GIT_DIFF_FILE_BINARY) != 0 || - (delta->new.flags & GIT_DIFF_FILE_BINARY) != 0) + if ((delta->old_file.flags & GIT_DIFF_FILE_BINARY) != 0 || + (delta->new_file.flags & GIT_DIFF_FILE_BINARY) != 0) delta->binary = 1; - else if ((delta->old.flags & GIT_DIFF_FILE_NOT_BINARY) != 0 || - (delta->new.flags & GIT_DIFF_FILE_NOT_BINARY) != 0) + else if ((delta->old_file.flags & GIT_DIFF_FILE_NOT_BINARY) != 0 || + (delta->new_file.flags & GIT_DIFF_FILE_NOT_BINARY) != 0) delta->binary = 0; /* otherwise leave delta->binary value untouched */ } @@ -134,33 +134,33 @@ static int file_is_binary_by_attr( delta->binary = -1; /* make sure files are conceivably mmap-able */ - if ((git_off_t)((size_t)delta->old.size) != delta->old.size || - (git_off_t)((size_t)delta->new.size) != delta->new.size) + if ((git_off_t)((size_t)delta->old_file.size) != delta->old_file.size || + (git_off_t)((size_t)delta->new_file.size) != delta->new_file.size) { - delta->old.flags |= GIT_DIFF_FILE_BINARY; - delta->new.flags |= GIT_DIFF_FILE_BINARY; + delta->old_file.flags |= GIT_DIFF_FILE_BINARY; + delta->new_file.flags |= GIT_DIFF_FILE_BINARY; delta->binary = 1; return 0; } /* check if user is forcing us to text diff these files */ if (diff->opts.flags & GIT_DIFF_FORCE_TEXT) { - delta->old.flags |= GIT_DIFF_FILE_NOT_BINARY; - delta->new.flags |= GIT_DIFF_FILE_NOT_BINARY; + delta->old_file.flags |= GIT_DIFF_FILE_NOT_BINARY; + delta->new_file.flags |= GIT_DIFF_FILE_NOT_BINARY; delta->binary = 0; return 0; } /* check diff attribute +, -, or 0 */ - if (update_file_is_binary_by_attr(diff->repo, &delta->old) < 0) + if (update_file_is_binary_by_attr(diff->repo, &delta->old_file) < 0) return -1; - mirror_new = (delta->new.path == delta->old.path || - strcmp(delta->new.path, delta->old.path) == 0); + mirror_new = (delta->new_file.path == delta->old_file.path || + strcmp(delta->new_file.path, delta->old_file.path) == 0); if (mirror_new) - delta->new.flags &= (delta->old.flags & BINARY_DIFF_FLAGS); + delta->new_file.flags &= (delta->old_file.flags & BINARY_DIFF_FLAGS); else - error = update_file_is_binary_by_attr(diff->repo, &delta->new); + error = update_file_is_binary_by_attr(diff->repo, &delta->new_file); update_delta_is_binary(delta); @@ -175,20 +175,20 @@ static int file_is_binary_by_content( { GIT_UNUSED(diff); - if ((delta->old.flags & BINARY_DIFF_FLAGS) == 0) { + if ((delta->old_file.flags & BINARY_DIFF_FLAGS) == 0) { size_t search_len = min(old_data->len, 4000); if (strnlen(old_data->data, search_len) != search_len) - delta->old.flags |= GIT_DIFF_FILE_BINARY; + delta->old_file.flags |= GIT_DIFF_FILE_BINARY; else - delta->old.flags |= GIT_DIFF_FILE_NOT_BINARY; + delta->old_file.flags |= GIT_DIFF_FILE_NOT_BINARY; } - if ((delta->new.flags & BINARY_DIFF_FLAGS) == 0) { + if ((delta->new_file.flags & BINARY_DIFF_FLAGS) == 0) { size_t search_len = min(new_data->len, 4000); if (strnlen(new_data->data, search_len) != search_len) - delta->new.flags |= GIT_DIFF_FILE_BINARY; + delta->new_file.flags |= GIT_DIFF_FILE_BINARY; else - delta->new.flags |= GIT_DIFF_FILE_NOT_BINARY; + delta->new_file.flags |= GIT_DIFF_FILE_NOT_BINARY; } update_delta_is_binary(delta); @@ -349,37 +349,37 @@ int git_diff_foreach( delta->status == GIT_DELTA_MODIFIED)) { if (diff->old_src == GIT_ITERATOR_WORKDIR) - error = get_workdir_content(diff->repo, &delta->old, &old_data); + error = get_workdir_content(diff->repo, &delta->old_file, &old_data); else error = get_blob_content( - diff->repo, &delta->old.oid, &old_data, &old_blob); + diff->repo, &delta->old_file.oid, &old_data, &old_blob); if (error < 0) goto cleanup; } if (delta->binary != 1 && - (hunk_cb || line_cb || git_oid_iszero(&delta->new.oid)) && + (hunk_cb || line_cb || git_oid_iszero(&delta->new_file.oid)) && (delta->status == GIT_DELTA_ADDED || delta->status == GIT_DELTA_MODIFIED)) { if (diff->new_src == GIT_ITERATOR_WORKDIR) - error = get_workdir_content(diff->repo, &delta->new, &new_data); + error = get_workdir_content(diff->repo, &delta->new_file, &new_data); else error = get_blob_content( - diff->repo, &delta->new.oid, &new_data, &new_blob); + diff->repo, &delta->new_file.oid, &new_data, &new_blob); if (error < 0) goto cleanup; - if ((delta->new.flags | GIT_DIFF_FILE_VALID_OID) == 0) { + if ((delta->new_file.flags | GIT_DIFF_FILE_VALID_OID) == 0) { error = git_odb_hash( - &delta->new.oid, new_data.data, new_data.len, GIT_OBJ_BLOB); + &delta->new_file.oid, new_data.data, new_data.len, GIT_OBJ_BLOB); if (error < 0) goto cleanup; /* since we did not have the definitive oid, we may have * incorrect status and need to skip this item. */ - if (git_oid_cmp(&delta->old.oid, &delta->new.oid) == 0) { + if (git_oid_cmp(&delta->old_file.oid, &delta->new_file.oid) == 0) { delta->status = GIT_DELTA_UNMODIFIED; if ((diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0) goto cleanup; @@ -423,8 +423,8 @@ int git_diff_foreach( &xdiff_params, &xdiff_config, &xdiff_callback); cleanup: - release_content(&delta->old, &old_data, old_blob); - release_content(&delta->new, &new_data, new_blob); + release_content(&delta->old_file, &old_data, old_blob); + release_content(&delta->new_file, &new_data, new_blob); if (error < 0) break; @@ -473,23 +473,23 @@ static int print_compact(void *data, git_diff_delta *delta, float progress) if (!code) return 0; - old_suffix = pick_suffix(delta->old.mode); - new_suffix = pick_suffix(delta->new.mode); + old_suffix = pick_suffix(delta->old_file.mode); + new_suffix = pick_suffix(delta->new_file.mode); git_buf_clear(pi->buf); - if (delta->old.path != delta->new.path && - strcmp(delta->old.path,delta->new.path) != 0) + if (delta->old_file.path != delta->new_file.path && + strcmp(delta->old_file.path,delta->new_file.path) != 0) git_buf_printf(pi->buf, "%c\t%s%c -> %s%c\n", code, - delta->old.path, old_suffix, delta->new.path, new_suffix); - else if (delta->old.mode != delta->new.mode && - delta->old.mode != 0 && delta->new.mode != 0) + delta->old_file.path, old_suffix, delta->new_file.path, new_suffix); + else if (delta->old_file.mode != delta->new_file.mode && + delta->old_file.mode != 0 && delta->new_file.mode != 0) git_buf_printf(pi->buf, "%c\t%s%c (%o -> %o)\n", code, - delta->old.path, new_suffix, delta->old.mode, delta->new.mode); + delta->old_file.path, new_suffix, delta->old_file.mode, delta->new_file.mode); else if (old_suffix != ' ') - git_buf_printf(pi->buf, "%c\t%s%c\n", code, delta->old.path, old_suffix); + git_buf_printf(pi->buf, "%c\t%s%c\n", code, delta->old_file.path, old_suffix); else - git_buf_printf(pi->buf, "%c\t%s\n", code, delta->old.path); + git_buf_printf(pi->buf, "%c\t%s\n", code, delta->old_file.path); if (git_buf_oom(pi->buf)) return -1; @@ -524,21 +524,21 @@ static int print_oid_range(diff_print_info *pi, git_diff_delta *delta) char start_oid[8], end_oid[8]; /* TODO: Determine a good actual OID range to print */ - git_oid_to_string(start_oid, sizeof(start_oid), &delta->old.oid); - git_oid_to_string(end_oid, sizeof(end_oid), &delta->new.oid); + git_oid_to_string(start_oid, sizeof(start_oid), &delta->old_file.oid); + git_oid_to_string(end_oid, sizeof(end_oid), &delta->new_file.oid); /* TODO: Match git diff more closely */ - if (delta->old.mode == delta->new.mode) { + if (delta->old_file.mode == delta->new_file.mode) { git_buf_printf(pi->buf, "index %s..%s %o\n", - start_oid, end_oid, delta->old.mode); + start_oid, end_oid, delta->old_file.mode); } else { - if (delta->old.mode == 0) { - git_buf_printf(pi->buf, "new file mode %o\n", delta->new.mode); - } else if (delta->new.mode == 0) { - git_buf_printf(pi->buf, "deleted file mode %o\n", delta->old.mode); + if (delta->old_file.mode == 0) { + git_buf_printf(pi->buf, "new file mode %o\n", delta->new_file.mode); + } else if (delta->new_file.mode == 0) { + git_buf_printf(pi->buf, "deleted file mode %o\n", delta->old_file.mode); } else { - git_buf_printf(pi->buf, "old mode %o\n", delta->old.mode); - git_buf_printf(pi->buf, "new mode %o\n", delta->new.mode); + git_buf_printf(pi->buf, "old mode %o\n", delta->old_file.mode); + git_buf_printf(pi->buf, "new mode %o\n", delta->new_file.mode); } git_buf_printf(pi->buf, "index %s..%s\n", start_oid, end_oid); } @@ -552,31 +552,31 @@ static int print_oid_range(diff_print_info *pi, git_diff_delta *delta) static int print_patch_file(void *data, git_diff_delta *delta, float progress) { diff_print_info *pi = data; - const char *oldpfx = pi->diff->opts.src_prefix; - const char *oldpath = delta->old.path; - const char *newpfx = pi->diff->opts.dst_prefix; - const char *newpath = delta->new.path; + const char *oldpfx = pi->diff->opts.old_prefix; + const char *oldpath = delta->old_file.path; + const char *newpfx = pi->diff->opts.new_prefix; + const char *newpath = delta->new_file.path; int result; GIT_UNUSED(progress); if (!oldpfx) - oldpfx = DIFF_SRC_PREFIX_DEFAULT; + oldpfx = DIFF_OLD_PREFIX_DEFAULT; if (!newpfx) - newpfx = DIFF_DST_PREFIX_DEFAULT; + newpfx = DIFF_NEW_PREFIX_DEFAULT; git_buf_clear(pi->buf); - git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", oldpfx, delta->old.path, newpfx, delta->new.path); + git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", oldpfx, delta->old_file.path, newpfx, delta->new_file.path); if (print_oid_range(pi, delta) < 0) return -1; - if (git_oid_iszero(&delta->old.oid)) { + if (git_oid_iszero(&delta->old_file.oid)) { oldpfx = ""; oldpath = "/dev/null"; } - if (git_oid_iszero(&delta->new.oid)) { + if (git_oid_iszero(&delta->new_file.oid)) { newpfx = ""; newpath = "/dev/null"; } @@ -681,7 +681,7 @@ int git_diff_blobs( { diff_output_info info; git_diff_delta delta; - mmfile_t old, new; + mmfile_t old_data, new_data; xpparam_t xdiff_params; xdemitconf_t xdiff_config; xdemitcb_t xdiff_callback; @@ -695,31 +695,31 @@ int git_diff_blobs( } if (old_blob) { - old.ptr = (char *)git_blob_rawcontent(old_blob); - old.size = git_blob_rawsize(old_blob); + old_data.ptr = (char *)git_blob_rawcontent(old_blob); + old_data.size = git_blob_rawsize(old_blob); } else { - old.ptr = ""; - old.size = 0; + old_data.ptr = ""; + old_data.size = 0; } if (new_blob) { - new.ptr = (char *)git_blob_rawcontent(new_blob); - new.size = git_blob_rawsize(new_blob); + new_data.ptr = (char *)git_blob_rawcontent(new_blob); + new_data.size = git_blob_rawsize(new_blob); } else { - new.ptr = ""; - new.size = 0; + new_data.ptr = ""; + new_data.size = 0; } /* populate a "fake" delta record */ - delta.status = old.ptr ? - (new.ptr ? GIT_DELTA_MODIFIED : GIT_DELTA_DELETED) : - (new.ptr ? GIT_DELTA_ADDED : GIT_DELTA_UNTRACKED); - delta.old.mode = 0100644; /* can't know the truth from a blob alone */ - delta.new.mode = 0100644; - git_oid_cpy(&delta.old.oid, git_object_id((const git_object *)old_blob)); - git_oid_cpy(&delta.new.oid, git_object_id((const git_object *)new_blob)); - delta.old.path = NULL; - delta.new.path = NULL; + delta.status = old_data.ptr ? + (new_data.ptr ? GIT_DELTA_MODIFIED : GIT_DELTA_DELETED) : + (new_data.ptr ? GIT_DELTA_ADDED : GIT_DELTA_UNTRACKED); + delta.old_file.mode = 0100644; /* can't know the truth from a blob alone */ + delta.new_file.mode = 0100644; + git_oid_cpy(&delta.old_file.oid, git_object_id((const git_object *)old_blob)); + git_oid_cpy(&delta.new_file.oid, git_object_id((const git_object *)new_blob)); + delta.old_file.path = NULL; + delta.new_file.path = NULL; delta.similarity = 0; info.diff = NULL; @@ -733,7 +733,7 @@ int git_diff_blobs( xdiff_callback.outf = diff_output_cb; xdiff_callback.priv = &info; - xdl_diff(&old, &new, &xdiff_params, &xdiff_config, &xdiff_callback); + xdl_diff(&old_data, &new_data, &xdiff_params, &xdiff_config, &xdiff_callback); return 0; } -- cgit v1.2.1 From 8b2bcfbe68ea9cb8f30018cc2607c9409ecf0fc0 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 5 Mar 2012 09:14:56 -0800 Subject: Copy values to avoid strict aliasing warning To make this code more resilient to future changes, we'll explicitly translate the libgit2 structure to the libxdiff structure. --- src/diff_output.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/diff_output.c') diff --git a/src/diff_output.c b/src/diff_output.c index a6d75f60f..ee18ea6e7 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -316,6 +316,7 @@ int git_diff_foreach( git_vector_foreach(&diff->deltas, info.index, delta) { git_blob *old_blob = NULL, *new_blob = NULL; git_map old_data, new_data; + mmfile_t old_xdiff_data, new_xdiff_data; if (delta->status == GIT_DELTA_UNMODIFIED && (diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0) @@ -418,8 +419,12 @@ int git_diff_foreach( assert(hunk_cb || line_cb); info.delta = delta; + old_xdiff_data.ptr = old_data.data; + old_xdiff_data.size = old_data.len; + new_xdiff_data.ptr = new_data.data; + new_xdiff_data.size = new_data.len; - xdl_diff((mmfile_t *)&old_data, (mmfile_t *)&new_data, + xdl_diff(&old_xdiff_data, &new_xdiff_data, &xdiff_params, &xdiff_config, &xdiff_callback); cleanup: -- cgit v1.2.1 From 3fd99be98a91416dae77d65fe593965a0723fa8c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 5 Mar 2012 09:30:17 -0800 Subject: Convert from strnlen to git_text_is_binary Since strnlen is not supported on all platforms and since we now have the shiny new git_text_is_binary in the filtering code, let's convert diff binary detection to use the new stuff. --- src/diff_output.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src/diff_output.c') diff --git a/src/diff_output.c b/src/diff_output.c index ee18ea6e7..13963faf8 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -13,6 +13,7 @@ #include "diff.h" #include "map.h" #include "fileops.h" +#include "filter.h" typedef struct { git_diff_list *diff; @@ -173,19 +174,30 @@ static int file_is_binary_by_content( git_map *old_data, git_map *new_data) { + git_buf search; + git_text_stats stats; + GIT_UNUSED(diff); if ((delta->old_file.flags & BINARY_DIFF_FLAGS) == 0) { - size_t search_len = min(old_data->len, 4000); - if (strnlen(old_data->data, search_len) != search_len) + search.ptr = old_data->data; + search.size = min(old_data->len, 4000); + + git_text_gather_stats(&stats, &search); + + if (git_text_is_binary(&stats)) delta->old_file.flags |= GIT_DIFF_FILE_BINARY; else delta->old_file.flags |= GIT_DIFF_FILE_NOT_BINARY; } if ((delta->new_file.flags & BINARY_DIFF_FLAGS) == 0) { - size_t search_len = min(new_data->len, 4000); - if (strnlen(new_data->data, search_len) != search_len) + search.ptr = new_data->data; + search.size = min(new_data->len, 4000); + + git_text_gather_stats(&stats, &search); + + if (git_text_is_binary(&stats)) delta->new_file.flags |= GIT_DIFF_FILE_BINARY; else delta->new_file.flags |= GIT_DIFF_FILE_NOT_BINARY; -- cgit v1.2.1 From f917481ee84cbba481c1854cccdedb2d98377d43 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 3 May 2012 16:37:25 -0700 Subject: Support reading attributes from index Depending on the operation, we need to consider gitattributes in both the work dir and the index. This adds a parameter to all of the gitattributes related functions that allows user control of attribute reading behavior (i.e. prefer workdir, prefer index, only use index). This fix also covers allowing us to check attributes (and hence do diff and status) on bare repositories. This was a somewhat larger change that I hoped because it had to change the cache key used for gitattributes files. --- src/diff_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/diff_output.c') diff --git a/src/diff_output.c b/src/diff_output.c index ca28fd01e..c380db996 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -103,7 +103,7 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) static int update_file_is_binary_by_attr(git_repository *repo, git_diff_file *file) { const char *value; - if (git_attr_get(repo, file->path, "diff", &value) < 0) + if (git_attr_get(repo, 0, file->path, "diff", &value) < 0) return -1; if (GIT_ATTR_FALSE(value)) -- cgit v1.2.1