diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/blame.c | 13 | ||||
-rw-r--r-- | src/checkout.c | 17 | ||||
-rw-r--r-- | src/cherrypick.c | 14 | ||||
-rw-r--r-- | src/clone.c | 13 | ||||
-rw-r--r-- | src/common.h | 5 | ||||
-rw-r--r-- | src/config.c | 31 | ||||
-rw-r--r-- | src/diff.c | 210 | ||||
-rw-r--r-- | src/diff.h | 6 | ||||
-rw-r--r-- | src/diff_tform.c | 8 | ||||
-rw-r--r-- | src/index.c | 6 | ||||
-rw-r--r-- | src/iterator.c | 8 | ||||
-rw-r--r-- | src/iterator.h | 1 | ||||
-rw-r--r-- | src/merge.c | 40 | ||||
-rw-r--r-- | src/odb.c | 13 | ||||
-rw-r--r-- | src/push.c | 13 | ||||
-rw-r--r-- | src/refdb.c | 13 | ||||
-rw-r--r-- | src/remote.c | 13 | ||||
-rw-r--r-- | src/repository.c | 15 | ||||
-rw-r--r-- | src/revert.c | 13 | ||||
-rw-r--r-- | src/status.c | 70 | ||||
-rw-r--r-- | src/sysdir.c | 16 | ||||
-rw-r--r-- | src/transport.c | 13 |
22 files changed, 284 insertions, 267 deletions
diff --git a/src/blame.c b/src/blame.c index e45c0ee1c..eb977c287 100644 --- a/src/blame.c +++ b/src/blame.c @@ -480,14 +480,9 @@ int git_blame_buffer( return 0; } -int git_blame_init_options(git_blame_options* opts, int version) +int git_blame_init_options(git_blame_options *opts, unsigned int version) { - if (version != GIT_BLAME_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_blame_options", version); - return -1; - } else { - git_blame_options o = GIT_BLAME_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_blame_options, GIT_BLAME_OPTIONS_INIT); + return 0; } diff --git a/src/checkout.c b/src/checkout.c index bc976b854..b869efe2b 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -184,9 +184,7 @@ static bool checkout_is_workdir_modified( if (baseitem->size && wditem->file_size != baseitem->size) return true; - if (git_diff__oid_for_file( - data->repo, wditem->path, wditem->mode, - wditem->file_size, &oid) < 0) + if (git_diff__oid_for_entry(&oid, data->diff, wditem, NULL) < 0) return false; return (git_oid__cmp(&baseitem->id, &oid) != 0); @@ -2242,14 +2240,9 @@ int git_checkout_head( return git_checkout_tree(repo, NULL, opts); } -int git_checkout_init_opts(git_checkout_options* opts, int version) +int git_checkout_init_options(git_checkout_options *opts, unsigned int version) { - if (version != GIT_CHECKOUT_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_checkout_options", version); - return -1; - } else { - git_checkout_options o = GIT_CHECKOUT_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_checkout_options, GIT_CHECKOUT_OPTIONS_INIT); + return 0; } diff --git a/src/cherrypick.c b/src/cherrypick.c index 6a5ca834c..e02348a03 100644 --- a/src/cherrypick.c +++ b/src/cherrypick.c @@ -217,14 +217,10 @@ done: return error; } -int git_cherry_pick_init_opts(git_cherry_pick_options* opts, int version) +int git_cherry_pick_init_options( + git_cherry_pick_options *opts, unsigned int version) { - if (version != GIT_CHERRY_PICK_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_cherry_pick_options", version); - return -1; - } else { - git_cherry_pick_options o = GIT_CHERRY_PICK_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_cherry_pick_options, GIT_CHERRY_PICK_OPTIONS_INIT); + return 0; } diff --git a/src/clone.c b/src/clone.c index 62f103561..c6be00f0e 100644 --- a/src/clone.c +++ b/src/clone.c @@ -445,14 +445,9 @@ int git_clone( return error; } -int git_clone_init_options(git_clone_options* opts, int version) +int git_clone_init_options(git_clone_options *opts, unsigned int version) { - if (version != GIT_CLONE_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_clone_options", version); - return -1; - } else { - git_clone_options o = GIT_CLONE_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_clone_options, GIT_CLONE_OPTIONS_INIT); + return 0; } diff --git a/src/common.h b/src/common.h index dd97a3099..807e5fa39 100644 --- a/src/common.h +++ b/src/common.h @@ -170,6 +170,11 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v } #define GIT_INIT_STRUCTURE(S,V) git__init_structure(S, sizeof(*S), V) +#define GIT_INIT_STRUCTURE_FROM_TEMPLATE(PTR,VERSION,TYPE,TPL) do { \ + TYPE _tmpl = TPL; \ + GITERR_CHECK_VERSION(&(VERSION), _tmpl.version, #TYPE); \ + memcpy((PTR), &_tmpl, sizeof(_tmpl)); } while (0) + /* NOTE: other giterr functions are in the public errors.h header file */ #include "util.h" diff --git a/src/config.c b/src/config.c index 16854c0c8..f9d697197 100644 --- a/src/config.c +++ b/src/config.c @@ -984,24 +984,22 @@ int git_config__global_location(git_buf *buf) { const git_buf *paths; const char *sep, *start; - size_t len; if (git_sysdir_get(&paths, GIT_SYSDIR_GLOBAL) < 0) return -1; /* no paths, so give up */ - if (git_buf_len(paths) == 0) + if (!paths || !git_buf_len(paths)) return -1; - start = git_buf_cstr(paths); - sep = strchr(start, GIT_PATH_LIST_SEPARATOR); - - if (sep) - len = sep - start; - else - len = paths->size; + /* find unescaped separator or end of string */ + for (sep = start = git_buf_cstr(paths); *sep; ++sep) { + if (*sep == GIT_PATH_LIST_SEPARATOR && + (sep <= start || sep[-1] != '\\')) + break; + } - if (git_buf_set(buf, start, len) < 0) + if (git_buf_set(buf, start, (size_t)(sep - start)) < 0) return -1; return git_buf_joinpath(buf, buf->ptr, GIT_CONFIG_FILENAME_GLOBAL); @@ -1276,14 +1274,9 @@ cleanup: return error; } -int git_config_init_backend(git_config_backend* backend, int version) +int git_config_init_backend(git_config_backend *backend, unsigned int version) { - if (version != GIT_CONFIG_BACKEND_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_config_backend", version); - return -1; - } else { - git_config_backend b = GIT_CONFIG_BACKEND_INIT; - memcpy(backend, &b, sizeof(b)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + backend, version, git_config_backend, GIT_CONFIG_BACKEND_INIT); + return 0; } diff --git a/src/diff.c b/src/diff.c index 4b6fbe25a..781f23ec6 100644 --- a/src/diff.c +++ b/src/diff.c @@ -442,6 +442,14 @@ static int diff_list_apply_options( diff->new_src = tmp_src; } + /* Unset UPDATE_INDEX unless diffing workdir and index */ + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_UPDATE_INDEX) && + (!(diff->old_src == GIT_ITERATOR_TYPE_WORKDIR || + diff->new_src == GIT_ITERATOR_TYPE_WORKDIR) || + !(diff->old_src == GIT_ITERATOR_TYPE_INDEX || + diff->new_src == GIT_ITERATOR_TYPE_INDEX))) + diff->opts.flags &= ~GIT_DIFF_UPDATE_INDEX; + /* if ignore_submodules not explicitly set, check diff config */ if (diff->opts.ignore_submodules <= 0) { const git_config_entry *entry; @@ -510,76 +518,105 @@ void git_diff_addref(git_diff *diff) } int git_diff__oid_for_file( - git_repository *repo, + git_oid *out, + git_diff *diff, const char *path, uint16_t mode, - git_off_t size, - git_oid *oid) + git_off_t size) +{ + git_index_entry entry; + + memset(&entry, 0, sizeof(entry)); + entry.mode = mode; + entry.file_size = size; + entry.path = (char *)path; + + return git_diff__oid_for_entry(out, diff, &entry, NULL); +} + +int git_diff__oid_for_entry( + git_oid *out, + git_diff *diff, + const git_index_entry *src, + const git_oid *update_match) { - int result = 0; + int error = 0; git_buf full_path = GIT_BUF_INIT; + git_index_entry entry = *src; + git_filter_list *fl = NULL; + + memset(out, 0, sizeof(*out)); if (git_buf_joinpath( - &full_path, git_repository_workdir(repo), path) < 0) + &full_path, git_repository_workdir(diff->repo), entry.path) < 0) return -1; - if (!mode) { + if (!entry.mode) { struct stat st; - if (p_stat(path, &st) < 0) { - giterr_set(GITERR_OS, "Could not stat '%s'", path); - result = -1; - goto cleanup; + diff->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); + return error; } - mode = st.st_mode; - size = st.st_size; + git_index_entry__init_from_stat( + &entry, &st, (diff->diffcaps & GIT_DIFFCAPS_TRUST_MODE_BITS) != 0); } /* calculate OID for file if possible */ - if (S_ISGITLINK(mode)) { + if (S_ISGITLINK(entry.mode)) { git_submodule *sm; - memset(oid, 0, sizeof(*oid)); - - if (!git_submodule_lookup(&sm, repo, path)) { + if (!git_submodule_lookup(&sm, diff->repo, entry.path)) { const git_oid *sm_oid = git_submodule_wd_id(sm); if (sm_oid) - git_oid_cpy(oid, sm_oid); + git_oid_cpy(out, sm_oid); 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(); - memset(oid, 0, sizeof(*oid)); } - } else if (S_ISLNK(mode)) { - result = git_odb__hashlink(oid, full_path.ptr); - } else if (!git__is_sizet(size)) { - giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'", path); - result = -1; - } else { - git_filter_list *fl = NULL; - - result = git_filter_list_load(&fl, repo, NULL, path, GIT_FILTER_TO_ODB); - if (!result) { - int fd = git_futils_open_ro(full_path.ptr); - if (fd < 0) - result = fd; - else { - result = git_odb__hashfd_filtered( - oid, fd, (size_t)size, GIT_OBJ_BLOB, fl); - p_close(fd); - } - - git_filter_list_free(fl); + } else if (S_ISLNK(entry.mode)) { + error = git_odb__hashlink(out, full_path.ptr); + diff->perf.oid_calculations++; + } else if (!git__is_sizet(entry.file_size)) { + giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'", + entry.path); + error = -1; + } else if (!(error = git_filter_list_load( + &fl, diff->repo, NULL, entry.path, GIT_FILTER_TO_ODB))) + { + 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); + p_close(fd); + diff->perf.oid_calculations++; } + + git_filter_list_free(fl); } -cleanup: + /* update index for entry if requested */ + if (!error && update_match && git_oid_equal(out, update_match)) { + git_index *idx; + + if (!(error = git_repository_index(&idx, diff->repo))) { + memcpy(&entry.id, out, sizeof(entry.id)); + error = git_index_add(idx, &entry); + git_index_free(idx); + } + } + git_buf_free(&full_path); - return result; + return error; } static bool diff_time_eq( @@ -660,6 +697,7 @@ static int maybe_modified( unsigned int omode = oitem->mode; unsigned int nmode = nitem->mode; bool new_is_workdir = (info->new_iter->type == GIT_ITERATOR_TYPE_WORKDIR); + bool modified_uncertain = false; const char *matched_pathspec; int error = 0; @@ -727,15 +765,21 @@ static int maybe_modified( /* if the stat data looks different, then mark modified - this just * means that the OID will be recalculated below to confirm change */ - else if (omode != nmode || - oitem->file_size != nitem->file_size || - !diff_time_eq(&oitem->mtime, &nitem->mtime, use_nanos) || + else if (omode != nmode || oitem->file_size != nitem->file_size) { + status = GIT_DELTA_MODIFIED; + modified_uncertain = + (oitem->file_size <= 0 && nitem->file_size > 0); + } + else if (!diff_time_eq(&oitem->mtime, &nitem->mtime, use_nanos) || (use_ctime && !diff_time_eq(&oitem->ctime, &nitem->ctime, use_nanos)) || oitem->ino != nitem->ino || oitem->uid != nitem->uid || oitem->gid != nitem->gid) + { status = GIT_DELTA_MODIFIED; + modified_uncertain = true; + } } /* if mode is GITLINK and submodules are ignored, then skip */ @@ -746,10 +790,14 @@ static int maybe_modified( /* 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 (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->id)) { + if (modified_uncertain && git_oid_iszero(&nitem->id)) { if (git_oid_iszero(&noid)) { - if ((error = git_diff__oid_for_file(diff->repo, - nitem->path, nitem->mode, nitem->file_size, &noid)) < 0) + const git_oid *update_check = + DIFF_FLAG_IS_SET(diff, GIT_DIFF_UPDATE_INDEX) ? + &oitem->id : NULL; + + if ((error = git_diff__oid_for_entry( + &noid, diff, nitem, update_check)) < 0) return error; } @@ -1066,6 +1114,8 @@ int git_diff__from_iterators( error = 0; } + diff->perf.stat_calls += old_iter->stat_calls + new_iter->stat_calls; + cleanup: if (!error) *diff_ptr = diff; @@ -1174,6 +1224,9 @@ int git_diff_index_to_workdir( &b, repo, GIT_ITERATOR_DONT_AUTOEXPAND, pfx, pfx) ); + if (!error && DIFF_FLAG_IS_SET(*diff, GIT_DIFF_UPDATE_INDEX)) + error = git_index_write(index); + return error; } @@ -1226,20 +1279,6 @@ int git_diff_tree_to_workdir_with_index( return error; } -int git_diff_options_init(git_diff_options *options, unsigned int version) -{ - git_diff_options template = GIT_DIFF_OPTIONS_INIT; - - if (version != template.version) { - giterr_set(GITERR_INVALID, - "Invalid version %d for git_diff_options", (int)version); - return -1; - } - - memcpy(options, &template, sizeof(*options)); - return 0; -} - size_t git_diff_num_deltas(const git_diff *diff) { assert(diff); @@ -1271,6 +1310,15 @@ int git_diff_is_sorted_icase(const git_diff *diff) return (diff->opts.flags & GIT_DIFF_IGNORE_CASE) != 0; } +int git_diff_get_perfdata(git_diff_perfdata *out, const git_diff *diff) +{ + assert(out); + GITERR_CHECK_VERSION(out, GIT_DIFF_PERFDATA_VERSION, "git_diff_perfdata"); + out->stat_calls = diff->perf.stat_calls; + out->oid_calculations = diff->perf.oid_calculations; + return 0; +} + int git_diff__paired_foreach( git_diff *head2idx, git_diff *idx2wd, @@ -1573,38 +1621,26 @@ int git_diff_commit_as_email( return error; } -int git_diff_init_options(git_diff_options* opts, int version) +int git_diff_init_options(git_diff_options *opts, unsigned int version) { - if (version != GIT_DIFF_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_diff_options", version); - return -1; - } else { - git_diff_options o = GIT_DIFF_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_diff_options, GIT_DIFF_OPTIONS_INIT); + return 0; } -int git_diff_find_init_options(git_diff_find_options* opts, int version) +int git_diff_find_init_options( + git_diff_find_options *opts, unsigned int version) { - if (version != GIT_DIFF_FIND_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_diff_find_options", version); - return -1; - } else { - git_diff_find_options o = GIT_DIFF_FIND_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_diff_find_options, GIT_DIFF_FIND_OPTIONS_INIT); + return 0; } -int git_diff_format_email_init_options(git_diff_format_email_options* opts, int version) +int git_diff_format_email_init_options( + git_diff_format_email_options *opts, unsigned int version) { - if (version != GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_diff_format_email_options", version); - return -1; - } else { - git_diff_format_email_options o = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_diff_format_email_options, + GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT); + return 0; } diff --git a/src/diff.h b/src/diff.h index aae8fbff1..3305238d0 100644 --- a/src/diff.h +++ b/src/diff.h @@ -8,6 +8,7 @@ #define INCLUDE_diff_h__ #include "git2/diff.h" +#include "git2/sys/diff.h" #include "git2/oid.h" #include <stdio.h> @@ -62,6 +63,7 @@ struct git_diff { git_iterator_type_t old_src; git_iterator_type_t new_src; uint32_t diffcaps; + git_diff_perfdata perf; int (*strcomp)(const char *, const char *); int (*strncomp)(const char *, const char *, size_t); @@ -90,7 +92,9 @@ extern int git_diff_delta__format_file_header( int oid_strlen); extern int git_diff__oid_for_file( - git_repository *, const char *, uint16_t, git_off_t, git_oid *); + git_oid *out, git_diff *, const char *, uint16_t, git_off_t); +extern int git_diff__oid_for_entry( + git_oid *out, git_diff *, const git_index_entry *, const git_oid *update); extern int git_diff__from_iterators( git_diff **diff_ptr, diff --git a/src/diff_tform.c b/src/diff_tform.c index 97fbc2883..a2dab0ae2 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -574,14 +574,14 @@ static int similarity_measure( if (exact_match) { if (git_oid_iszero(&a_file->id) && diff->old_src == GIT_ITERATOR_TYPE_WORKDIR && - !git_diff__oid_for_file(diff->repo, a_file->path, - a_file->mode, a_file->size, &a_file->id)) + !git_diff__oid_for_file(&a_file->id, + diff, a_file->path, a_file->mode, a_file->size)) a_file->flags |= GIT_DIFF_FLAG_VALID_ID; if (git_oid_iszero(&b_file->id) && diff->new_src == GIT_ITERATOR_TYPE_WORKDIR && - !git_diff__oid_for_file(diff->repo, b_file->path, - b_file->mode, b_file->size, &b_file->id)) + !git_diff__oid_for_file(&b_file->id, + diff, b_file->path, b_file->mode, b_file->size)) b_file->flags |= GIT_DIFF_FLAG_VALID_ID; } diff --git a/src/index.c b/src/index.c index c044af402..8a7f29279 100644 --- a/src/index.c +++ b/src/index.c @@ -842,7 +842,7 @@ static int index_entry_reuc_init(git_index_reuc_entry **reuc_out, static void index_entry_cpy(git_index_entry *tgt, const git_index_entry *src) { - char *tgt_path = tgt->path; + const char *tgt_path = tgt->path; memcpy(tgt, src, sizeof(*tgt)); tgt->path = tgt_path; /* reset to existing path data */ } @@ -2282,9 +2282,7 @@ static int read_tree_cb( entry->mode == old_entry->mode && git_oid_equal(&entry->id, &old_entry->id)) { - char *oldpath = entry->path; - memcpy(entry, old_entry, sizeof(*entry)); - entry->path = oldpath; + index_entry_cpy(entry, old_entry); entry->flags_extended = 0; } diff --git a/src/iterator.c b/src/iterator.c index ef27fa71f..4f8087c8d 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -1016,6 +1016,7 @@ static int fs_iterator__expand_dir(fs_iterator *fi) fs_iterator__free_frame(ff); return GIT_ENOTFOUND; } + fi->base.stat_calls += ff->entries.length; fs_iterator__seek_frame_start(fi, ff); @@ -1304,9 +1305,10 @@ static int workdir_iterator__enter_dir(fs_iterator *fi) /* convert submodules to GITLINK and remove trailing slashes */ git_vector_foreach(&ff->entries, pos, entry) { - if (S_ISDIR(entry->st.st_mode) && - git_submodule__is_submodule(fi->base.repo, entry->path)) - { + if (!S_ISDIR(entry->st.st_mode) || !strcmp(GIT_DIR, entry->path)) + continue; + + if (git_submodule__is_submodule(fi->base.repo, entry->path)) { entry->st.st_mode = GIT_FILEMODE_COMMIT; entry->path_len--; entry->path[entry->path_len] = '\0'; diff --git a/src/iterator.h b/src/iterator.h index ba9c1e486..f67830212 100644 --- a/src/iterator.h +++ b/src/iterator.h @@ -52,6 +52,7 @@ struct git_iterator { char *start; char *end; int (*prefixcomp)(const char *str, const char *prefix); + size_t stat_calls; unsigned int flags; }; diff --git a/src/merge.c b/src/merge.c index 69c42bc0c..6a8e5874f 100644 --- a/src/merge.c +++ b/src/merge.c @@ -2803,38 +2803,24 @@ void git_merge_head_free(git_merge_head *head) git__free(head); } -int git_merge_init_options(git_merge_options *opts, int version) +int git_merge_init_options(git_merge_options *opts, unsigned int version) { - if (version != GIT_MERGE_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_merge_options", version); - return -1; - } else { - git_merge_options default_opts = GIT_MERGE_OPTIONS_INIT; - memcpy(opts, &default_opts, sizeof(git_merge_options)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_merge_options, GIT_MERGE_OPTIONS_INIT); + return 0; } -int git_merge_file_init_input(git_merge_file_input *input, int version) +int git_merge_file_init_input(git_merge_file_input *input, unsigned int version) { - if (version != GIT_MERGE_FILE_INPUT_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_merge_file_input", version); - return -1; - } else { - git_merge_file_input i = GIT_MERGE_FILE_INPUT_INIT; - memcpy(input, &i, sizeof(i)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + input, version, git_merge_file_input, GIT_MERGE_FILE_INPUT_INIT); + return 0; } -int git_merge_file_init_options(git_merge_file_options *opts, int version) +int git_merge_file_init_options( + git_merge_file_options *opts, unsigned int version) { - if (version != GIT_MERGE_FILE_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_merge_file_options", version); - return -1; - } else { - git_merge_file_options o = GIT_MERGE_FILE_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_merge_file_options, GIT_MERGE_FILE_OPTIONS_INIT); + return 0; } @@ -1123,14 +1123,9 @@ int git_odb__error_ambiguous(const char *message) return GIT_EAMBIGUOUS; } -int git_odb_init_backend(git_odb_backend* backend, int version) +int git_odb_init_backend(git_odb_backend *backend, unsigned int version) { - if (version != GIT_ODB_BACKEND_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_odb_backend", version); - return -1; - } else { - git_odb_backend b = GIT_ODB_BACKEND_INIT; - memcpy(backend, &b, sizeof(b)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + backend, version, git_odb_backend, GIT_ODB_BACKEND_INIT); + return 0; } diff --git a/src/push.c b/src/push.c index 9943f215c..be5ec1c0e 100644 --- a/src/push.c +++ b/src/push.c @@ -716,14 +716,9 @@ void git_push_free(git_push *push) git__free(push); } -int git_push_init_options(git_push_options* opts, int version) +int git_push_init_options(git_push_options *opts, unsigned int version) { - if (version != GIT_PUSH_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_push_options", version); - return -1; - } else { - git_push_options o = GIT_PUSH_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_push_options, GIT_PUSH_OPTIONS_INIT); + return 0; } diff --git a/src/refdb.c b/src/refdb.c index 3e7a592f8..69bf74734 100644 --- a/src/refdb.c +++ b/src/refdb.c @@ -236,14 +236,9 @@ int git_refdb_ensure_log(git_refdb *db, const char *refname) return db->backend->ensure_log(db->backend, refname); } -int git_refdb_init_backend(git_refdb_backend* backend, int version) +int git_refdb_init_backend(git_refdb_backend *backend, unsigned int version) { - if (version != GIT_REFDB_BACKEND_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_refdb_backend", version); - return -1; - } else { - git_refdb_backend b = GIT_REFDB_BACKEND_INIT; - memcpy(backend, &b, sizeof(b)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + backend, version, git_refdb_backend, GIT_REFDB_BACKEND_INIT); + return 0; } diff --git a/src/remote.c b/src/remote.c index be7198a98..8f302a51e 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1736,14 +1736,9 @@ const git_refspec *git_remote_get_refspec(const git_remote *remote, size_t n) return git_vector_get(&remote->refspecs, n); } -int git_remote_init_callbacks(git_remote_callbacks* opts, int version) +int git_remote_init_callbacks(git_remote_callbacks *opts, unsigned int version) { - if (version != GIT_REMOTE_CALLBACKS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_remote_callbacks", version); - return -1; - } else { - git_remote_callbacks o = GIT_REMOTE_CALLBACKS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_remote_callbacks, GIT_REMOTE_CALLBACKS_INIT); + return 0; } diff --git a/src/repository.c b/src/repository.c index 8daa04d5d..ac7af7692 100644 --- a/src/repository.c +++ b/src/repository.c @@ -2026,14 +2026,11 @@ int git_repository_is_shallow(git_repository *repo) return st.st_size == 0 ? 0 : 1; } -int git_repository_init_init_options(git_repository_init_options* opts, int version) +int git_repository_init_init_options( + git_repository_init_options *opts, unsigned int version) { - if (version != GIT_REPOSITORY_INIT_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_repository_init_options", version); - return -1; - } else { - git_repository_init_options o = GIT_REPOSITORY_INIT_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_repository_init_options, + GIT_REPOSITORY_INIT_OPTIONS_INIT); + return 0; } diff --git a/src/revert.c b/src/revert.c index 29e124f6c..9c587724b 100644 --- a/src/revert.c +++ b/src/revert.c @@ -220,14 +220,9 @@ done: return error; } -int git_revert_init_opts(git_revert_options* opts, int version) +int git_revert_init_options(git_revert_options *opts, unsigned int version) { - if (version != GIT_REVERT_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_revert_options", version); - return -1; - } else { - git_revert_options o = GIT_REVERT_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_revert_options, GIT_REVERT_OPTIONS_INIT); + return 0; } diff --git a/src/status.c b/src/status.c index c4b990a84..8d7612f72 100644 --- a/src/status.c +++ b/src/status.c @@ -81,15 +81,15 @@ static unsigned int workdir_delta2status( if (git_oid_iszero(&idx2wd->old_file.id) && diff->old_src == GIT_ITERATOR_TYPE_WORKDIR && !git_diff__oid_for_file( - diff->repo, idx2wd->old_file.path, idx2wd->old_file.mode, - idx2wd->old_file.size, &idx2wd->old_file.id)) + &idx2wd->old_file.id, diff, idx2wd->old_file.path, + idx2wd->old_file.mode, idx2wd->old_file.size)) idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_ID; if (git_oid_iszero(&idx2wd->new_file.id) && diff->new_src == GIT_ITERATOR_TYPE_WORKDIR && !git_diff__oid_for_file( - diff->repo, idx2wd->new_file.path, idx2wd->new_file.mode, - idx2wd->new_file.size, &idx2wd->new_file.id)) + &idx2wd->new_file.id, diff, idx2wd->new_file.path, + idx2wd->new_file.mode, idx2wd->new_file.size)) idx2wd->new_file.flags |= GIT_DIFF_FLAG_VALID_ID; if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id)) @@ -225,6 +225,28 @@ static git_status_list *git_status_list_alloc(git_index *index) return status; } +static int status_validate_options(const git_status_options *opts) +{ + if (!opts) + return 0; + + GITERR_CHECK_VERSION(opts, GIT_STATUS_OPTIONS_VERSION, "git_status_options"); + + if (opts->show > GIT_STATUS_SHOW_WORKDIR_ONLY) { + giterr_set(GITERR_INVALID, "Unknown status 'show' option"); + return -1; + } + + if ((opts->flags & GIT_STATUS_OPT_NO_REFRESH) != 0 && + (opts->flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0) { + giterr_set(GITERR_INVALID, "Updating index from status " + "is not allowed when index refresh is disabled"); + return -1; + } + + return 0; +} + int git_status_list_new( git_status_list **out, git_repository *repo, @@ -240,11 +262,10 @@ int git_status_list_new( int error = 0; unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS; - assert(show <= GIT_STATUS_SHOW_WORKDIR_ONLY); - *out = NULL; - GITERR_CHECK_VERSION(opts, GIT_STATUS_OPTIONS_VERSION, "git_status_options"); + if (status_validate_options(opts) < 0) + return -1; if ((error = git_repository__ensure_not_bare(repo, "status")) < 0 || (error = git_repository_index(&index, repo)) < 0) @@ -287,6 +308,8 @@ int git_status_list_new( diffopt.flags = diffopt.flags | GIT_DIFF_RECURSE_IGNORED_DIRS; if ((flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES) != 0) diffopt.flags = diffopt.flags | GIT_DIFF_IGNORE_SUBMODULES; + if ((flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0) + diffopt.flags = diffopt.flags | GIT_DIFF_UPDATE_INDEX; if ((flags & GIT_STATUS_OPT_RENAMES_FROM_REWRITES) != 0) findopt.flags = findopt.flags | @@ -495,14 +518,31 @@ int git_status_should_ignore( return git_ignore_path_is_ignored(ignored, repo, path); } -int git_status_init_options(git_status_options* opts, int version) +int git_status_init_options(git_status_options *opts, unsigned int version) { - if (version != GIT_STATUS_OPTIONS_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_status_options", version); - return -1; - } else { - git_status_options o = GIT_STATUS_OPTIONS_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_status_options, GIT_STATUS_OPTIONS_INIT); + return 0; +} + +int git_status_list_get_perfdata( + git_diff_perfdata *out, const git_status_list *status) +{ + assert(out); + GITERR_CHECK_VERSION(out, GIT_DIFF_PERFDATA_VERSION, "git_diff_perfdata"); + + out->stat_calls = 0; + out->oid_calculations = 0; + + if (status->head2idx) { + out->stat_calls += status->head2idx->perf.stat_calls; + out->oid_calculations += status->head2idx->perf.oid_calculations; + } + if (status->idx2wd) { + out->stat_calls += status->idx2wd->perf.stat_calls; + out->oid_calculations += status->idx2wd->perf.oid_calculations; } + + return 0; } + diff --git a/src/sysdir.c b/src/sysdir.c index aebf23135..e0c24f3b3 100644 --- a/src/sysdir.c +++ b/src/sysdir.c @@ -194,14 +194,19 @@ static int git_sysdir_find_in_dirlist( const git_buf *syspath; GITERR_CHECK_ERROR(git_sysdir_get(&syspath, which)); + if (!syspath || !git_buf_len(syspath)) + goto done; for (scan = git_buf_cstr(syspath); scan; scan = next) { - for (next = strchr(scan, GIT_PATH_LIST_SEPARATOR); - next && next > scan && next[-1] == '\\'; - next = strchr(next + 1, GIT_PATH_LIST_SEPARATOR)) - /* find unescaped separator or end of string */; + /* find unescaped separator or end of string */ + for (next = scan; *next; ++next) { + if (*next == GIT_PATH_LIST_SEPARATOR && + (next <= scan || next[-1] != '\\')) + break; + } - len = next ? (size_t)(next++ - scan) : strlen(scan); + len = (size_t)(next - scan); + next = (*next ? next + 1 : NULL); if (!len) continue; @@ -213,6 +218,7 @@ static int git_sysdir_find_in_dirlist( return 0; } +done: git_buf_free(path); giterr_set(GITERR_OS, "The %s file '%s' doesn't exist", label, name); return GIT_ENOTFOUND; diff --git a/src/transport.c b/src/transport.c index dc074a503..2194b1864 100644 --- a/src/transport.c +++ b/src/transport.c @@ -218,14 +218,9 @@ int git_remote_supported_url(const char* url) return fn != &git_transport_dummy; } -int git_transport_init(git_transport* opts, int version) +int git_transport_init(git_transport *opts, unsigned int version) { - if (version != GIT_TRANSPORT_VERSION) { - giterr_set(GITERR_INVALID, "Invalid version %d for git_transport", version); - return -1; - } else { - git_transport o = GIT_TRANSPORT_INIT; - memcpy(opts, &o, sizeof(o)); - return 0; - } + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_transport, GIT_TRANSPORT_INIT); + return 0; } |