vendor/libgit2/src/diff_generate.c in rugged-0.27.9 vs vendor/libgit2/src/diff_generate.c in rugged-0.27.10

- old
+ new

@@ -7,11 +7,11 @@ #include "diff_generate.h" #include "diff.h" #include "patch_generate.h" -#include "fileops.h" +#include "futils.h" #include "config.h" #include "attr_file.h" #include "filter.h" #include "pathspec.h" #include "index.h" @@ -79,11 +79,11 @@ git__free(delta); if (error > 0) /* positive value means to skip this delta */ return 0; else /* negative value means to cancel diff */ - return giterr_set_after_callback_function(error, "git_diff"); + return git_error_set_after_callback_function(error, "git_diff"); } } if ((error = git_vector_insert(&diff->base.deltas, delta)) < 0) git__free(delta); @@ -136,11 +136,11 @@ } if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) has_old = !has_old; - if ((entry->flags & GIT_IDXENTRY_VALID) != 0) + if ((entry->flags & GIT_INDEX_ENTRY_VALID) != 0) return 0; if (status == GIT_DELTA_IGNORED && DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_IGNORED)) return 0; @@ -155,11 +155,11 @@ if (!diff_pathspec_match(&matched_pathspec, diff, entry)) return 0; delta = diff_delta__alloc(diff, status, entry->path); - GITERR_CHECK_ALLOC(delta); + GIT_ERROR_CHECK_ALLOC(delta); /* This fn is just for single-sided diffs */ assert(status != GIT_DELTA_MODIFIED); delta->nfiles = 1; @@ -177,11 +177,11 @@ delta->new_file.id_abbrev = GIT_OID_HEXSZ; } delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID; - if (has_old || !git_oid_iszero(&delta->new_file.id)) + if (has_old || !git_oid_is_zero(&delta->new_file.id)) delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID; return diff_insert_delta(diff, delta, matched_pathspec); } @@ -218,11 +218,11 @@ old_id = new_id; new_id = temp_id; } delta = diff_delta__alloc(diff, status, canonical_path); - GITERR_CHECK_ALLOC(delta); + GIT_ERROR_CHECK_ALLOC(delta); delta->nfiles = 2; if (!git_index_entry_is_conflict(old_entry)) { delta->old_file.size = old_entry->file_size; delta->old_file.mode = old_mode; @@ -238,11 +238,11 @@ delta->new_file.size = new_entry->file_size; delta->new_file.mode = new_mode; delta->old_file.flags |= GIT_DIFF_FLAG_EXISTS; delta->new_file.flags |= GIT_DIFF_FLAG_EXISTS; - if (!git_oid_iszero(&new_entry->id)) + if (!git_oid_is_zero(&new_entry->id)) delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID; } return diff_insert_delta(diff, delta, matched_pathspec); } @@ -271,11 +271,12 @@ git_oid__cmp(&delta->new_file.id, &item->id) == 0) return delta; break; case GIT_DELTA_MODIFIED: if (git_oid__cmp(&delta->old_file.id, &item->id) == 0 || - git_oid__cmp(&delta->new_file.id, &item->id) == 0) + (delta->new_file.mode == item->mode && + git_oid__cmp(&delta->new_file.id, &item->id) == 0)) return delta; break; default: break; } @@ -469,21 +470,21 @@ /* load config values that affect diff behavior */ if ((val = git_repository_config_snapshot(&cfg, repo)) < 0) return val; - if (!git_config__cvar(&val, cfg, GIT_CVAR_SYMLINKS) && val) + if (!git_config__configmap_lookup(&val, cfg, GIT_CONFIGMAP_SYMLINKS) && val) diff->diffcaps |= GIT_DIFFCAPS_HAS_SYMLINKS; - if (!git_config__cvar(&val, cfg, GIT_CVAR_IGNORESTAT) && val) + if (!git_config__configmap_lookup(&val, cfg, GIT_CONFIGMAP_IGNORESTAT) && val) diff->diffcaps |= GIT_DIFFCAPS_IGNORE_STAT; if ((diff->base.opts.flags & GIT_DIFF_IGNORE_FILEMODE) == 0 && - !git_config__cvar(&val, cfg, GIT_CVAR_FILEMODE) && val) + !git_config__configmap_lookup(&val, cfg, GIT_CONFIGMAP_FILEMODE) && val) diff->diffcaps |= GIT_DIFFCAPS_TRUST_MODE_BITS; - if (!git_config__cvar(&val, cfg, GIT_CVAR_TRUSTCTIME) && val) + if (!git_config__configmap_lookup(&val, cfg, GIT_CONFIGMAP_TRUSTCTIME) && val) diff->diffcaps |= GIT_DIFFCAPS_TRUST_CTIME; /* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */ /* If not given explicit `opts`, check `diff.xyz` configs */ @@ -514,11 +515,11 @@ git_config_entry *entry; git_config__lookup_entry(&entry, cfg, "diff.ignoresubmodules", true); if (entry && git_submodule_parse_ignore( &diff->base.opts.ignore_submodules, entry->value) < 0) - giterr_clear(); + git_error_clear(); git_config_entry_free(entry); } /* if either prefix is not set, figure out appropriate value */ if (!diff->base.opts.old_prefix || !diff->base.opts.new_prefix) { @@ -557,17 +558,22 @@ int git_diff__oid_for_file( git_oid *out, git_diff *diff, const char *path, uint16_t mode, - git_off_t size) + git_object_size_t size) { git_index_entry entry; + if (size > UINT32_MAX) { + git_error_set(GIT_ERROR_NOMEMORY, "file size overflow (for 32-bits) on '%s'", path); + return -1; + } + memset(&entry, 0, sizeof(entry)); entry.mode = mode; - entry.file_size = size; + entry.file_size = (uint32_t)size; entry.path = (char *)path; return git_diff__oid_for_entry(out, diff, &entry, mode, NULL); } @@ -598,11 +604,11 @@ diff->base.perf.stat_calls++; if (p_stat(full_path.ptr, &st) < 0) { error = git_path_set_error(errno, entry.path, "stat"); - git_buf_free(&full_path); + git_buf_dispose(&full_path); return error; } git_index_entry__init_from_stat(&entry, &st, (diff->diffcaps & GIT_DIFFCAPS_TRUST_MODE_BITS) != 0); @@ -619,17 +625,17 @@ git_submodule_free(sm); } else { /* if submodule lookup failed probably just in an intermediate * state where some init hasn't happened, so ignore the error */ - giterr_clear(); + git_error_clear(); } } else if (S_ISLNK(mode)) { error = git_odb__hashlink(out, full_path.ptr); diff->base.perf.oid_calculations++; } else if (!git__is_sizet(entry.file_size)) { - giterr_set(GITERR_OS, "file size overflow (for 32-bits) on '%s'", + git_error_set(GIT_ERROR_NOMEMORY, "file size overflow (for 32-bits) on '%s'", entry.path); error = -1; } else if (!(error = git_filter_list_load(&fl, diff->base.repo, NULL, entry.path, GIT_FILTER_TO_ODB, GIT_FILTER_ALLOW_UNSAFE))) @@ -637,11 +643,11 @@ int fd = git_futils_open_ro(full_path.ptr); if (fd < 0) error = fd; else { error = git_odb__hashfd_filtered( - out, fd, (size_t)entry.file_size, GIT_OBJ_BLOB, fl); + out, fd, (size_t)entry.file_size, GIT_OBJECT_BLOB, fl); p_close(fd); diff->base.perf.oid_calculations++; } git_filter_list_free(fl); @@ -661,11 +667,11 @@ error = git_index_add(idx, &updated_entry); diff->index_updated = true; } } - git_buf_free(&full_path); + git_buf_dispose(&full_path); return error; } typedef struct { git_repository *repo; @@ -697,11 +703,11 @@ if ((error = git_submodule_lookup( &sub, diff->base.repo, info->nitem->path)) < 0) { /* GIT_EEXISTS means dir with .git in it was found - ignore it */ if (error == GIT_EEXISTS) { - giterr_clear(); + git_error_clear(); error = 0; } return error; } @@ -761,15 +767,15 @@ if (git_index_entry_is_conflict(oitem) || git_index_entry_is_conflict(nitem)) { status = GIT_DELTA_CONFLICTED; /* support "assume unchanged" (poorly, b/c we still stat everything) */ - } else if ((oitem->flags & GIT_IDXENTRY_VALID) != 0) { + } else if ((oitem->flags & GIT_INDEX_ENTRY_VALID) != 0) { status = GIT_DELTA_UNMODIFIED; /* support "skip worktree" index bit */ - } else if ((oitem->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE) != 0) { + } else if ((oitem->flags_extended & GIT_INDEX_ENTRY_SKIP_WORKTREE) != 0) { status = GIT_DELTA_UNMODIFIED; /* if basic type of file changed, then split into delete and add */ } else if (GIT_MODE_TYPE(omode) != GIT_MODE_TYPE(nmode)) { if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE)) { @@ -789,17 +795,17 @@ } /* if oids and modes match (and are valid), then file is unmodified */ } else if (git_oid_equal(&oitem->id, &nitem->id) && omode == nmode && - !git_oid_iszero(&oitem->id)) { + !git_oid_is_zero(&oitem->id)) { status = GIT_DELTA_UNMODIFIED; /* if we have an unknown OID and a workdir iterator, then check some * circumstances that can accelerate things or need special handling */ - } else if (git_oid_iszero(&nitem->id) && new_is_workdir) { + } else if (git_oid_is_zero(&nitem->id) && new_is_workdir) { bool use_ctime = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) != 0); git_index *index = git_iterator_index(info->new_iter); status = GIT_DELTA_UNMODIFIED; @@ -835,11 +841,11 @@ } /* if we got here and decided that the files are modified, but we * haven't calculated the OID of the new item, then calculate it now */ - if (modified_uncertain && git_oid_iszero(&nitem->id)) { + if (modified_uncertain && git_oid_is_zero(&nitem->id)) { const git_oid *update_check = DIFF_FLAG_IS_SET(diff, GIT_DIFF_UPDATE_INDEX) && omode == nmode ? &oitem->id : NULL; if ((error = git_diff__oid_for_entry( @@ -869,11 +875,11 @@ return error; } return diff_delta__from_two( diff, status, oitem, omode, nitem, nmode, - git_oid_iszero(&noid) ? NULL : &noid, matched_pathspec); + git_oid_is_zero(&noid) ? NULL : &noid, matched_pathspec); } static bool entry_is_prefixed( git_diff_generated *diff, const git_index_entry *item, @@ -1057,11 +1063,11 @@ if (recurse_into_dir) { error = iterator_advance_into(&info->nitem, info->new_iter); /* if directory is empty, can't advance into it, so skip it */ if (error == GIT_ENOTFOUND) { - giterr_clear(); + git_error_clear(); error = iterator_advance(&info->nitem, info->new_iter); } return error; } @@ -1079,20 +1085,20 @@ } else if (nitem->mode == GIT_FILEMODE_COMMIT) { /* ignore things that are not actual submodules */ if (git_submodule_lookup(NULL, info->repo, nitem->path) != 0) { - giterr_clear(); + git_error_clear(); delta_type = GIT_DELTA_IGNORED; /* if this contains a tracked item, treat as normal TREE */ if (contains_oitem) { error = iterator_advance_into(&info->nitem, info->new_iter); if (error != GIT_ENOTFOUND) return error; - giterr_clear(); + git_error_clear(); return iterator_advance(&info->nitem, info->new_iter); } } } @@ -1189,11 +1195,11 @@ int error = 0; *out = NULL; diff = diff_generated_alloc(repo, old_iter, new_iter); - GITERR_CHECK_ALLOC(diff); + GIT_ERROR_CHECK_ALLOC(diff); info.repo = repo; info.old_iter = old_iter; info.new_iter = new_iter; @@ -1254,43 +1260,49 @@ git_diff_free(&diff->base); return error; } -#define DIFF_FROM_ITERATORS(MAKE_FIRST, FLAGS_FIRST, MAKE_SECOND, FLAGS_SECOND) do { \ - git_iterator *a = NULL, *b = NULL; \ - char *pfx = (opts && !(opts->flags & GIT_DIFF_DISABLE_PATHSPEC_MATCH)) ? \ - git_pathspec_prefix(&opts->pathspec) : NULL; \ - git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT, \ - b_opts = GIT_ITERATOR_OPTIONS_INIT; \ - a_opts.flags = FLAGS_FIRST; \ - a_opts.start = pfx; \ - a_opts.end = pfx; \ - b_opts.flags = FLAGS_SECOND; \ - b_opts.start = pfx; \ - b_opts.end = pfx; \ - GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); \ - if (opts && (opts->flags & GIT_DIFF_DISABLE_PATHSPEC_MATCH)) { \ - a_opts.pathlist.strings = opts->pathspec.strings; \ - a_opts.pathlist.count = opts->pathspec.count; \ - b_opts.pathlist.strings = opts->pathspec.strings; \ - b_opts.pathlist.count = opts->pathspec.count; \ - } \ - if (!error && !(error = MAKE_FIRST) && !(error = MAKE_SECOND)) \ - error = git_diff__from_iterators(&diff, repo, a, b, opts); \ - git__free(pfx); git_iterator_free(a); git_iterator_free(b); \ -} while (0) +static int diff_prepare_iterator_opts(char **prefix, git_iterator_options *a, int aflags, + git_iterator_options *b, int bflags, + const git_diff_options *opts) +{ + GIT_ERROR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); + *prefix = NULL; + + if (opts && (opts->flags & GIT_DIFF_DISABLE_PATHSPEC_MATCH)) { + a->pathlist.strings = opts->pathspec.strings; + a->pathlist.count = opts->pathspec.count; + b->pathlist.strings = opts->pathspec.strings; + b->pathlist.count = opts->pathspec.count; + } else if (opts) { + *prefix = git_pathspec_prefix(&opts->pathspec); + GIT_ERROR_CHECK_ALLOC(prefix); + } + + a->flags = aflags; + b->flags = bflags; + a->start = b->start = *prefix; + a->end = b->end = *prefix; + + return 0; +} + int git_diff_tree_to_tree( git_diff **out, git_repository *repo, git_tree *old_tree, git_tree *new_tree, const git_diff_options *opts) { - git_diff *diff = NULL; git_iterator_flag_t iflag = GIT_ITERATOR_DONT_IGNORE_CASE; + git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT, + b_opts = GIT_ITERATOR_OPTIONS_INIT; + git_iterator *a = NULL, *b = NULL; + git_diff *diff = NULL; + char *prefix = NULL; int error = 0; assert(out && repo); *out = NULL; @@ -1300,28 +1312,34 @@ * for case insensitivity */ if (opts && (opts->flags & GIT_DIFF_IGNORE_CASE) != 0) iflag = GIT_ITERATOR_IGNORE_CASE; - DIFF_FROM_ITERATORS( - git_iterator_for_tree(&a, old_tree, &a_opts), iflag, - git_iterator_for_tree(&b, new_tree, &b_opts), iflag - ); + if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, iflag, &b_opts, iflag, opts)) < 0 || + (error = git_iterator_for_tree(&a, old_tree, &a_opts)) < 0 || + (error = git_iterator_for_tree(&b, new_tree, &b_opts)) < 0 || + (error = git_diff__from_iterators(&diff, repo, a, b, opts)) < 0) + goto out; - if (!error) - *out = diff; + *out = diff; + diff = NULL; +out: + git_iterator_free(a); + git_iterator_free(b); + git_diff_free(diff); + git__free(prefix); return error; } static int diff_load_index(git_index **index, git_repository *repo) { int error = git_repository_index__weakptr(index, repo); /* reload the repository index when user did not pass one in */ if (!error && git_index_read(*index, false) < 0) - giterr_clear(); + git_error_clear(); return error; } int git_diff_tree_to_index( @@ -1329,13 +1347,17 @@ git_repository *repo, git_tree *old_tree, git_index *index, const git_diff_options *opts) { - git_diff *diff = NULL; git_iterator_flag_t iflag = GIT_ITERATOR_DONT_IGNORE_CASE | GIT_ITERATOR_INCLUDE_CONFLICTS; + git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT, + b_opts = GIT_ITERATOR_OPTIONS_INIT; + git_iterator *a = NULL, *b = NULL; + git_diff *diff = NULL; + char *prefix = NULL; bool index_ignore_case = false; int error = 0; assert(out && repo); @@ -1344,84 +1366,107 @@ if (!index && (error = diff_load_index(&index, repo)) < 0) return error; index_ignore_case = index->ignore_case; - DIFF_FROM_ITERATORS( - git_iterator_for_tree(&a, old_tree, &a_opts), iflag, - git_iterator_for_index(&b, repo, index, &b_opts), iflag - ); + if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, iflag, &b_opts, iflag, opts)) < 0 || + (error = git_iterator_for_tree(&a, old_tree, &a_opts)) < 0 || + (error = git_iterator_for_index(&b, repo, index, &b_opts)) < 0 || + (error = git_diff__from_iterators(&diff, repo, a, b, opts)) < 0) + goto out; /* if index is in case-insensitive order, re-sort deltas to match */ - if (!error && index_ignore_case) + if (index_ignore_case) git_diff__set_ignore_case(diff, true); - if (!error) - *out = diff; + *out = diff; + diff = NULL; +out: + git_iterator_free(a); + git_iterator_free(b); + git_diff_free(diff); + git__free(prefix); return error; } int git_diff_index_to_workdir( git_diff **out, git_repository *repo, git_index *index, const git_diff_options *opts) { + git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT, + b_opts = GIT_ITERATOR_OPTIONS_INIT; + git_iterator *a = NULL, *b = NULL; git_diff *diff = NULL; + char *prefix = NULL; int error = 0; assert(out && repo); *out = NULL; if (!index && (error = diff_load_index(&index, repo)) < 0) return error; - DIFF_FROM_ITERATORS( - git_iterator_for_index(&a, repo, index, &a_opts), - GIT_ITERATOR_INCLUDE_CONFLICTS, + if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, GIT_ITERATOR_INCLUDE_CONFLICTS, + &b_opts, GIT_ITERATOR_DONT_AUTOEXPAND, opts)) < 0 || + (error = git_iterator_for_index(&a, repo, index, &a_opts)) < 0 || + (error = git_iterator_for_workdir(&b, repo, index, NULL, &b_opts)) < 0 || + (error = git_diff__from_iterators(&diff, repo, a, b, opts)) < 0) + goto out; - git_iterator_for_workdir(&b, repo, index, NULL, &b_opts), - GIT_ITERATOR_DONT_AUTOEXPAND - ); + if ((diff->opts.flags & GIT_DIFF_UPDATE_INDEX) && ((git_diff_generated *)diff)->index_updated) + if ((error = git_index_write(index)) < 0) + goto out; - if (!error && (diff->opts.flags & GIT_DIFF_UPDATE_INDEX) != 0 && - ((git_diff_generated *)diff)->index_updated) - error = git_index_write(index); + *out = diff; + diff = NULL; +out: + git_iterator_free(a); + git_iterator_free(b); + git_diff_free(diff); + git__free(prefix); - if (!error) - *out = diff; - return error; } int git_diff_tree_to_workdir( git_diff **out, git_repository *repo, git_tree *old_tree, const git_diff_options *opts) { + git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT, + b_opts = GIT_ITERATOR_OPTIONS_INIT; + git_iterator *a = NULL, *b = NULL; git_diff *diff = NULL; + char *prefix = NULL; git_index *index; - int error = 0; + int error; assert(out && repo); *out = NULL; - if ((error = git_repository_index__weakptr(&index, repo))) - return error; + if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, 0, + &b_opts, GIT_ITERATOR_DONT_AUTOEXPAND, opts) < 0) || + (error = git_repository_index__weakptr(&index, repo)) < 0 || + (error = git_iterator_for_tree(&a, old_tree, &a_opts)) < 0 || + (error = git_iterator_for_workdir(&b, repo, index, old_tree, &b_opts)) < 0 || + (error = git_diff__from_iterators(&diff, repo, a, b, opts)) < 0) + goto out; - DIFF_FROM_ITERATORS( - git_iterator_for_tree(&a, old_tree, &a_opts), 0, - git_iterator_for_workdir(&b, repo, index, old_tree, &b_opts), GIT_ITERATOR_DONT_AUTOEXPAND - ); + *out = diff; + diff = NULL; +out: + git_iterator_free(a); + git_iterator_free(b); + git_diff_free(diff); + git__free(prefix); - if (!error) - *out = diff; - return error; } int git_diff_tree_to_workdir_with_index( git_diff **out, @@ -1460,28 +1505,39 @@ git_repository *repo, git_index *old_index, git_index *new_index, const git_diff_options *opts) { - git_diff *diff; - int error = 0; + git_iterator_options a_opts = GIT_ITERATOR_OPTIONS_INIT, + b_opts = GIT_ITERATOR_OPTIONS_INIT; + git_iterator *a = NULL, *b = NULL; + git_diff *diff = NULL; + char *prefix = NULL; + int error; assert(out && old_index && new_index); *out = NULL; - DIFF_FROM_ITERATORS( - git_iterator_for_index(&a, repo, old_index, &a_opts), GIT_ITERATOR_DONT_IGNORE_CASE, - git_iterator_for_index(&b, repo, new_index, &b_opts), GIT_ITERATOR_DONT_IGNORE_CASE - ); + if ((error = diff_prepare_iterator_opts(&prefix, &a_opts, GIT_ITERATOR_DONT_IGNORE_CASE, + &b_opts, GIT_ITERATOR_DONT_IGNORE_CASE, opts) < 0) || + (error = git_iterator_for_index(&a, repo, old_index, &a_opts)) < 0 || + (error = git_iterator_for_index(&b, repo, new_index, &b_opts)) < 0 || + (error = git_diff__from_iterators(&diff, repo, a, b, opts)) < 0) + goto out; /* if index is in case-insensitive order, re-sort deltas to match */ - if (!error && (old_index->ignore_case || new_index->ignore_case)) + if (old_index->ignore_case || new_index->ignore_case) git_diff__set_ignore_case(diff, true); - if (!error) - *out = diff; + *out = diff; + diff = NULL; +out: + git_iterator_free(a); + git_iterator_free(b); + git_diff_free(diff); + git__free(prefix); return error; } int git_diff__paired_foreach( @@ -1549,11 +1605,11 @@ } else { i++; j++; } if ((error = cb(h2i, i2w, payload)) != 0) { - giterr_set_after_callback(error); + git_error_set_after_callback(error); break; } } /* restore case-insensitive delta sort */ @@ -1588,10 +1644,10 @@ if ((parents = git_commit_parentcount(commit)) > 1) { char commit_oidstr[GIT_OID_HEXSZ + 1]; error = -1; - giterr_set(GITERR_INVALID, "commit %s is a merge commit", + git_error_set(GIT_ERROR_INVALID, "commit %s is a merge commit", git_oid_tostr(commit_oidstr, GIT_OID_HEXSZ + 1, git_commit_id(commit))); goto on_error; } if (parents > 0)