diff --git a/include/git2/config.h b/include/git2/config.h index 95da4bc03..3ab58f1a7 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -612,8 +612,8 @@ GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value); GIT_EXTERN(int) git_config_backend_foreach_match( git_config_backend *backend, const char *regexp, - int (*fn)(const git_config_entry *, void *), - void *data); + git_config_foreach_cb callback, + void *payload); /** @} */ diff --git a/include/git2/errors.h b/include/git2/errors.h index c6076f3ab..26f9a747c 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -71,6 +71,7 @@ typedef enum { GITERR_SSH, GITERR_FILTER, GITERR_REVERT, + GITERR_CALLBACK, } git_error_t; /** diff --git a/src/attr.c b/src/attr.c index 1a0f1f97f..08d7ee99d 100644 --- a/src/attr.c +++ b/src/attr.c @@ -191,11 +191,10 @@ int git_attr_foreach( if (error < 0) goto cleanup; - error = callback(assign->name, assign->value, payload); - if (error) { - error = giterr_user_cancel(); + error = GITERR_CALLBACK( + callback(assign->name, assign->value, payload) ); + if (error) goto cleanup; - } } } } @@ -480,7 +479,6 @@ typedef struct { const char *workdir; git_index *index; git_vector *files; - git_error_state error; } attr_walk_up_info; int git_attr_cache__decide_sources( @@ -524,7 +522,7 @@ static int push_one_attr(void *ref, git_buf *path) info->repo, path->ptr, GIT_ATTR_FILE, src[i], git_attr_file__parse_buffer, NULL, info->files); - return giterr_capture(&info->error, error); + return error; } static int collect_attr_files( @@ -570,8 +568,6 @@ static int collect_attr_files( info.files = files; error = git_path_walk_up(&dir, workdir, push_one_attr, &info); - if (error == GIT_EUSER) - error = giterr_restore(&info.error); if (error < 0) goto cleanup; diff --git a/src/checkout.c b/src/checkout.c index e33ac2ed6..4c64252e4 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -83,10 +83,8 @@ static int checkout_notify( const git_diff_file *baseline = NULL, *target = NULL, *workdir = NULL; const char *path = NULL; - if (!data->opts.notify_cb) - return 0; - - if ((why & data->opts.notify_flags) == 0) + if (!data->opts.notify_cb || + (why & data->opts.notify_flags) == 0) return 0; if (wditem) { @@ -125,8 +123,10 @@ static int checkout_notify( path = delta->old_file.path; } - return data->opts.notify_cb( - why, path, baseline, target, workdir, data->opts.notify_payload); + return giterr_set_callback( + data->opts.notify_cb( + why, path, baseline, target, workdir, data->opts.notify_payload), + "git_checkout notification"); } static bool checkout_is_workdir_modified( @@ -186,69 +186,66 @@ static bool checkout_is_workdir_modified( ((data->strategy & GIT_CHECKOUT_##FLAG) ? CHECKOUT_ACTION__##YES : CHECKOUT_ACTION__##NO) static int checkout_action_common( + int *action, checkout_data *data, - int action, const git_diff_delta *delta, const git_index_entry *wd) { git_checkout_notify_t notify = GIT_CHECKOUT_NOTIFY_NONE; - if (action <= 0) - return action; - if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) - action = (action & ~CHECKOUT_ACTION__REMOVE); + *action = (*action & ~CHECKOUT_ACTION__REMOVE); - if ((action & CHECKOUT_ACTION__UPDATE_BLOB) != 0) { + if ((*action & CHECKOUT_ACTION__UPDATE_BLOB) != 0) { if (S_ISGITLINK(delta->new_file.mode)) - action = (action & ~CHECKOUT_ACTION__UPDATE_BLOB) | + *action = (*action & ~CHECKOUT_ACTION__UPDATE_BLOB) | CHECKOUT_ACTION__UPDATE_SUBMODULE; /* to "update" a symlink, we must remove the old one first */ if (delta->new_file.mode == GIT_FILEMODE_LINK && wd != NULL) - action |= CHECKOUT_ACTION__REMOVE; + *action |= CHECKOUT_ACTION__REMOVE; notify = GIT_CHECKOUT_NOTIFY_UPDATED; } - if ((action & CHECKOUT_ACTION__CONFLICT) != 0) + if ((*action & CHECKOUT_ACTION__CONFLICT) != 0) notify = GIT_CHECKOUT_NOTIFY_CONFLICT; - if (notify != GIT_CHECKOUT_NOTIFY_NONE && - checkout_notify(data, notify, delta, wd) != 0) - return giterr_user_cancel(); - - return action; + return checkout_notify(data, notify, delta, wd); } static int checkout_action_no_wd( + int *action, checkout_data *data, const git_diff_delta *delta) { - int action = CHECKOUT_ACTION__NONE; + int error = 0; + + *action = CHECKOUT_ACTION__NONE; switch (delta->status) { case GIT_DELTA_UNMODIFIED: /* case 12 */ - if (checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL)) - return giterr_user_cancel(); - action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, NONE); + error = checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL); + if (error) + return error; + *action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, NONE); break; case GIT_DELTA_ADDED: /* case 2 or 28 (and 5 but not really) */ - action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); + *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); break; case GIT_DELTA_MODIFIED: /* case 13 (and 35 but not really) */ - action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, CONFLICT); + *action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, CONFLICT); break; case GIT_DELTA_TYPECHANGE: /* case 21 (B->T) and 28 (T->B)*/ if (delta->new_file.mode == GIT_FILEMODE_TREE) - action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); + *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); break; case GIT_DELTA_DELETED: /* case 8 or 25 */ default: /* impossible */ break; } - return checkout_action_common(data, action, delta, NULL); + return checkout_action_common(action, data, delta, NULL); } static int checkout_action_wd_only( @@ -257,6 +254,7 @@ static int checkout_action_wd_only( const git_index_entry *wd, git_vector *pathspec) { + int error = 0; bool remove = false; git_checkout_notify_t notify = GIT_CHECKOUT_NOTIFY_NONE; @@ -269,13 +267,13 @@ static int checkout_action_wd_only( /* check if item is tracked in the index but not in the checkout diff */ if (data->index != NULL) { if (wd->mode != GIT_FILEMODE_TREE) { - int error; - - if ((error = git_index_find(NULL, data->index, wd->path)) == 0) { + if (!(error = git_index_find(NULL, data->index, wd->path))) { notify = GIT_CHECKOUT_NOTIFY_DIRTY; remove = ((data->strategy & GIT_CHECKOUT_FORCE) != 0); } else if (error != GIT_ENOTFOUND) return error; + else + giterr_clear(); } else { /* for tree entries, we have to see if there are any index * entries that are contained inside that tree @@ -301,18 +299,16 @@ static int checkout_action_wd_only( remove = ((data->strategy & GIT_CHECKOUT_REMOVE_UNTRACKED) != 0); } - if (checkout_notify(data, notify, NULL, wd)) - return giterr_user_cancel(); + error = checkout_notify(data, notify, NULL, wd); - if (remove) { + if (!error && remove) { char *path = git_pool_strdup(&data->pool, wd->path); GITERR_CHECK_ALLOC(path); - if (git_vector_insert(&data->removes, path) < 0) - return -1; + error = git_vector_insert(&data->removes, path); } - return 0; + return error; } static bool submodule_is_config_only( @@ -331,35 +327,35 @@ static bool submodule_is_config_only( } static int checkout_action_with_wd( + int *action, checkout_data *data, const git_diff_delta *delta, const git_index_entry *wd) { - int action = CHECKOUT_ACTION__NONE; + *action = CHECKOUT_ACTION__NONE; switch (delta->status) { case GIT_DELTA_UNMODIFIED: /* case 14/15 or 33 */ if (checkout_is_workdir_modified(data, &delta->old_file, wd)) { - if (checkout_notify( - data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd)) - return giterr_user_cancel(); - action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, NONE); + GITERR_CHECK_ERROR( + checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd) ); + *action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, NONE); } break; case GIT_DELTA_ADDED: /* case 3, 4 or 6 */ - action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT); break; case GIT_DELTA_DELETED: /* case 9 or 10 (or 26 but not really) */ if (checkout_is_workdir_modified(data, &delta->old_file, wd)) - action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT); else - action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE); + *action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE); break; case GIT_DELTA_MODIFIED: /* case 16, 17, 18 (or 36 but not really) */ if (checkout_is_workdir_modified(data, &delta->old_file, wd)) - action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT); else - action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); + *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); break; case GIT_DELTA_TYPECHANGE: /* case 22, 23, 29, 30 */ if (delta->old_file.mode == GIT_FILEMODE_TREE) { @@ -367,92 +363,93 @@ static int checkout_action_with_wd( /* either deleting items in old tree will delete the wd dir, * or we'll get a conflict when we attempt blob update... */ - action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); + *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); else if (wd->mode == GIT_FILEMODE_COMMIT) { /* workdir is possibly a "phantom" submodule - treat as a * tree if the only submodule info came from the config */ if (submodule_is_config_only(data, wd->path)) - action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); + *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); else - action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); } else - action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT); } else if (checkout_is_workdir_modified(data, &delta->old_file, wd)) - action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); else - action = CHECKOUT_ACTION_IF(SAFE, REMOVE_AND_UPDATE, NONE); + *action = CHECKOUT_ACTION_IF(SAFE, REMOVE_AND_UPDATE, NONE); /* don't update if the typechange is to a tree */ if (delta->new_file.mode == GIT_FILEMODE_TREE) - action = (action & ~CHECKOUT_ACTION__UPDATE_BLOB); + *action = (*action & ~CHECKOUT_ACTION__UPDATE_BLOB); break; default: /* impossible */ break; } - return checkout_action_common(data, action, delta, wd); + return checkout_action_common(action, data, delta, wd); } static int checkout_action_with_wd_blocker( + int *action, checkout_data *data, const git_diff_delta *delta, const git_index_entry *wd) { - int action = CHECKOUT_ACTION__NONE; + *action = CHECKOUT_ACTION__NONE; switch (delta->status) { case GIT_DELTA_UNMODIFIED: /* should show delta as dirty / deleted */ - if (checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd)) - return giterr_user_cancel(); - action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, NONE); + GITERR_CHECK_ERROR( + checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd) ); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, NONE); break; case GIT_DELTA_ADDED: case GIT_DELTA_MODIFIED: - action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); break; case GIT_DELTA_DELETED: - action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT); break; case GIT_DELTA_TYPECHANGE: /* not 100% certain about this... */ - action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); break; default: /* impossible */ break; } - return checkout_action_common(data, action, delta, wd); + return checkout_action_common(action, data, delta, wd); } static int checkout_action_with_wd_dir( + int *action, checkout_data *data, const git_diff_delta *delta, const git_index_entry *wd) { - int action = CHECKOUT_ACTION__NONE; + *action = CHECKOUT_ACTION__NONE; switch (delta->status) { case GIT_DELTA_UNMODIFIED: /* case 19 or 24 (or 34 but not really) */ - if (checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL) || - checkout_notify( - data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd)) - return giterr_user_cancel(); + GITERR_CHECK_ERROR( + checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL)); + GITERR_CHECK_ERROR( + checkout_notify(data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd)); break; case GIT_DELTA_ADDED:/* case 4 (and 7 for dir) */ case GIT_DELTA_MODIFIED: /* case 20 (or 37 but not really) */ if (delta->old_file.mode == GIT_FILEMODE_COMMIT) /* expected submodule (and maybe found one) */; else if (delta->new_file.mode != GIT_FILEMODE_TREE) - action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); break; case GIT_DELTA_DELETED: /* case 11 (and 27 for dir) */ - if (delta->old_file.mode != GIT_FILEMODE_TREE && - checkout_notify( - data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd)) - return giterr_user_cancel(); + if (delta->old_file.mode != GIT_FILEMODE_TREE) + GITERR_CHECK_ERROR( + checkout_notify(data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd)); break; case GIT_DELTA_TYPECHANGE: /* case 24 or 31 */ if (delta->old_file.mode == GIT_FILEMODE_TREE) { @@ -462,39 +459,41 @@ static int checkout_action_with_wd_dir( * directory if is it left empty, so we can defer removing the * dir and it will succeed if no children are left. */ - action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); - if (action != CHECKOUT_ACTION__NONE) - action |= CHECKOUT_ACTION__DEFER_REMOVE; + *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); + if (*action != CHECKOUT_ACTION__NONE) + *action |= CHECKOUT_ACTION__DEFER_REMOVE; } else if (delta->new_file.mode != GIT_FILEMODE_TREE) /* For typechange to dir, dir is already created so no action */ - action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); + *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); break; default: /* impossible */ break; } - return checkout_action_common(data, action, delta, wd); + return checkout_action_common(action, data, delta, wd); } static int checkout_action( + int *action, checkout_data *data, git_diff_delta *delta, git_iterator *workdir, - const git_index_entry **wditem_ptr, + const git_index_entry **wditem, git_vector *pathspec) { - const git_index_entry *wd = *wditem_ptr; - int cmp = -1, act; + int cmp = -1, error; int (*strcomp)(const char *, const char *) = data->diff->strcomp; int (*pfxcomp)(const char *str, const char *pfx) = data->diff->pfxcomp; - int error; + int (*advance)(const git_index_entry **, git_iterator *) = NULL; /* move workdir iterator to follow along with deltas */ while (1) { + const git_index_entry *wd = *wditem; + if (!wd) - return checkout_action_no_wd(data, delta); + return checkout_action_no_wd(action, data, delta); cmp = strcomp(wd->path, delta->old_file.path); @@ -512,79 +511,77 @@ static int checkout_action( if (cmp == 0) { if (wd->mode == GIT_FILEMODE_TREE) { /* case 2 - entry prefixed by workdir tree */ - error = git_iterator_advance_into_or_over(&wd, workdir); - if (error && error != GIT_ITEROVER) - goto fail; - *wditem_ptr = wd; + error = git_iterator_advance_into_or_over(wditem, workdir); + if (error < 0 && error != GIT_ITEROVER) + goto done; continue; } /* case 3 maybe - wd contains non-dir where dir expected */ if (delta->old_file.path[strlen(wd->path)] == '/') { - act = checkout_action_with_wd_blocker(data, delta, wd); - *wditem_ptr = - git_iterator_advance(&wd, workdir) ? NULL : wd; - return act; + error = checkout_action_with_wd_blocker( + action, data, delta, wd); + advance = git_iterator_advance; + goto done; } } /* case 1 - handle wd item (if it matches pathspec) */ - if (checkout_action_wd_only(data, workdir, wd, pathspec) < 0) - goto fail; - if ((error = git_iterator_advance(&wd, workdir)) < 0 && + error = checkout_action_wd_only(data, workdir, wd, pathspec); + if (error) + goto done; + if ((error = git_iterator_advance(wditem, workdir)) < 0 && error != GIT_ITEROVER) - goto fail; - - *wditem_ptr = wd; + goto done; continue; } if (cmp == 0) { /* case 4 */ - act = checkout_action_with_wd(data, delta, wd); - *wditem_ptr = git_iterator_advance(&wd, workdir) ? NULL : wd; - return act; + error = checkout_action_with_wd(action, data, delta, wd); + advance = git_iterator_advance; + goto done; } cmp = pfxcomp(wd->path, delta->old_file.path); if (cmp == 0) { /* case 5 */ if (wd->path[strlen(delta->old_file.path)] != '/') - return checkout_action_no_wd(data, delta); + return checkout_action_no_wd(action, data, delta); if (delta->status == GIT_DELTA_TYPECHANGE) { if (delta->old_file.mode == GIT_FILEMODE_TREE) { - act = checkout_action_with_wd(data, delta, wd); - if ((error = git_iterator_advance_into(&wd, workdir)) < 0 && - error != GIT_ENOTFOUND) - goto fail; - *wditem_ptr = wd; - return act; + error = checkout_action_with_wd(action, data, delta, wd); + advance = git_iterator_advance_into; + goto done; } if (delta->new_file.mode == GIT_FILEMODE_TREE || delta->new_file.mode == GIT_FILEMODE_COMMIT || delta->old_file.mode == GIT_FILEMODE_COMMIT) { - act = checkout_action_with_wd(data, delta, wd); - if ((error = git_iterator_advance(&wd, workdir)) < 0 && - error != GIT_ITEROVER) - goto fail; - *wditem_ptr = wd; - return act; + error = checkout_action_with_wd(action, data, delta, wd); + advance = git_iterator_advance; + goto done; } } - return checkout_action_with_wd_dir(data, delta, wd); + return checkout_action_with_wd_dir(action, data, delta, wd); } /* case 6 - wd is after delta */ - return checkout_action_no_wd(data, delta); + return checkout_action_no_wd(action, data, delta); } -fail: - *wditem_ptr = NULL; - return -1; +done: + if (!error && advance != NULL && + (error = advance(wditem, workdir)) < 0) { + *wditem = NULL; + if (error == GIT_ITEROVER) + error = 0; + } + + return error; } static int checkout_remaining_wd_items( @@ -965,7 +962,7 @@ static int checkout_get_actions( checkout_data *data, git_iterator *workdir) { - int error = 0; + int error = 0, act; const git_index_entry *wditem; git_vector pathspec = GIT_VECTOR_INIT, *deltas; git_pool pathpool = GIT_POOL_INIT_STRINGPOOL; @@ -992,12 +989,9 @@ static int checkout_get_actions( } git_vector_foreach(deltas, i, delta) { - int act = checkout_action(data, delta, workdir, &wditem, &pathspec); - - if (act < 0) { - error = act; + error = checkout_action(&act, data, delta, workdir, &wditem, &pathspec); + if (error) goto fail; - } actions[i] = act; @@ -1012,7 +1006,7 @@ static int checkout_get_actions( } error = checkout_remaining_wd_items(data, workdir, wditem, &pathspec); - if (error < 0) + if (error) goto fail; counts[CHECKOUT_ACTION__REMOVE] += data->removes.length; diff --git a/src/clone.c b/src/clone.c index 415efabba..ffbe8f8af 100644 --- a/src/clone.c +++ b/src/clone.c @@ -107,7 +107,6 @@ struct head_info { git_buf branchname; const git_refspec *refspec; bool found; - git_error_state error; }; static int reference_matches_remote_head( @@ -147,7 +146,7 @@ static int reference_matches_remote_head( } } - return giterr_capture(&head_info->error, error); + return error; } static int update_head_to_new_branch( @@ -209,12 +208,8 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) /* Check to see if the remote HEAD points to the remote master */ error = reference_matches_remote_head( git_buf_cstr(&remote_master_name), &head_info); - - if (error < 0) { - error = giterr_restore(&head_info.error); - if (error < 0 && error != GIT_ITEROVER) - goto cleanup; - } + if (error < 0 && error != GIT_ITEROVER) + goto cleanup; if (head_info.found) { error = update_head_to_new_branch( @@ -227,9 +222,6 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) /* Not master. Check all the other refs. */ error = git_reference_foreach_name( repo, reference_matches_remote_head, &head_info); - - if (error == GIT_EUSER) - error = giterr_restore(&head_info.error); if (error < 0 && error != GIT_ITEROVER) goto cleanup; @@ -349,7 +341,7 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_ old_fetchhead = git_remote_update_fetchhead(remote); git_remote_set_update_fetchhead(remote, 0); - if ((error = git_remote_fetch(remote)) < 0) + if ((error = git_remote_fetch(remote)) != 0) goto cleanup; if (branch) @@ -363,10 +355,12 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_ cleanup: git_remote_set_update_fetchhead(remote, old_fetchhead); + /* Go back to the original refspecs */ - if (git_remote_set_fetch_refspecs(remote, &refspecs) < 0) { - git_strarray_free(&refspecs); - return -1; + { + int error_alt = git_remote_set_fetch_refspecs(remote, &refspecs); + if (!error) + error = error_alt; } git_strarray_free(&refspecs); diff --git a/src/common.h b/src/common.h index 0ad4130aa..a0e47df9a 100644 --- a/src/common.h +++ b/src/common.h @@ -62,7 +62,7 @@ * Check a return value and propogate result if non-zero. */ #define GITERR_CHECK_ERROR(code) \ - do { int _err = (code); if (_err < 0) return _err; } while (0) + do { int _err = (code); if (_err) return _err; } while (0) /** * Set the error message for this thread, formatting as needed. @@ -75,6 +75,27 @@ void giterr_set(int error_class, const char *string, ...); */ int giterr_set_regex(const regex_t *regex, int error_code); +/** + * Set error message for user callback if needed. + * + * If the error code in non-zero and no error message is set, this + * sets a generic error message. + * + * @return This always returns the `error_code` parameter. + */ +GIT_INLINE(int) giterr_set_callback(int error_code, const char *action) +{ + if (error_code) { + const git_error *e = giterr_last(); + if (!e || !e->message) + giterr_set(e ? e->klass : GITERR_CALLBACK, + "%s callback returned %d", action, error_code); + } + return error_code; +} + +#define GITERR_CALLBACK(code) giterr_set_callback((code), __func__) + /** * Gets the system error code for this thread. */ @@ -85,15 +106,6 @@ int giterr_system_last(void); */ void giterr_system_set(int code); -/** - * Note that a user cancelled an operation with GIT_EUSER - */ -GIT_INLINE(int) giterr_user_cancel(void) -{ - giterr_clear(); - return GIT_EUSER; -} - /** * Structure to preserve libgit2 error state */ diff --git a/src/config.c b/src/config.c index 3af9d58de..8b3a426ed 100644 --- a/src/config.c +++ b/src/config.c @@ -480,23 +480,23 @@ int git_config_foreach( int git_config_backend_foreach_match( git_config_backend *backend, const char *regexp, - int (*fn)(const git_config_entry *, void *), - void *data) + git_config_foreach_cb cb, + void *payload) { git_config_entry *entry; git_config_iterator* iter; regex_t regex; - int result = 0; + int error = 0; if (regexp != NULL) { - if ((result = regcomp(®ex, regexp, REG_EXTENDED)) < 0) { - giterr_set_regex(®ex, result); + if ((error = regcomp(®ex, regexp, REG_EXTENDED)) < 0) { + giterr_set_regex(®ex, error); regfree(®ex); return -1; } } - if ((result = backend->iterator(&iter, backend)) < 0) { + if ((error = backend->iterator(&iter, backend)) < 0) { iter = NULL; return -1; } @@ -507,10 +507,9 @@ int git_config_backend_foreach_match( continue; /* abort iterator on non-zero return value */ - if (fn(entry, data)) { - result = giterr_user_cancel(); + error = GITERR_CALLBACK( cb(entry, payload) ); + if (error) break; - } } if (regexp != NULL) @@ -518,7 +517,7 @@ int git_config_backend_foreach_match( iter->free(iter); - return result; + return error; } int git_config_foreach_match( @@ -534,12 +533,9 @@ int git_config_foreach_match( if ((error = git_config_iterator_glob_new(&iter, cfg, regexp)) < 0) return error; - while ((error = git_config_next(&entry, iter)) == 0) { - if (cb(entry, payload)) { - error = giterr_user_cancel(); - break; - } - } + while (!(error = git_config_next(&entry, iter)) && + !(error = GITERR_CALLBACK( cb(entry, payload) ))) + /* make callback on each config */; git_config_iterator_free(iter); @@ -798,10 +794,8 @@ int git_config_get_multivar_foreach( while ((err = iter->next(&entry, iter)) == 0) { found = 1; - if (cb(entry, payload)) { - iter->free(iter); - return giterr_user_cancel(); - } + if ((err = GITERR_CALLBACK( cb(entry, payload) )) != 0) + break; } iter->free(iter); @@ -1212,7 +1206,6 @@ struct rename_data { git_config *config; git_buf *name; size_t old_len; - git_error_state error; }; static int rename_config_entries_cb( @@ -1235,8 +1228,7 @@ static int rename_config_entries_cb( if (!error) error = git_config_delete_entry(data->config, entry->name); - /* capture error message as needed, since it will become EUSER */ - return giterr_capture(&data->error, error); + return error; } int git_config_rename_section( @@ -1257,7 +1249,6 @@ int git_config_rename_section( if ((error = git_repository_config__weakptr(&config, repo)) < 0) goto cleanup; - memset(&data, 0, sizeof(data)); data.config = config; data.name = &replace; data.old_len = strlen(old_section_name) + 1; @@ -1277,9 +1268,6 @@ int git_config_rename_section( error = git_config_foreach_match( config, git_buf_cstr(&pattern), rename_config_entries_cb, &data); - if (error == GIT_EUSER) - error = giterr_restore(&data.error); - cleanup: git_buf_free(&pattern); git_buf_free(&replace); diff --git a/src/diff.c b/src/diff.c index af47e86aa..101426f6e 100644 --- a/src/diff.c +++ b/src/diff.c @@ -49,16 +49,25 @@ static git_diff_delta *diff_delta__alloc( return delta; } -static int diff_notify( - const git_diff *diff, - const git_diff_delta *delta, - const char *matched_pathspec) +static int diff_insert_delta( + git_diff *diff, git_diff_delta *delta, const char *matched_pathspec) { - if (!diff->opts.notify_cb) - return 0; + int error = 0; - return diff->opts.notify_cb( - diff, delta, matched_pathspec, diff->opts.notify_payload); + if (diff->opts.notify_cb) { + error = diff->opts.notify_cb( + diff, delta, matched_pathspec, diff->opts.notify_payload); + + if (error) { + git__free(delta); + return (error > 0) ? 0 : giterr_set_callback(error, "git_diff"); + } + } + + if ((error = git_vector_insert(&diff->deltas, delta)) < 0) + git__free(delta); + + return error; } static int diff_delta__from_one( @@ -68,7 +77,6 @@ static int diff_delta__from_one( { git_diff_delta *delta; const char *matched_pathspec; - int notify_res; if ((entry->flags & GIT_IDXENTRY_VALID) != 0) return 0; @@ -111,21 +119,12 @@ static int diff_delta__from_one( !git_oid_iszero(&delta->new_file.oid)) delta->new_file.flags |= GIT_DIFF_FLAG_VALID_OID; - notify_res = diff_notify(diff, delta, matched_pathspec); - - if (notify_res) - git__free(delta); - else if (git_vector_insert(&diff->deltas, delta) < 0) { - git__free(delta); - return -1; - } - - return notify_res < 0 ? giterr_user_cancel() : 0; + return diff_insert_delta(diff, delta, matched_pathspec); } static int diff_delta__from_two( git_diff *diff, - git_delta_t status, + git_delta_t status, const git_index_entry *old_entry, uint32_t old_mode, const git_index_entry *new_entry, @@ -134,7 +133,6 @@ static int diff_delta__from_two( const char *matched_pathspec) { git_diff_delta *delta; - int notify_res; const char *canonical_path = old_entry->path; if (status == GIT_DELTA_UNMODIFIED && @@ -173,16 +171,7 @@ static int diff_delta__from_two( if (new_oid || !git_oid_iszero(&new_entry->oid)) delta->new_file.flags |= GIT_DIFF_FLAG_VALID_OID; - notify_res = diff_notify(diff, delta, matched_pathspec); - - if (notify_res) - git__free(delta); - else if (git_vector_insert(&diff->deltas, delta) < 0) { - git__free(delta); - return -1; - } - - return notify_res < 0 ? giterr_user_cancel() : 0; + return diff_insert_delta(diff, delta, matched_pathspec); } static git_diff_delta *diff_delta__last_for_item( @@ -654,6 +643,7 @@ static int maybe_modified( unsigned int nmode = nitem->mode; bool new_is_workdir = (info->new_iter->type == GIT_ITERATOR_TYPE_WORKDIR); const char *matched_pathspec; + int error = 0; if (!git_pathspec__match( &diff->pathspec, oitem->path, @@ -688,10 +678,9 @@ static int maybe_modified( if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE)) status = GIT_DELTA_TYPECHANGE; else { - if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 || - diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem) < 0) - return -1; - return 0; + if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem))) + error = diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem); + return error; } } @@ -713,8 +702,8 @@ static int maybe_modified( /* TODO: add check against index file st_mtime to avoid racy-git */ if (S_ISGITLINK(nmode)) { - if (maybe_modified_submodule(&status, &noid, diff, info) < 0) - return -1; + if ((error = maybe_modified_submodule(&status, &noid, diff, info)) < 0) + return error; } /* if the stat data looks different, then mark modified - this just @@ -741,9 +730,9 @@ static int maybe_modified( */ if (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->oid)) { if (git_oid_iszero(&noid)) { - if (git_diff__oid_for_file(diff->repo, - nitem->path, nitem->mode, nitem->file_size, &noid) < 0) - return -1; + if ((error = git_diff__oid_for_file(diff->repo, + nitem->path, nitem->mode, nitem->file_size, &noid)) < 0) + return error; } /* if oid matches, then mark unmodified (except submodules, where @@ -898,7 +887,7 @@ static int handle_unmatched_new_item( git_diff_delta *last; /* attempt to insert record for this directory */ - if ((error = diff_delta__from_one(diff, delta_type, nitem)) < 0) + if ((error = diff_delta__from_one(diff, delta_type, nitem)) != 0) return error; /* if delta wasn't created (because of rules), just skip ahead */ @@ -977,7 +966,7 @@ static int handle_unmatched_new_item( } /* Actually create the record for this item if necessary */ - if ((error = diff_delta__from_one(diff, delta_type, nitem)) < 0) + if ((error = diff_delta__from_one(diff, delta_type, nitem)) != 0) return error; /* If user requested TYPECHANGE records, then check for that instead of @@ -1002,7 +991,7 @@ static int handle_unmatched_old_item( git_diff *diff, diff_in_progress *info) { int error = diff_delta__from_one(diff, GIT_DELTA_DELETED, info->oitem); - if (error < 0) + if (error != 0) return error; /* if we are generating TYPECHANGE records then check for that @@ -1399,10 +1388,8 @@ int git_diff__paired_foreach( i++; j++; } - if (cb(h2i, i2w, payload)) { - error = giterr_user_cancel(); + if ((error = GITERR_CALLBACK( cb(h2i, i2w, payload) )) != 0) break; - } } /* restore case-insensitive delta sort */ diff --git a/src/diff_patch.c b/src/diff_patch.c index c0910558e..11f02478d 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -32,7 +32,6 @@ struct git_patch { git_array_t(git_diff_line) lines; size_t content_size, context_size, header_size; git_pool flattened; - git_error_state error; }; enum { @@ -200,11 +199,12 @@ static int diff_patch_invoke_file_callback( float progress = patch->diff ? ((float)patch->delta_index / patch->diff->deltas.length) : 1.0f; - if (output->file_cb && - output->file_cb(patch->delta, progress, output->payload) != 0) - return giterr_user_cancel(); + if (!output->file_cb) + return 0; - return 0; + return giterr_set_callback( + output->file_cb(patch->delta, progress, output->payload), + "git_patch"); } static int diff_patch_generate(git_patch *patch, git_diff_output *output) @@ -291,7 +291,7 @@ int git_diff_foreach( git_patch_free(&patch); - if (error < 0) + if (error) break; } @@ -331,9 +331,6 @@ static int diff_single_generate(diff_patch_with_delta *pd, git_xdiff_output *xo) if (!error) error = diff_patch_generate(patch, (git_diff_output *)xo); - if (error == GIT_EUSER) - giterr_clear(); /* don't leave error message set invalidly */ - return error; } @@ -462,9 +459,6 @@ int git_patch_from_blobs( error = diff_patch_from_blobs( pd, &xo, old_blob, old_path, new_blob, new_path, opts); - if (error == GIT_EUSER) - error = giterr_restore(&pd->patch.error); - if (!error) *out = (git_patch *)pd; else @@ -576,9 +570,6 @@ int git_patch_from_blob_and_buffer( error = diff_patch_from_blob_and_buffer( pd, &xo, old_blob, old_path, buf, buflen, buf_path, opts); - if (error == GIT_EUSER) - error = giterr_restore(&pd->patch.error); - if (!error) *out = (git_patch *)pd; else @@ -627,12 +618,9 @@ int git_patch_from_diff( if (!error) error = diff_patch_generate(patch, &xo.output); - if (error == GIT_EUSER) - error = giterr_restore(&patch->error); - if (!error) { - /* if cumulative diff size is < 0.5 total size, flatten the patch */ - /* unload the file content */ + /* TODO: if cumulative diff size is < 0.5 total size, flatten patch */ + /* TODO: and unload the file content */ } if (error || !patch_ptr) @@ -640,8 +628,6 @@ int git_patch_from_diff( else *patch_ptr = patch; - if (error == GIT_EUSER) - giterr_clear(); /* don't leave error message set invalidly */ return error; } @@ -879,8 +865,7 @@ static int diff_patch_hunk_cb( GIT_UNUSED(delta); hunk = git_array_alloc(patch->hunks); - if (!hunk) - return giterr_capture(&patch->error, -1); + GITERR_CHECK_ALLOC(hunk); memcpy(&hunk->hunk, hunk_, sizeof(hunk->hunk)); @@ -909,8 +894,7 @@ static int diff_patch_line_cb( assert(hunk); /* programmer error if no hunk is available */ line = git_array_alloc(patch->lines); - if (!line) - return giterr_capture(&patch->error, -1); + GITERR_CHECK_ALLOC(line); memcpy(line, line_, sizeof(*line)); diff --git a/src/diff_print.c b/src/diff_print.c index 712402864..ff477e4c8 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -18,7 +18,6 @@ typedef struct { uint32_t flags; int oid_strlen; git_diff_line line; - git_error_state error; } diff_print_info; static int diff_print_info_init( @@ -34,7 +33,6 @@ static int diff_print_info_init( pi->print_cb = cb; pi->payload = payload; pi->buf = out; - memset(&pi->error, 0, sizeof(pi->error)); if (diff) pi->flags = diff->opts.flags; @@ -104,19 +102,16 @@ static int diff_print_one_name_only( return 0; git_buf_clear(out); - - if (git_buf_puts(out, delta->new_file.path) < 0 || - git_buf_putc(out, '\n')) - return giterr_capture(&pi->error, -1); + git_buf_puts(out, delta->new_file.path); + git_buf_putc(out, '\n'); + if (git_buf_oom(out)) + return -1; pi->line.origin = GIT_DIFF_LINE_FILE_HDR; pi->line.content = git_buf_cstr(out); pi->line.content_len = git_buf_len(out); - if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) - return giterr_user_cancel(); - - return 0; + return pi->print_cb(delta, NULL, &pi->line, pi->payload); } static int diff_print_one_name_status( @@ -150,18 +145,14 @@ static int diff_print_one_name_status( git_buf_printf(out, "%c\t%s%c\n", code, delta->old_file.path, old_suffix); else git_buf_printf(out, "%c\t%s\n", code, delta->old_file.path); - if (git_buf_oom(out)) - return giterr_capture(&pi->error, -1); + return -1; pi->line.origin = GIT_DIFF_LINE_FILE_HDR; pi->line.content = git_buf_cstr(out); pi->line.content_len = git_buf_len(out); - if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) - return giterr_user_cancel(); - - return 0; + return pi->print_cb(delta, NULL, &pi->line, pi->payload); } static int diff_print_one_raw( @@ -198,16 +189,13 @@ static int diff_print_one_raw( delta->old_file.path : delta->new_file.path); if (git_buf_oom(out)) - return giterr_capture(&pi->error, -1); + return -1; pi->line.origin = GIT_DIFF_LINE_FILE_HDR; pi->line.content = git_buf_cstr(out); pi->line.content_len = git_buf_len(out); - if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) - return giterr_user_cancel(); - - return 0; + return pi->print_cb(delta, NULL, &pi->line, pi->payload); } static int diff_print_oid_range( @@ -234,10 +222,7 @@ static int diff_print_oid_range( git_buf_printf(out, "index %s..%s\n", start_oid, end_oid); } - if (git_buf_oom(out)) - return -1; - - return 0; + return git_buf_oom(out) ? -1 : 0; } static int diff_delta_format_with_paths( @@ -281,8 +266,7 @@ int git_diff_delta__format_file_header( git_buf_printf(out, "diff --git %s%s %s%s\n", oldpfx, delta->old_file.path, newpfx, delta->new_file.path); - if (diff_print_oid_range(out, delta, oid_strlen) < 0) - return -1; + GITERR_CHECK_ERROR(diff_print_oid_range(out, delta, oid_strlen)); if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) diff_delta_format_with_paths( @@ -294,6 +278,7 @@ int git_diff_delta__format_file_header( static int diff_print_patch_file( const git_diff_delta *delta, float progress, void *data) { + int error; diff_print_info *pi = data; const char *oldpfx = pi->diff ? pi->diff->opts.old_prefix : DIFF_OLD_PREFIX_DEFAULT; @@ -309,36 +294,33 @@ static int diff_print_patch_file( (pi->flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) == 0)) return 0; - if (git_diff_delta__format_file_header( - pi->buf, delta, oldpfx, newpfx, pi->oid_strlen) < 0) - return giterr_capture(&pi->error, -1); + if ((error = git_diff_delta__format_file_header( + pi->buf, delta, oldpfx, newpfx, pi->oid_strlen)) < 0) + return error; pi->line.origin = GIT_DIFF_LINE_FILE_HDR; pi->line.content = git_buf_cstr(pi->buf); pi->line.content_len = git_buf_len(pi->buf); - if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) - return giterr_user_cancel(); + if ((error = pi->print_cb(delta, NULL, &pi->line, pi->payload)) != 0) + return error; if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) return 0; git_buf_clear(pi->buf); - if (diff_delta_format_with_paths( + if ((error = diff_delta_format_with_paths( pi->buf, delta, oldpfx, newpfx, - "Binary files %s%s and %s%s differ\n") < 0) - return giterr_capture(&pi->error, -1); + "Binary files %s%s and %s%s differ\n")) < 0) + return error; pi->line.origin = GIT_DIFF_LINE_BINARY; pi->line.content = git_buf_cstr(pi->buf); pi->line.content_len = git_buf_len(pi->buf); pi->line.num_lines = 1; - if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) - return giterr_user_cancel(); - - return 0; + return pi->print_cb(delta, NULL, &pi->line, pi->payload); } static int diff_print_patch_hunk( @@ -355,10 +337,7 @@ static int diff_print_patch_hunk( pi->line.content = h->header; pi->line.content_len = h->header_len; - if (pi->print_cb(d, h, &pi->line, pi->payload)) - return giterr_user_cancel(); - - return 0; + return pi->print_cb(d, h, &pi->line, pi->payload); } static int diff_print_patch_line( @@ -372,10 +351,7 @@ static int diff_print_patch_line( if (S_ISDIR(delta->new_file.mode)) return 0; - if (pi->print_cb(delta, hunk, line, pi->payload)) - return giterr_user_cancel(); - - return 0; + return pi->print_cb(delta, hunk, line, pi->payload); } /* print a git_diff to an output callback */ @@ -421,8 +397,8 @@ int git_diff_print( error = git_diff_foreach( diff, print_file, print_hunk, print_line, &pi); - if (error == GIT_EUSER && pi.error.error_code) - error = giterr_restore(&pi.error); + if (error) /* make sure error message is set */ + giterr_set_callback(error, "git_diff_print"); } git_buf_free(&buf); @@ -450,8 +426,8 @@ int git_patch_print( patch, diff_print_patch_file, diff_print_patch_hunk, diff_print_patch_line, &pi); - if (error && error != GIT_EUSER) - error = giterr_restore(&pi.error); + if (error) /* make sure error message is set */ + giterr_set_callback(error, "git_patch_print"); } git_buf_free(&temp); @@ -484,17 +460,12 @@ int git_patch_to_str( int error; git_buf output = GIT_BUF_INIT; - error = git_patch_print(patch, diff_print_to_buffer_cb, &output); - - /* GIT_EUSER means git_buf_put in print_to_buffer_cb returned -1, - * meaning a memory allocation failure, so just map to -1... - */ - if (error == GIT_EUSER) { - giterr_set_oom(); - error = -1; + if (!(error = git_patch_print(patch, diff_print_to_buffer_cb, &output))) + *string = git_buf_detach(&output); + else { + git_buf_free(&output); + *string = NULL; } - *string = git_buf_detach(&output); - return error; } diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c index c6ca48882..e5984f1c9 100644 --- a/src/diff_xdiff.c +++ b/src/diff_xdiff.c @@ -126,8 +126,9 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) info->hunk.header[info->hunk.header_len] = '\0'; if (output->hunk_cb != NULL && - output->hunk_cb(delta, &info->hunk, output->payload)) - return (output->error = giterr_user_cancel()); + (output->error = output->hunk_cb( + delta, &info->hunk, output->payload))) + return output->error; info->old_lineno = info->hunk.old_start; info->new_lineno = info->hunk.new_start; @@ -150,10 +151,9 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) output->error = diff_update_lines( info, &line, bufs[1].ptr, bufs[1].size); - if (!output->error && - output->data_cb != NULL && - output->data_cb(delta, &info->hunk, &line, output->payload)) - output->error = giterr_user_cancel(); + if (!output->error && output->data_cb != NULL) + output->error = output->data_cb( + delta, &info->hunk, &line, output->payload); } if (len == 3 && !output->error) { @@ -172,10 +172,9 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) output->error = diff_update_lines( info, &line, bufs[2].ptr, bufs[2].size); - if (!output->error && - output->data_cb != NULL && - output->data_cb(delta, &info->hunk, &line, output->payload)) - output->error = giterr_user_cancel(); + if (!output->error && output->data_cb != NULL) + output->error = output->data_cb( + delta, &info->hunk, &line, output->payload); } return output->error; diff --git a/src/fetch.c b/src/fetch.c index 276591821..5bf2b93c1 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -104,7 +104,7 @@ cleanup: int git_fetch_negotiate(git_remote *remote) { git_transport *t = remote->transport; - + if (filter_wants(remote) < 0) { giterr_set(GITERR_NET, "Failed to filter the reference list for wants"); return -1; @@ -128,9 +128,9 @@ int git_fetch_download_pack(git_remote *remote) { git_transport *t = remote->transport; - if(!remote->need_pack) + if (!remote->need_pack) return 0; return t->download_pack(t, remote->repo, &remote->stats, - remote->callbacks.transfer_progress, remote->callbacks.payload); + remote->callbacks.transfer_progress, remote->callbacks.payload); } diff --git a/src/fetchhead.c b/src/fetchhead.c index ee1492211..7c37be4c6 100644 --- a/src/fetchhead.c +++ b/src/fetchhead.c @@ -269,10 +269,10 @@ int git_repository_fetchhead_foreach(git_repository *repo, else ref_name = NULL; - if (cb(ref_name, remote_url, &oid, is_merge, payload) != 0) { - error = giterr_user_cancel(); + error = GITERR_CALLBACK( + cb(ref_name, remote_url, &oid, is_merge, payload) ); + if (error) goto done; - } } if (*buffer) { diff --git a/src/fileops.c b/src/fileops.c index 0418e9e52..98dcd3269 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -404,7 +404,6 @@ typedef struct { size_t baselen; uint32_t flags; int depth; - git_error_state error; } futils__rmdir_data; #define FUTILS_MAX_DEPTH 100 @@ -474,16 +473,14 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path) data->depth++; error = git_path_direach(path, 0, futils__rmdir_recurs_foreach, data); - if (error == GIT_EUSER) - return error; data->depth--; if (error < 0) - goto done; + return error; if (data->depth == 0 && (data->flags & GIT_RMDIR_SKIP_ROOT) != 0) - goto done; + return error; if ((error = p_rmdir(path->ptr)) < 0) { if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) != 0 && @@ -502,8 +499,7 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path) else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0) error = futils__error_cannot_rmdir(path->ptr, "still present"); -done: - return giterr_capture(&data->error, error); + return error; } static int futils__rmdir_empty_parent(void *opaque, git_buf *path) @@ -512,9 +508,9 @@ static int futils__rmdir_empty_parent(void *opaque, git_buf *path) int error = 0; if (git_buf_len(path) <= data->baselen) - return giterr_capture(&data->error, GIT_ITEROVER); + error = GIT_ITEROVER; - if (p_rmdir(git_buf_cstr(path)) < 0) { + else if (p_rmdir(git_buf_cstr(path)) < 0) { int en = errno; if (en == ENOENT || en == ENOTDIR) { @@ -526,7 +522,7 @@ static int futils__rmdir_empty_parent(void *opaque, git_buf *path) } } - return giterr_capture(&data->error, error); + return error; } int git_futils_rmdir_r( @@ -552,10 +548,10 @@ int git_futils_rmdir_r( error = git_path_walk_up( &fullpath, base, futils__rmdir_empty_parent, &data); - if (error == GIT_EUSER) - error = giterr_restore(&data.error); - if (error == GIT_ITEROVER) + if (error == GIT_ITEROVER) { + giterr_clear(); error = 0; + } git_buf_free(&fullpath); @@ -859,7 +855,6 @@ typedef struct { uint32_t flags; uint32_t mkdir_flags; mode_t dirmode; - git_error_state error; } cp_r_info; #define GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT (1u << 10) @@ -899,19 +894,19 @@ static int _cp_r_callback(void *ref, git_buf *from) if ((error = git_buf_joinpath( &info->to, info->to_root, from->ptr + info->from_prefix)) < 0) - goto done; + return error; if (!(error = git_path_lstat(info->to.ptr, &to_st))) exists = true; else if (error != GIT_ENOTFOUND) - goto done; + return error; else { giterr_clear(); error = 0; } if ((error = git_path_lstat(from->ptr, &from_st)) < 0) - goto done; + return error; if (S_ISDIR(from_st.st_mode)) { mode_t oldmode = info->dirmode; @@ -925,16 +920,13 @@ static int _cp_r_callback(void *ref, git_buf *from) error = _cp_r_mkdir(info, from); /* recurse onto target directory */ - if (!error && (!exists || S_ISDIR(to_st.st_mode))) { + if (!error && (!exists || S_ISDIR(to_st.st_mode))) error = git_path_direach(from, 0, _cp_r_callback, info); - if (error == GIT_EUSER) - return error; - } if (oldmode != 0) info->dirmode = oldmode; - goto done; + return error; } if (exists) { @@ -944,8 +936,7 @@ static int _cp_r_callback(void *ref, git_buf *from) if (p_unlink(info->to.ptr) < 0) { giterr_set(GITERR_OS, "Cannot overwrite existing file '%s'", info->to.ptr); - error = -1; - goto done; + return GIT_EEXISTS; } } @@ -958,7 +949,7 @@ static int _cp_r_callback(void *ref, git_buf *from) /* Make container directory on demand if needed */ if ((info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0 && (error = _cp_r_mkdir(info, from)) < 0) - goto done; + return error; /* make symlink or regular file */ if (S_ISLNK(from_st.st_mode)) @@ -972,8 +963,7 @@ static int _cp_r_callback(void *ref, git_buf *from) error = git_futils_cp(from->ptr, info->to.ptr, usemode); } -done: - return giterr_capture(&info->error, error); + return error; } int git_futils_cp_r( @@ -1015,9 +1005,6 @@ int git_futils_cp_r( git_buf_free(&path); git_buf_free(&info.to); - if (error == GIT_EUSER) - error = giterr_restore(&info.error); - return error; } diff --git a/src/ignore.c b/src/ignore.c index aa53d409d..c79fe4871 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -74,20 +74,12 @@ static int parse_ignore_file( #define push_ignore_file(R,IGN,S,B,F) \ git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,parse_ignore_file,(IGN),(S)) -struct ignores_walk_up_data { - git_ignores *ign; - git_error_state error; -}; - -static int push_one_ignore(void *ref, git_buf *path) +static int push_one_ignore(void *payload, git_buf *path) { - struct ignores_walk_up_data *data = ref; + git_ignores *ign = payload; - return giterr_capture( - &data->error, - push_ignore_file( - data->ign->repo, data->ign, &data->ign->ign_path, - path->ptr, GIT_IGNORE_FILE) ); + return push_ignore_file( + ign->repo, ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE); } static int get_internal_ignores(git_attr_file **ign, git_repository *repo) @@ -142,13 +134,8 @@ int git_ignore__for_path( /* load .gitignore up the path */ if (workdir != NULL) { - struct ignores_walk_up_data data = { ignores }; - error = git_path_walk_up( - &ignores->dir, workdir, push_one_ignore, &data); - - if (error == GIT_EUSER) - error = giterr_restore(&data.error); + &ignores->dir, workdir, push_one_ignore, ignores); if (error < 0) goto cleanup; } diff --git a/src/index.c b/src/index.c index d0d2cf187..671bdfa79 100644 --- a/src/index.c +++ b/src/index.c @@ -2036,17 +2036,12 @@ int git_index_read_tree(git_index *index, const git_tree *tree) error = git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, &data); - if (error == GIT_EUSER) { - giterr_set_oom(); - git_vector_free(&entries); - return -1; + if (!error) { + git_vector_sort(&entries); + git_index_clear(index); + git_vector_swap(&entries, &index->entries); } - git_vector_sort(&entries); - - git_index_clear(index); - - git_vector_swap(&entries, &index->entries); git_vector_free(&entries); return error; @@ -2122,7 +2117,7 @@ int git_index_add_all( if (error > 0) /* return > 0 means skip this one */ continue; if (error < 0) { /* return < 0 means abort */ - error = giterr_user_cancel(); + GITERR_CALLBACK(error); break; } } @@ -2210,7 +2205,7 @@ static int index_apply_to_all( continue; } if (error < 0) { /* return < 0 means abort */ - error = giterr_user_cancel(); + giterr_set_callback(error, "git_index_matched_path"); break; } } diff --git a/src/indexer.c b/src/indexer.c index d3253cb57..320845bd9 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -386,10 +386,10 @@ on_error: static int do_progress_callback(git_indexer *idx, git_transfer_progress *stats) { - if (idx->progress_cb && - idx->progress_cb(stats, idx->progress_payload)) - return giterr_user_cancel(); - + if (idx->progress_cb) + return giterr_set_callback( + idx->progress_cb(stats, idx->progress_payload), + "indexer progress"); return 0; } @@ -495,7 +495,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran processed = stats->indexed_objects = 0; stats->total_objects = total_objects; - if ((error = do_progress_callback(idx, stats)) < 0) + if ((error = do_progress_callback(idx, stats)) != 0) return error; } @@ -520,7 +520,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran return 0; } if (error < 0) - return -1; + return error; git_mwindow_close(&w); idx->entry_start = entry_start; @@ -533,7 +533,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran return 0; } if (error < 0) - return -1; + return error; idx->have_delta = 1; } else { @@ -578,7 +578,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran } stats->received_objects++; - if ((error = do_progress_callback(idx, stats)) < 0) + if ((error = do_progress_callback(idx, stats)) != 0) goto on_error; } diff --git a/src/merge.c b/src/merge.c index d5bc6a39c..6f73fc14a 100644 --- a/src/merge.c +++ b/src/merge.c @@ -287,10 +287,8 @@ int git_repository_mergehead_foreach( if ((error = git_oid_fromstr(&oid, line)) < 0) goto cleanup; - if (cb(&oid, payload) != 0) { - error = giterr_user_cancel(); + if ((error = GITERR_CALLBACK( cb(&oid, payload) )) != 0) goto cleanup; - } ++line_num; } diff --git a/src/notes.c b/src/notes.c index 7e8aecbae..e3a3fccf8 100644 --- a/src/notes.c +++ b/src/notes.c @@ -582,12 +582,10 @@ int git_note_foreach( if ((error = git_note_iterator_new(&iter, repo, notes_ref)) < 0) return error; - while (!(error = git_note_next(¬e_id, &annotated_id, iter))) { - if (note_cb(¬e_id, &annotated_id, payload)) { - error = giterr_user_cancel(); - break; - } - } + while (!(error = git_note_next(¬e_id, &annotated_id, iter)) && + !(error = GITERR_CALLBACK( + note_cb(¬e_id, &annotated_id, payload)))) + /* callback for each note */; if (error == GIT_ITEROVER) error = 0; diff --git a/src/odb_loose.c b/src/odb_loose.c index ae772b425..78cd792bd 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -547,8 +547,7 @@ static int locate_object_short_oid( /* Explore directory to find a unique object matching short_oid */ error = git_path_direach( object_location, 0, fn_locate_object_short_oid, &state); - - if (error && error != GIT_EUSER) + if (error < 0 && error != GIT_EAMBIGUOUS) return error; if (!state.found) @@ -696,7 +695,6 @@ struct foreach_state { size_t dir_len; git_odb_foreach_cb cb; void *data; - git_error_state cb_error; }; GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr) @@ -735,19 +733,15 @@ static int foreach_object_dir_cb(void *_state, git_buf *path) if (filename_to_oid(&oid, path->ptr + state->dir_len) < 0) return 0; - if (state->cb(&oid, state->data)) - return giterr_user_cancel(); - - return 0; + return giterr_set_callback( + state->cb(&oid, state->data), "git_odb_foreach"); } static int foreach_cb(void *_state, git_buf *path) { struct foreach_state *state = (struct foreach_state *) _state; - return giterr_capture( - &state->cb_error, - git_path_direach(path, 0, foreach_object_dir_cb, state)); + return git_path_direach(path, 0, foreach_object_dir_cb, state); } static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb cb, void *data) @@ -762,9 +756,10 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb objects_dir = backend->objects_dir; - if (git_buf_sets(&buf, objects_dir) < 0) - return -1; + git_buf_sets(&buf, objects_dir); git_path_to_dir(&buf); + if (git_buf_oom(&buf)) + return -1; memset(&state, 0, sizeof(state)); state.cb = cb; @@ -773,9 +768,6 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb error = git_path_direach(&buf, 0, foreach_cb, &state); - if (error == GIT_EUSER) - error = giterr_restore(&state.cb_error); - git_buf_free(&buf); return error; diff --git a/src/odb_pack.c b/src/odb_pack.c index 2c0319fb6..903b00d26 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -190,15 +190,9 @@ static int packfile_sort__cb(const void *a_, const void *b_) } -struct packfile_load_data { - struct pack_backend *backend; - git_error_state error; -}; - -static int packfile_load__cb(void *_data, git_buf *path) +static int packfile_load__cb(void *data, git_buf *path) { - struct packfile_load_data *data = _data; - struct pack_backend *backend = data->backend; + struct pack_backend *backend = data; struct git_pack_file *pack; const char *path_str = git_buf_cstr(path); size_t i, cmp_len = git_buf_len(path); @@ -227,7 +221,7 @@ static int packfile_load__cb(void *_data, git_buf *path) if (!error) error = git_vector_insert(&backend->packs, pack); - return giterr_capture(&data->error, error); + return error; } @@ -328,32 +322,26 @@ static int pack_entry_find_prefix( * Implement the git_odb_backend API calls * ***********************************************************/ -static int pack_backend__refresh(git_odb_backend *backend) +static int pack_backend__refresh(git_odb_backend *backend_) { - struct packfile_load_data data; int error; struct stat st; git_buf path = GIT_BUF_INIT; + struct pack_backend *backend = (struct pack_backend *)backend_; - memset(&data, 0, sizeof(data)); - data.backend = (struct pack_backend *)backend; - - if (data.backend->pack_folder == NULL) + if (backend->pack_folder == NULL) return 0; - if (p_stat(data.backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode)) + if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode)) return git_odb__error_notfound("failed to refresh packfiles", NULL); - git_buf_sets(&path, data.backend->pack_folder); + git_buf_sets(&path, backend->pack_folder); /* reload all packs */ - error = git_path_direach(&path, 0, packfile_load__cb, &data); - - if (error == GIT_EUSER) - error = giterr_restore(&data.error); + error = git_path_direach(&path, 0, packfile_load__cb, backend); git_buf_free(&path); - git_vector_sort(&data.backend->packs); + git_vector_sort(&backend->packs); return error; } diff --git a/src/pack-objects.c b/src/pack-objects.c index ac0615064..2f0007f4f 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -32,7 +32,6 @@ struct unpacked { struct tree_walk_context { git_packbuilder *pb; git_buf buf; - git_error_state error; }; struct pack_write_context { @@ -206,14 +205,18 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, po = pb->object_list + pb->nr_objects; memset(po, 0x0, sizeof(*po)); - if (git_odb_read_header(&po->size, &po->type, pb->odb, oid) < 0) - return -1; + if ((ret = git_odb_read_header(&po->size, &po->type, pb->odb, oid)) < 0) + return ret; pb->nr_objects++; git_oid_cpy(&po->id, oid); po->hash = name_hash(name); pos = kh_put(oid, pb->object_ix, &po->id, &ret); + if (ret < 0) { + giterr_set_oom(); + return ret; + } assert(ret != 0); kh_value(pb->object_ix, pos) = po; @@ -226,10 +229,9 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, if (elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) { pb->last_progress_report_time = current_time; - if (pb->progress_cb( - GIT_PACKBUILDER_ADDING_OBJECTS, - pb->nr_objects, 0, pb->progress_cb_payload)) - return giterr_user_cancel(); + return GITERR_CALLBACK( pb->progress_cb( + GIT_PACKBUILDER_ADDING_OBJECTS, + pb->nr_objects, 0, pb->progress_cb_payload) ); } } @@ -1303,7 +1305,7 @@ static int cb_tree_walk( error = git_packbuilder_insert( ctx->pb, git_tree_entry_id(entry), git_buf_cstr(&ctx->buf)); - return giterr_capture(&ctx->error, error); + return error; } int git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid *oid) @@ -1331,9 +1333,6 @@ int git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid *oid) !(error = git_packbuilder_insert(pb, oid, NULL))) error = git_tree_walk(tree, GIT_TREEWALK_PRE, cb_tree_walk, &context); - if (error == GIT_EUSER) - error = giterr_restore(&context.error); - git_tree_free(tree); git_buf_free(&context.buf); return error; diff --git a/src/pack.c b/src/pack.c index f69fe85e8..3f2adb2f3 100644 --- a/src/pack.c +++ b/src/pack.c @@ -1082,15 +1082,16 @@ int git_pack_foreach_entry( git_vector_foreach(&offsets, i, current) git_vector_insert(&oids, (void*)¤t[4]); } + git_vector_free(&offsets); - p->oids = (git_oid **)oids.contents; + p->oids = (git_oid **)git_vector_detach(NULL, NULL, &oids); } for (i = 0; i < p->num_objects; i++) - if (cb(p->oids[i], data)) - return giterr_user_cancel(); + if ((error = GITERR_CALLBACK( cb(p->oids[i], data) )) != 0) + break; - return 0; + return error; } static int pack_entry_find_offset( diff --git a/src/path.c b/src/path.c index 8be41c17e..857a2e61c 100644 --- a/src/path.c +++ b/src/path.c @@ -434,11 +434,11 @@ int git_path_walk_up( iter.asize = path->asize; while (scan >= stop) { - if (cb(data, &iter)) - error = giterr_user_cancel(); + error = GITERR_CALLBACK( cb(data, &iter) ); iter.ptr[scan] = oldc; - if (error < 0) + if (error) break; + scan = git_buf_rfind_next(&iter, '/'); if (scan >= 0) { scan++; @@ -874,14 +874,12 @@ int git_path_direach( if ((error = git_buf_put(path, de_path, de_len)) < 0) break; - error = fn(arg, path); + error = GITERR_CALLBACK( fn(arg, path) ); git_buf_truncate(path, wd_len); /* restore path */ - if (error) { - error = giterr_user_cancel(); + if (error) break; - } } closedir(dir); diff --git a/src/path.h b/src/path.h index 3daafd265..f26175d15 100644 --- a/src/path.h +++ b/src/path.h @@ -255,9 +255,10 @@ enum { * @param flags Combination of GIT_PATH_DIR flags. * @param callback Callback for each entry. Passed the `payload` and each * successive path inside the directory as a full path. This may - * safely append text to the pathbuf if needed. + * safely append text to the pathbuf if needed. Return non-zero to + * cancel iteration (and return value will be propagated back). * @param payload Passed to callback as first argument. - * @return 0 on success, GIT_EUSER on non-zero callback, or error code + * @return 0 on success or error code from OS error or from callback */ extern int git_path_direach( git_buf *pathbuf, @@ -288,7 +289,7 @@ extern int git_path_cmp( * original input path. * @param callback Function to invoke on each path. Passed the `payload` * and the buffer containing the current path. The path should not - * be modified in any way. + * be modified in any way. Return non-zero to stop iteration. * @param state Passed to fn as the first ath. */ extern int git_path_walk_up( diff --git a/src/push.c b/src/push.c index a314922c1..428173397 100644 --- a/src/push.c +++ b/src/push.c @@ -659,8 +659,8 @@ int git_push_status_foreach(git_push *push, unsigned int i; git_vector_foreach(&push->status, i, status) { - if (cb(status->ref, status->msg, data) < 0) - return giterr_user_cancel(); + GITERR_CHECK_ERROR( + GITERR_CALLBACK( cb(status->ref, status->msg, data) ) ); } return 0; diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 938e02a78..df7cb9d4d 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -264,14 +264,9 @@ done: return error; } -struct packed_loadloose_data { - refdb_fs_backend *backend; - git_error_state error; -}; - -static int _dirent_loose_load(void *data_, git_buf *full_path) +static int _dirent_loose_load(void *payload, git_buf *full_path) { - struct packed_loadloose_data *data = data_; + refdb_fs_backend *backend = payload; const char *file_path; if (git__suffixcmp(full_path->ptr, ".lock") == 0) @@ -279,12 +274,11 @@ static int _dirent_loose_load(void *data_, git_buf *full_path) if (git_path_isdir(full_path->ptr)) return git_path_direach( - full_path, data->backend->direach_flags, _dirent_loose_load, data); + full_path, backend->direach_flags, _dirent_loose_load, backend); - file_path = full_path->ptr + strlen(data->backend->path); + file_path = full_path->ptr + strlen(backend->path); - return giterr_capture( - &data->error, loose_lookup_to_packfile(data->backend, file_path)); + return loose_lookup_to_packfile(backend, file_path); } /* @@ -297,27 +291,20 @@ static int packed_loadloose(refdb_fs_backend *backend) { int error; git_buf refs_path = GIT_BUF_INIT; - struct packed_loadloose_data data; if (git_buf_joinpath(&refs_path, backend->path, GIT_REFS_DIR) < 0) return -1; - memset(&data, 0, sizeof(data)); - data.backend = backend; - /* * Load all the loose files from disk into the Packfile table. * This will overwrite any old packed entries with their * updated loose versions */ error = git_path_direach( - &refs_path, backend->direach_flags, _dirent_loose_load, &data); + &refs_path, backend->direach_flags, _dirent_loose_load, backend); git_buf_free(&refs_path); - if (error == GIT_EUSER) - error = giterr_restore(&data.error); - return error; } diff --git a/src/refs.c b/src/refs.c index 60ed9ffb1..afb067986 100644 --- a/src/refs.c +++ b/src/refs.c @@ -516,12 +516,9 @@ int git_reference_foreach( if ((error = git_reference_iterator_new(&iter, repo)) < 0) return error; - while ((error = git_reference_next(&ref, iter)) == 0) { - if (callback(ref, payload)) { - error = giterr_user_cancel(); - break; - } - } + while (!(error = git_reference_next(&ref, iter)) && + !(error = GITERR_CALLBACK( callback(ref, payload) ))) + /* callback on each reference */; if (error == GIT_ITEROVER) error = 0; @@ -542,12 +539,9 @@ int git_reference_foreach_name( if ((error = git_reference_iterator_new(&iter, repo)) < 0) return error; - while ((error = git_reference_next_name(&refname, iter)) == 0) { - if (callback(refname, payload)) { - error = giterr_user_cancel(); - break; - } - } + while (!(error = git_reference_next_name(&refname, iter)) && + !(error = GITERR_CALLBACK( callback(refname, payload) ))) + /* callback on each reference name */; if (error == GIT_ITEROVER) error = 0; @@ -569,12 +563,9 @@ int git_reference_foreach_glob( if ((error = git_reference_iterator_glob_new(&iter, repo, glob)) < 0) return error; - while ((error = git_reference_next_name(&refname, iter)) == 0) { - if (callback(refname, payload)) { - error = giterr_user_cancel(); - break; - } - } + while (!(error = git_reference_next_name(&refname, iter)) && + !(error = GITERR_CALLBACK( callback(refname, payload) ))) + /* callback on each matching reference name */; if (error == GIT_ITEROVER) error = 0; @@ -621,7 +612,9 @@ void git_reference_iterator_free(git_reference_iterator *iter) static int cb__reflist_add(const char *ref, void *data) { - return git_vector_insert((git_vector *)data, git__strdup(ref)); + char *name = git__strdup(ref); + GITERR_CHECK_ALLOC(name); + return git_vector_insert((git_vector *)data, name); } int git_reference_list( @@ -644,8 +637,8 @@ int git_reference_list( return -1; } - array->strings = (char **)ref_list.contents; - array->count = ref_list.length; + array->strings = (char **)git_vector_detach(&array->count, NULL, &ref_list); + return 0; } diff --git a/src/remote.c b/src/remote.c index 93d243001..307306d1a 100644 --- a/src/remote.c +++ b/src/remote.c @@ -251,14 +251,12 @@ int git_remote_create_inmemory(git_remote **out, git_repository *repo, const cha struct refspec_cb_data { git_remote *remote; int fetch; - git_error_state error; }; static int refspec_cb(const git_config_entry *entry, void *payload) { struct refspec_cb_data *data = (struct refspec_cb_data *)payload; - return giterr_capture( - &data->error, add_refspec(data->remote, entry->value, data->fetch)); + return add_refspec(data->remote, entry->value, data->fetch); } static int get_optional_config( @@ -316,17 +314,15 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) if ((error = get_check_cert(&remote->check_cert, repo)) < 0) goto cleanup; - if ((git_vector_init(&remote->refs, 32, NULL) < 0) || - (git_vector_init(&remote->refspecs, 2, NULL) < 0) || - (git_vector_init(&remote->active_refspecs, 2, NULL) < 0)) { + if (git_vector_init(&remote->refs, 32, NULL) < 0 || + git_vector_init(&remote->refspecs, 2, NULL) < 0 || + git_vector_init(&remote->active_refspecs, 2, NULL) < 0) { error = -1; goto cleanup; } - if (git_buf_printf(&buf, "remote.%s.url", name) < 0) { - error = -1; + if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0) goto cleanup; - } if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0) goto cleanup; @@ -387,9 +383,6 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) cleanup: git_buf_free(&buf); - if (error == GIT_EUSER) - error = giterr_restore(&data.error); - if (error < 0) git_remote_free(remote); @@ -636,7 +629,7 @@ int git_remote_connect(git_remote *remote, git_direction direction) if (!remote->check_cert) flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT; - if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) < 0) + if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) != 0) goto on_error; remote->transport = t; @@ -788,7 +781,7 @@ int git_remote_download(git_remote *remote) git_vector_free(&refs); if (error < 0) - return -1; + return error; if ((error = git_fetch_negotiate(remote)) < 0) return error; @@ -801,10 +794,10 @@ int git_remote_fetch(git_remote *remote) int error; /* Connect and download everything */ - if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) < 0) + if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) != 0) return error; - if ((error = git_remote_download(remote)) < 0) + if ((error = git_remote_download(remote)) != 0) return error; /* We don't need to be connected anymore */ @@ -1032,7 +1025,6 @@ int git_remote_update_tips(git_remote *remote) int error; size_t i; - if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) return -1; @@ -1112,14 +1104,9 @@ void git_remote_free(git_remote *remote) git__free(remote); } -struct remote_list_data { - git_vector list; - git_error_state error; -}; - static int remote_list_cb(const git_config_entry *entry, void *payload) { - struct remote_list_data *data = payload; + git_vector *list = payload; const char *name = entry->name + strlen("remote."); size_t namelen = strlen(name); char *remote_name; @@ -1130,42 +1117,35 @@ static int remote_list_cb(const git_config_entry *entry, void *payload) remote_name = git__strndup(name, namelen - 4); /* strip ".url" */ else remote_name = git__strndup(name, namelen - 8); /* strip ".pushurl" */ - if (!remote_name) - return giterr_capture(&data->error, -1); + GITERR_CHECK_ALLOC(remote_name); - return giterr_capture( - &data->error, git_vector_insert(&data->list, remote_name)); + return git_vector_insert(list, remote_name); } int git_remote_list(git_strarray *remotes_list, git_repository *repo) { int error; git_config *cfg; - struct remote_list_data data; + git_vector list = GIT_VECTOR_INIT; if ((error = git_repository_config__weakptr(&cfg, repo)) < 0) return error; - memset(&data, 0, sizeof(data)); - if ((error = git_vector_init(&data.list, 4, git__strcmp_cb)) < 0) + if ((error = git_vector_init(&list, 4, git__strcmp_cb)) < 0) return error; error = git_config_foreach_match( - cfg, "^remote\\..*\\.(push)?url$", remote_list_cb, &data); - - /* cb error is converted to GIT_EUSER by git_config_foreach */ - if (error == GIT_EUSER) - error = giterr_restore(&data.error); + cfg, "^remote\\..*\\.(push)?url$", remote_list_cb, &list); if (error < 0) { - git_vector_free_all(&data.list); + git_vector_free_all(&list); return error; } - git_vector_uniq(&data.list, git__free); + git_vector_uniq(&list, git__free); - remotes_list->strings = (char **)data.list.contents; - remotes_list->count = data.list.length; + remotes_list->strings = + (char **)git_vector_detach(&remotes_list->count, NULL, &list); return 0; } @@ -1256,7 +1236,6 @@ struct update_data { git_config *config; const char *old_remote_name; const char *new_remote_name; - git_error_state error; }; static int update_config_entries_cb( @@ -1268,9 +1247,8 @@ static int update_config_entries_cb( if (strcmp(entry->value, data->old_remote_name)) return 0; - return giterr_capture( - &data->error, git_config_set_string( - data->config, entry->name, data->new_remote_name)); + return git_config_set_string( + data->config, entry->name, data->new_remote_name); } static int update_branch_remote_config_entry( @@ -1287,13 +1265,8 @@ static int update_branch_remote_config_entry( data.old_remote_name = old_name; data.new_remote_name = new_name; - error = git_config_foreach_match( + return git_config_foreach_match( data.config, "branch\\..+\\.remote", update_config_entries_cb, &data); - - if (error == GIT_EUSER) - error = giterr_restore(&data.error); - - return error; } static int rename_one_remote_reference( @@ -1357,13 +1330,14 @@ static int rename_fetch_refspecs( git_buf base = GIT_BUF_INIT, var = GIT_BUF_INIT, val = GIT_BUF_INIT; const git_refspec *spec; size_t i; - int error = -1; - - if (git_buf_printf(&base, "+refs/heads/*:refs/remotes/%s/*", remote->name) < 0) - goto cleanup; + int error = 0; if ((error = git_repository_config__weakptr(&config, remote->repo)) < 0) - goto cleanup; + return error; + + if ((error = git_buf_printf( + &base, "+refs/heads/*:refs/remotes/%s/*", remote->name)) < 0) + return error; git_vector_foreach(&remote->refspecs, i, spec) { if (spec->push) @@ -1374,10 +1348,9 @@ static int rename_fetch_refspecs( if (!remote->name || strcmp(git_buf_cstr(&base), spec->string)) { - if (callback(spec->string, payload) < 0) { - error = giterr_user_cancel(); - goto cleanup; - } + error = GITERR_CALLBACK( callback(spec->string, payload) ); + if (error) + break; continue; } @@ -1391,15 +1364,14 @@ static int rename_fetch_refspecs( git_buf_printf(&var, "remote.%s.fetch", new_name) < 0) { error = -1; - goto cleanup; + break; } if ((error = git_config_set_string( config, git_buf_cstr(&var), git_buf_cstr(&val))) < 0) - goto cleanup; + break; } -cleanup: git_buf_free(&base); git_buf_free(&var); git_buf_free(&val); diff --git a/src/repository.c b/src/repository.c index 443744504..94f6603aa 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1608,15 +1608,14 @@ static int at_least_one_cb(const char *refname, void *payload) { GIT_UNUSED(refname); GIT_UNUSED(payload); - - return GIT_EUSER; + return GIT_PASSTHROUGH; } static int repo_contains_no_reference(git_repository *repo) { int error = git_reference_foreach_name(repo, &at_least_one_cb, NULL); - if (error == GIT_EUSER) + if (error == GIT_PASSTHROUGH) return 0; if (!error) diff --git a/src/revwalk.c b/src/revwalk.c index e8c7f23ec..c0a053211 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -169,15 +169,12 @@ static int push_ref(git_revwalk *walk, const char *refname, int hide) struct push_cb_data { git_revwalk *walk; int hide; - git_error_state error; }; static int push_glob_cb(const char *refname, void *data_) { struct push_cb_data *data = (struct push_cb_data *)data_; - - return giterr_capture( - &data->error, push_ref(data->walk, refname, data->hide) ); + return push_ref(data->walk, refname, data->hide); } static int push_glob(git_revwalk *walk, const char *glob, int hide) @@ -204,12 +201,9 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide) data.walk = walk; data.hide = hide; - memset(&data.error, 0, sizeof(data.error)); error = git_reference_foreach_glob( walk->repo, git_buf_cstr(&buf), push_glob_cb, &data); - if (error == GIT_EUSER) - error = giterr_restore(&data.error); git_buf_free(&buf); return error; diff --git a/src/stash.c b/src/stash.c index 06a7b9a33..458a1e175 100644 --- a/src/stash.c +++ b/src/stash.c @@ -440,7 +440,7 @@ static int is_dirty_cb(const char *path, unsigned int status, void *payload) GIT_UNUSED(status); GIT_UNUSED(payload); - return 1; + return GIT_PASSTHROUGH; } static int ensure_there_are_changes_to_stash( @@ -463,7 +463,7 @@ static int ensure_there_are_changes_to_stash( error = git_status_foreach_ext(repo, &opts, is_dirty_cb, NULL); - if (error == GIT_EUSER) + if (error == GIT_PASSTHROUGH) return 0; if (!error) @@ -582,13 +582,13 @@ int git_stash_foreach( for (i = 0; i < max; i++) { entry = git_reflog_entry_byindex(reflog, i); - if (callback(i, - git_reflog_entry_message(entry), - git_reflog_entry_id_new(entry), - payload)) { - error = giterr_user_cancel(); + error = GITERR_CALLBACK( + callback(i, + git_reflog_entry_message(entry), + git_reflog_entry_id_new(entry), + payload) ); + if (error) break; - } } cleanup: diff --git a/src/status.c b/src/status.c index ce571a2d8..d76617a72 100644 --- a/src/status.c +++ b/src/status.c @@ -152,32 +152,25 @@ static git_status_t status_compute( return st; } -struct status_data { - git_status_list *status; - git_error_state err; -}; - static int status_collect( git_diff_delta *head2idx, git_diff_delta *idx2wd, void *payload) { - struct status_data *data = payload; + git_status_list *status = payload; git_status_entry *status_entry; - if (!status_is_included(data->status, head2idx, idx2wd)) + if (!status_is_included(status, head2idx, idx2wd)) return 0; status_entry = git__malloc(sizeof(git_status_entry)); - if (!status_entry) - return giterr_capture(&data->err, -1); + GITERR_CHECK_ALLOC(status_entry); - status_entry->status = status_compute(data->status, head2idx, idx2wd); + status_entry->status = status_compute(status, head2idx, idx2wd); status_entry->head_to_index = head2idx; status_entry->index_to_workdir = idx2wd; - return giterr_capture( - &data->err, git_vector_insert(&data->status->paired, status_entry)); + return git_vector_insert(&status->paired, status_entry); } GIT_INLINE(int) status_entry_cmp_base( @@ -321,18 +314,10 @@ int git_status_list_new( goto done; } - { - struct status_data data = { 0 }; - data.status = status; - - error = git_diff__paired_foreach( - status->head2idx, status->idx2wd, status_collect, &data); - - if (error == GIT_EUSER) - error = giterr_restore(&data.err); - if (error < 0) - goto done; - } + error = git_diff__paired_foreach( + status->head2idx, status->idx2wd, status_collect, status); + if (error < 0) + goto done; if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY) git_vector_set_cmp(&status->paired, status_entry_cmp); @@ -407,10 +392,9 @@ int git_status_foreach_ext( status_entry->head_to_index->old_file.path : status_entry->index_to_workdir->old_file.path; - if (cb(path, status_entry->status, payload) != 0) { - error = giterr_user_cancel(); + error = GITERR_CALLBACK( cb(path, status_entry->status, payload) ); + if (error) break; - } } git_status_list_free(status); diff --git a/src/submodule.c b/src/submodule.c index 15c87c0b4..e9d534ae8 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -71,11 +71,6 @@ __KHASH_IMPL( str, static kh_inline, const char *, void *, 1, str_hash_no_trailing_slash, str_equal_no_trailing_slash); -struct submodule_callback_payload { - git_repository *repo; - git_error_state error; -}; - static int load_submodule_config(git_repository *repo); static git_config_backend *open_gitmodules(git_repository *, bool, const git_oid *); static int lookup_head_remote(git_buf *url, git_repository *repo); @@ -173,10 +168,8 @@ int git_submodule_foreach( break; } - if (callback(sm, sm->name, payload)) { - error = giterr_user_cancel(); + if ((error = GITERR_CALLBACK(callback(sm, sm->name, payload))) != 0) break; - } }); git_vector_free(&seen); @@ -825,7 +818,6 @@ int git_submodule_reload(git_submodule *submodule) { int error = 0; git_config_backend *mods; - struct submodule_callback_payload p; assert(submodule); @@ -838,9 +830,6 @@ int git_submodule_reload(git_submodule *submodule) return error; /* refresh config data */ - memset(&p, 0, sizeof(p)); - p.repo = submodule->repo; - mods = open_gitmodules(submodule->repo, false, NULL); if (mods != NULL) { git_buf path = GIT_BUF_INIT; @@ -851,13 +840,9 @@ int git_submodule_reload(git_submodule *submodule) if (git_buf_oom(&path)) error = -1; - else { + else error = git_config_file_foreach_match( - mods, path.ptr, submodule_load_from_config, &p); - - if (error == GIT_EUSER) - error = giterr_restore(&p.error); - } + mods, path.ptr, submodule_load_from_config, submodule->repo); git_buf_free(&path); git_config_file_free(mods); @@ -867,15 +852,11 @@ int git_submodule_reload(git_submodule *submodule) } /* refresh wd data */ - submodule->flags = submodule->flags & ~(GIT_SUBMODULE_STATUS_IN_WD | GIT_SUBMODULE_STATUS__WD_OID_VALID); - error = submodule_load_from_wd_lite(submodule, submodule->path, &p); - if (error) - error = giterr_restore(&p.error); - - return error; + return submodule_load_from_wd_lite( + submodule, submodule->path, submodule->repo); } static void submodule_copy_oid_maybe( @@ -1100,8 +1081,8 @@ int git_submodule_parse_update(git_submodule_update_t *out, const char *value) static int submodule_load_from_config( const git_config_entry *entry, void *payload) { - struct submodule_callback_payload *p = payload; - git_strmap *smcfg = p->repo->submodules; + git_repository *repo = payload; + git_strmap *smcfg = repo->submodules; const char *namestart, *property, *alternate = NULL; const char *key = entry->name, *value = entry->value, *path; git_buf name = GIT_BUF_INIT; @@ -1121,7 +1102,7 @@ static int submodule_load_from_config( path = !strcasecmp(property, "path") ? value : NULL; if ((error = git_buf_set(&name, namestart, property - namestart - 1)) < 0 || - (error = submodule_get(&sm, p->repo, name.ptr, path)) < 0) + (error = submodule_get(&sm, repo, name.ptr, path)) < 0) goto done; sm->flags |= GIT_SUBMODULE_STATUS_IN_CONFIG; @@ -1197,22 +1178,21 @@ static int submodule_load_from_config( done: git_buf_free(&name); - return giterr_capture(&p->error, error); + return error; } static int submodule_load_from_wd_lite( git_submodule *sm, const char *name, void *payload) { - struct submodule_callback_payload *p = payload; git_buf path = GIT_BUF_INIT; - GIT_UNUSED(name); + GIT_UNUSED(name); GIT_UNUSED(payload); if (git_repository_is_bare(sm->repo)) return 0; if (git_buf_joinpath(&path, git_repository_workdir(sm->repo), sm->path) < 0) - return giterr_capture(&p->error, -1); + return -1; if (git_path_isdir(path.ptr)) sm->flags |= GIT_SUBMODULE_STATUS__WD_SCANNED; @@ -1355,14 +1335,11 @@ static int load_submodule_config(git_repository *repo) int error; git_oid gitmodules_oid; git_config_backend *mods = NULL; - struct submodule_callback_payload p; if (repo->submodules) return 0; memset(&gitmodules_oid, 0, sizeof(gitmodules_oid)); - memset(&p, 0, sizeof(p)); - p.repo = repo; /* Submodule data is kept in a hashtable keyed by both name and path. * These are usually the same, but that is not guaranteed. @@ -1386,21 +1363,18 @@ static int load_submodule_config(git_repository *repo) if ((mods = open_gitmodules(repo, false, &gitmodules_oid)) != NULL && (error = git_config_file_foreach( - mods, submodule_load_from_config, &p)) < 0) + mods, submodule_load_from_config, repo)) < 0) goto cleanup; /* shallow scan submodules in work tree */ if (!git_repository_is_bare(repo)) - error = git_submodule_foreach(repo, submodule_load_from_wd_lite, &p); + error = git_submodule_foreach(repo, submodule_load_from_wd_lite, NULL); cleanup: if (mods != NULL) git_config_file_free(mods); - if (error == GIT_EUSER) - error = giterr_restore(&p.error); - if (error) git_submodule_config_free(repo); diff --git a/src/tag.c b/src/tag.c index 5d4e45e5d..adf2819d7 100644 --- a/src/tag.c +++ b/src/tag.c @@ -414,7 +414,6 @@ typedef struct { git_repository *repo; git_tag_foreach_cb cb; void *cb_data; - git_error_state error; } tag_cb_data; static int tags_cb(const char *ref, void *data) @@ -427,16 +426,15 @@ static int tags_cb(const char *ref, void *data) return 0; /* no tag */ if (!(error = git_reference_name_to_id(&oid, d->repo, ref))) { - if (d->cb(ref, &oid, d->cb_data)) - error = giterr_user_cancel(); + error = d->cb(ref, &oid, d->cb_data); + giterr_set_callback(error, "git_tag_foreach"); } - return giterr_capture(&d->error, error); + return error; } int git_tag_foreach(git_repository *repo, git_tag_foreach_cb cb, void *cb_data) { - int error; tag_cb_data data; assert(repo && cb); @@ -444,14 +442,8 @@ int git_tag_foreach(git_repository *repo, git_tag_foreach_cb cb, void *cb_data) data.cb = cb; data.cb_data = cb_data; data.repo = repo; - memset(&data.error, 0, sizeof(data.error)); - error = git_reference_foreach_name(repo, &tags_cb, &data); - - if (error == GIT_EUSER) - error = giterr_restore(&data.error); - - return error; + return git_reference_foreach_name(repo, &tags_cb, &data); } typedef struct { @@ -470,8 +462,8 @@ static int tag_list_cb(const char *tag_name, git_oid *oid, void *data) p_fnmatch(filter->pattern, tag_name + GIT_REFS_TAGS_DIR_LEN, 0) == 0) { char *matched = git__strdup(tag_name + GIT_REFS_TAGS_DIR_LEN); - if (!matched) - return -1; + GITERR_CHECK_ALLOC(matched); + return git_vector_insert(filter->taglist, matched); } @@ -494,19 +486,12 @@ int git_tag_list_match(git_strarray *tag_names, const char *pattern, git_reposit error = git_tag_foreach(repo, &tag_list_cb, (void *)&filter); - /* the only case where callback will return an error is oom */ - if (error == GIT_EUSER) { - giterr_set_oom(); - error = -1; - } - - if (error < 0) { + if (error < 0) git_vector_free(&taglist); - return error; - } - tag_names->strings = (char **)taglist.contents; - tag_names->count = taglist.length; + tag_names->strings = + (char **)git_vector_detach(&tag_names->count, NULL, &taglist); + return 0; } diff --git a/src/transports/http.c b/src/transports/http.c index ace0d97d0..0e1bbf60d 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -382,9 +382,6 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len) static void clear_parser_state(http_subtransport *t) { - unsigned i; - char *entry; - http_parser_init(&t->parser, HTTP_RESPONSE); gitno_buffer_setup(&t->socket, &t->parse_buffer, @@ -407,10 +404,7 @@ static void clear_parser_state(http_subtransport *t) git__free(t->location); t->location = NULL; - git_vector_foreach(&t->www_authenticate, i, entry) - git__free(entry); - - git_vector_free(&t->www_authenticate); + git_vector_free_all(&t->www_authenticate); } static int write_chunk(gitno_socket *socket, const char *buffer, size_t len) diff --git a/src/transports/local.c b/src/transports/local.c index f09e797ce..4635d5dd3 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -43,43 +43,43 @@ typedef struct { static int add_ref(transport_local *t, const char *name) { const char peeled[] = "^{}"; + git_oid head_oid; git_remote_head *head; git_object *obj = NULL, *target = NULL; git_buf buf = GIT_BUF_INIT; int error; + error = git_reference_name_to_id(&head_oid, t->repo, name); + if (error < 0) { + if (!strcmp(name, GIT_HEAD_FILE) && error == GIT_ENOTFOUND) { + /* This is actually okay. Empty repos often have a HEAD that + * points to a nonexistent "refs/heads/master". */ + giterr_clear(); + return 0; + } + return error; + } + head = git__calloc(1, sizeof(git_remote_head)); GITERR_CHECK_ALLOC(head); head->name = git__strdup(name); GITERR_CHECK_ALLOC(head->name); - error = git_reference_name_to_id(&head->oid, t->repo, name); - if (error < 0) { - git__free(head->name); - git__free(head); - if (!strcmp(name, GIT_HEAD_FILE) && error == GIT_ENOTFOUND) { - /* This is actually okay. Empty repos often have a HEAD that points to - * a nonexistent "refs/heads/master". */ - giterr_clear(); - return 0; - } - return error; - } + git_oid_cpy(&head->oid, &head_oid); - if (git_vector_insert(&t->refs, head) < 0) - { + if ((error = git_vector_insert(&t->refs, head)) < 0) { git__free(head->name); git__free(head); - return -1; + return error; } /* If it's not a tag, we don't need to try to peel it */ if (git__prefixcmp(name, GIT_REFS_TAGS_DIR)) return 0; - if (git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJ_ANY) < 0) - return -1; + if ((error = git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJ_ANY)) < 0) + return error; head = NULL; @@ -94,27 +94,24 @@ static int add_ref(transport_local *t, const char *name) /* And if it's a tag, peel it, and add it to the list */ head = git__calloc(1, sizeof(git_remote_head)); GITERR_CHECK_ALLOC(head); + if (git_buf_join(&buf, 0, name, peeled) < 0) return -1; - head->name = git_buf_detach(&buf); - if (git_tag_peel(&target, (git_tag *) obj) < 0) - goto on_error; + if (!(error = git_tag_peel(&target, (git_tag *)obj))) { + git_oid_cpy(&head->oid, git_object_id(target)); + + if ((error = git_vector_insert(&t->refs, head)) < 0) { + git__free(head->name); + git__free(head); + } + } - git_oid_cpy(&head->oid, git_object_id(target)); git_object_free(obj); git_object_free(target); - if (git_vector_insert(&t->refs, head) < 0) - return -1; - - return 0; - -on_error: - git_object_free(obj); - git_object_free(target); - return -1; + return error; } static int store_refs(transport_local *t) @@ -222,7 +219,7 @@ static int local_ls(const git_remote_head ***out, size_t *size, git_transport *t return -1; } - *out = (const git_remote_head **) t->refs.contents; + *out = (const git_remote_head **)t->refs.contents; *size = t->refs.length; return 0; @@ -529,7 +526,7 @@ static int local_download_pack( } } - if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0) + if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0) goto cleanup; /* Write the data to the ODB */ @@ -540,7 +537,7 @@ static int local_download_pack( data.progress_payload = progress_payload; data.writepack = writepack; - if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) < 0) + if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) != 0) goto cleanup; } error = writepack->commit(writepack, stats); diff --git a/src/transports/smart.c b/src/transports/smart.c index e298f3510..69eaf9b78 100644 --- a/src/transports/smart.c +++ b/src/transports/smart.c @@ -23,12 +23,13 @@ static int git_smart__recv_cb(gitno_buffer *buf) buf->offset += bytes_read; - if (t->packetsize_cb && !t->cancelled.val) - if (t->packetsize_cb(bytes_read, t->packetsize_payload)) { + if (t->packetsize_cb && !t->cancelled.val) { + error = t->packetsize_cb(bytes_read, t->packetsize_payload); + if (error) { git_atomic_set(&t->cancelled, 1); - - return giterr_user_cancel(); + return GIT_EUSER; } + } return (int)(buf->offset - old_len); } @@ -341,7 +342,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) t->parent.is_connected = git_smart__is_connected; t->parent.read_flags = git_smart__read_flags; t->parent.cancel = git_smart__cancel; - + t->owner = owner; t->rpc = definition->rpc; @@ -358,7 +359,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) if (definition->callback(&t->wrapped, &t->parent) < 0) { git__free(t); return -1; - } + } *out = (git_transport *) t; return 0; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index a4046ee43..dd9b5e0ed 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -45,7 +45,7 @@ int git_smart__store_refs(transport_smart *t, int flushes) error = GIT_EBUFS; if (error < 0 && error != GIT_EBUFS) - return -1; + return error; if (error == GIT_EBUFS) { if ((recvd = gitno_recv(buf)) < 0) @@ -209,12 +209,13 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo) git_strarray refs; unsigned int i; git_reference *ref; + int error; - if (git_reference_list(&refs, repo) < 0) - return -1; + if ((error = git_reference_list(&refs, repo)) < 0) + return error; - if (git_revwalk_new(&walk, repo) < 0) - return -1; + if ((error = git_revwalk_new(&walk, repo)) < 0) + return error; git_revwalk_sorting(walk, GIT_SORT_TIME); @@ -223,13 +224,13 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo) if (!git__prefixcmp(refs.strings[i], GIT_REFS_TAGS_DIR)) continue; - if (git_reference_lookup(&ref, repo, refs.strings[i]) < 0) + if ((error = git_reference_lookup(&ref, repo, refs.strings[i])) < 0) goto on_error; if (git_reference_type(ref) == GIT_REF_SYMBOLIC) continue; - if (git_revwalk_push(walk, git_reference_target(ref)) < 0) + if ((error = git_revwalk_push(walk, git_reference_target(ref))) < 0) goto on_error; git_reference_free(ref); @@ -242,7 +243,7 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo) on_error: git_reference_free(ref); git_strarray_free(&refs); - return -1; + return error; } static int wait_while_ack(gitno_buffer *buf) @@ -503,7 +504,7 @@ int git_smart__download_pack( } if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 || - ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0)) + ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0)) goto done; /* @@ -539,11 +540,9 @@ int git_smart__download_pack( if (pkt->type == GIT_PKT_PROGRESS) { if (t->progress_cb) { git_pkt_progress *p = (git_pkt_progress *) pkt; - if (t->progress_cb(p->data, p->len, t->message_cb_payload)) { - giterr_clear(); - error = GIT_EUSER; + error = t->progress_cb(p->data, p->len, t->message_cb_payload); + if (error) goto done; - } } git__free(pkt); } else if (pkt->type == GIT_PKT_DATA) { @@ -551,7 +550,7 @@ int git_smart__download_pack( error = writepack->append(writepack, p->data, p->len, stats); git__free(pkt); - if (error < 0) + if (error != 0) goto done; } else if (pkt->type == GIT_PKT_FLUSH) { /* A flush indicates the end of the packfile */ @@ -564,17 +563,15 @@ int git_smart__download_pack( * Trailing execution of progress_cb, if necessary... * Only the callback through the npp datastructure currently * updates the last_fired_bytes value. It is possible that - * progress has already been reported with the correct + * progress has already been reported with the correct * "received_bytes" value, but until (if?) this is unified * then we will report progress again to be sure that the * correct last received_bytes value is reported. */ if (npp.callback && npp.stats->received_bytes > npp.last_fired_bytes) { - if (npp.callback(npp.stats, npp.payload) < 0) { - giterr_clear(); - error = GIT_EUSER; + error = npp.callback(npp.stats, npp.payload); + if (error != 0) goto done; - } } error = writepack->commit(writepack, stats); diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 673cd0faf..e47e19cca 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -667,9 +667,11 @@ replay: if (allowed_types && (!t->cred || 0 == (t->cred->credtype & allowed_types))) { - if (t->owner->cred_acquire_cb(&t->cred, t->owner->url, t->connection_data.user, allowed_types, - t->owner->cred_acquire_payload) < 0) - return GIT_EUSER; + int error = t->owner->cred_acquire_cb( + &t->cred, t->owner->url, t->connection_data.user, + allowed_types, t->owner->cred_acquire_payload); + if (error < 0) + return error; assert(t->cred); diff --git a/src/tree.c b/src/tree.c index 8ded007eb..5f35ac3a8 100644 --- a/src/tree.c +++ b/src/tree.c @@ -883,9 +883,8 @@ static int tree_walk( git_vector_foreach(&tree->entries, i, entry) { if (preorder) { - error = callback(path->ptr, entry, payload); - if (error < 0) - return giterr_user_cancel(); + if ((error = callback(path->ptr, entry, payload)) < 0) + return giterr_set_callback(error, "git_tree_walk"); if (error > 0) { error = 0; continue; @@ -896,8 +895,8 @@ static int tree_walk( git_tree *subtree; size_t path_len = git_buf_len(path); - if ((error = git_tree_lookup( - &subtree, tree->object.repo, &entry->oid)) < 0) + error = git_tree_lookup(&subtree, tree->object.repo, &entry->oid); + if (error < 0) break; /* append the next entry to the path */ @@ -905,19 +904,22 @@ static int tree_walk( git_buf_putc(path, '/'); if (git_buf_oom(path)) - return -1; + error = -1; + else + error = tree_walk(subtree, callback, path, payload, preorder); - error = tree_walk(subtree, callback, path, payload, preorder); git_tree_free(subtree); - if (error != 0) break; git_buf_truncate(path, path_len); } - if (!preorder && callback(path->ptr, entry, payload) < 0) - return giterr_user_cancel(); + if (!preorder) { + if ((error = callback(path->ptr, entry, payload)) < 0) + return giterr_set_callback(error, "git_tree_walk"); + error = 0; + } } return error; diff --git a/src/vector.c b/src/vector.c index 9e217b831..b1ea89606 100644 --- a/src/vector.c +++ b/src/vector.c @@ -104,6 +104,22 @@ int git_vector_init(git_vector *v, size_t initial_size, git_vector_cmp cmp) return resize_vector(v, max(initial_size, MIN_ALLOCSIZE)); } +void **git_vector_detach(size_t *size, size_t *asize, git_vector *v) +{ + void **data = v->contents; + + if (size) + *size = v->length; + if (asize) + *asize = v->_alloc_size; + + v->_alloc_size = 0; + v->length = 0; + v->contents = NULL; + + return data; +} + int git_vector_insert(git_vector *v, void *element) { assert(v); diff --git a/src/vector.h b/src/vector.h index c6d3e9d55..defe22466 100644 --- a/src/vector.h +++ b/src/vector.h @@ -28,6 +28,8 @@ void git_vector_clear(git_vector *v); int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp); void git_vector_swap(git_vector *a, git_vector *b); +void **git_vector_detach(size_t *size, size_t *asize, git_vector *v); + void git_vector_sort(git_vector *v); /** Linear search for matching entry using internal comparison function */ diff --git a/tests/attr/repo.c b/tests/attr/repo.c index ef2ad5ce9..f9ba585fb 100644 --- a/tests/attr/repo.c +++ b/tests/attr/repo.c @@ -129,6 +129,8 @@ static int count_attrs( return 0; } +#define CANCEL_VALUE 12345 + static int cancel_iteration( const char *name, const char *value, @@ -140,7 +142,7 @@ static int cancel_iteration( *((int *)payload) -= 1; if (*((int *)payload) < 0) - return -1; + return CANCEL_VALUE; return 0; } @@ -166,7 +168,7 @@ void test_attr_repo__foreach(void) count = 2; cl_assert_equal_i( - GIT_EUSER, git_attr_foreach( + CANCEL_VALUE, git_attr_foreach( g_repo, 0, "sub/subdir_test1", &cancel_iteration, &count) ); } diff --git a/tests/config/read.c b/tests/config/read.c index abc088d59..25672729f 100644 --- a/tests/config/read.c +++ b/tests/config/read.c @@ -247,7 +247,7 @@ void test_config_read__foreach(void) count = 3; cl_git_fail(ret = git_config_foreach(cfg, cfg_callback_countdown, &count)); - cl_assert_equal_i(GIT_EUSER, ret); + cl_assert_equal_i(-100, ret); git_config_free(cfg); } diff --git a/tests/config/rename.c b/tests/config/rename.c index 29ade7b00..db07c798f 100644 --- a/tests/config/rename.c +++ b/tests/config/rename.c @@ -44,7 +44,6 @@ void test_config_rename__can_rename(void) void test_config_rename__prevent_overwrite(void) { const git_config_entry *ce; - const git_error *err; cl_git_pass(git_config_set_string( g_config, "branch.local-track.remote", "yellow")); @@ -60,8 +59,12 @@ void test_config_rename__prevent_overwrite(void) &ce, g_config, "branch.local-track.remote")); cl_assert_equal_s(".", ce->value); -// cl_assert((err = giterr_last()) != NULL); -// cl_assert(err->message != NULL); + /* so, we don't currently prevent overwrite... */ + /* { + const git_error *err; + cl_assert((err = giterr_last()) != NULL); + cl_assert(err->message != NULL); + } */ } static void assert_invalid_config_section_name( diff --git a/tests/core/path.c b/tests/core/path.c index 3858e30dd..471491b87 100644 --- a/tests/core/path.c +++ b/tests/core/path.c @@ -354,13 +354,15 @@ typedef struct { char **expect; } check_walkup_info; +#define CANCEL_VALUE 1234 + static int check_one_walkup_step(void *ref, git_buf *path) { check_walkup_info *info = (check_walkup_info *)ref; if (!info->cancel_after) { cl_assert_equal_s(info->expect[info->expect_idx], "[CANCEL]"); - return -1; + return CANCEL_VALUE; } info->cancel_after--; @@ -435,7 +437,7 @@ void test_core_path__11a_walkup_cancel(void) info.expect_idx = i; cl_assert_equal_i( - GIT_EUSER, + CANCEL_VALUE, git_path_walk_up(&p, root[j], check_one_walkup_step, &info) ); diff --git a/tests/diff/index.c b/tests/diff/index.c index 8f4567137..21afe8da2 100644 --- a/tests/diff/index.c +++ b/tests/diff/index.c @@ -128,9 +128,7 @@ void test_diff_index__1(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); cl_assert_equal_i( - GIT_EUSER, - git_diff_foreach(diff, diff_stop_after_2_files, NULL, NULL, &exp) - ); + 1, git_diff_foreach(diff, diff_stop_after_2_files, NULL, NULL, &exp) ); cl_assert_equal_i(2, exp.files); diff --git a/tests/diff/notify.c b/tests/diff/notify.c index cc33cb71c..f6accd004 100644 --- a/tests/diff/notify.c +++ b/tests/diff/notify.c @@ -20,7 +20,7 @@ static int assert_called_notifications( { bool found = false; notify_expected *exp = (notify_expected*)payload; - notify_expected *e;; + notify_expected *e; GIT_UNUSED(diff_so_far); diff --git a/tests/diff/rename.c b/tests/diff/rename.c index ca6d076d6..93e69f479 100644 --- a/tests/diff/rename.c +++ b/tests/diff/rename.c @@ -111,6 +111,28 @@ void test_diff_rename__match_oid(void) git_diff_free(diff); + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + /* git diff --find-copies-harder -M100 -B100 \ + * 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \ + * 2bc7f351d20b53f1c72c16c4b036e491c478c49a + */ + opts.flags = GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED | + GIT_DIFF_FIND_EXACT_MATCH_ONLY; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(3, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + git_tree_free(old_tree); git_tree_free(new_tree); } diff --git a/tests/notes/notes.c b/tests/notes/notes.c index 82dcaf8ca..c2579a2c4 100644 --- a/tests/notes/notes.c +++ b/tests/notes/notes.c @@ -129,7 +129,7 @@ void test_notes_notes__can_cancel_foreach(void) create_note(¬e_oid4, "refs/notes/i-can-see-dead-notes", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "I decorate 9fd7 and 4a20\n"); cl_assert_equal_i( - GIT_EUSER, + 1, git_note_foreach(_repo, "refs/notes/i-can-see-dead-notes", note_cancel_cb, &retrieved_notes)); } diff --git a/tests/object/tree/walk.c b/tests/object/tree/walk.c index 1207e864c..f8005e579 100644 --- a/tests/object/tree/walk.c +++ b/tests/object/tree/walk.c @@ -59,7 +59,7 @@ static int treewalk_stop_cb( (*count) += 1; - return (*count == 2) ? -1 : 0; + return (*count == 2) ? -123 : 0; } static int treewalk_stop_immediately_cb( @@ -83,20 +83,20 @@ void test_object_tree_walk__1(void) ct = 0; cl_assert_equal_i( - GIT_EUSER, git_tree_walk(tree, GIT_TREEWALK_PRE, treewalk_stop_cb, &ct)); + -123, git_tree_walk(tree, GIT_TREEWALK_PRE, treewalk_stop_cb, &ct)); cl_assert_equal_i(2, ct); ct = 0; cl_assert_equal_i( - GIT_EUSER, git_tree_walk(tree, GIT_TREEWALK_POST, treewalk_stop_cb, &ct)); + -123, git_tree_walk(tree, GIT_TREEWALK_POST, treewalk_stop_cb, &ct)); cl_assert_equal_i(2, ct); cl_assert_equal_i( - GIT_EUSER, git_tree_walk( + -100, git_tree_walk( tree, GIT_TREEWALK_PRE, treewalk_stop_immediately_cb, NULL)); cl_assert_equal_i( - GIT_EUSER, git_tree_walk( + -100, git_tree_walk( tree, GIT_TREEWALK_POST, treewalk_stop_immediately_cb, NULL)); git_tree_free(tree); @@ -152,7 +152,7 @@ void test_object_tree_walk__2(void) memset(&data, 0, sizeof(data)); data.stop = "3.txt"; - cl_assert_equal_i(GIT_EUSER, git_tree_walk( + cl_assert_equal_i(-1, git_tree_walk( tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); cl_assert_equal_i(3, data.files); cl_assert_equal_i(2, data.dirs); @@ -168,7 +168,7 @@ void test_object_tree_walk__2(void) memset(&data, 0, sizeof(data)); data.stop = "new.txt"; - cl_assert_equal_i(GIT_EUSER, git_tree_walk( + cl_assert_equal_i(-1, git_tree_walk( tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); cl_assert_equal_i(7, data.files); cl_assert_equal_i(4, data.dirs); diff --git a/tests/odb/foreach.c b/tests/odb/foreach.c index ebb8866f7..256ae9cd7 100644 --- a/tests/odb/foreach.c +++ b/tests/odb/foreach.c @@ -5,7 +5,6 @@ static git_odb *_odb; static git_repository *_repo; -static int nobj; void test_odb_foreach__cleanup(void) { @@ -18,10 +17,10 @@ void test_odb_foreach__cleanup(void) static int foreach_cb(const git_oid *oid, void *data) { - GIT_UNUSED(data); - GIT_UNUSED(oid); + int *nobj = data; + (*nobj)++; - nobj++; + GIT_UNUSED(oid); return 0; } @@ -38,43 +37,46 @@ static int foreach_cb(const git_oid *oid, void *data) */ void test_odb_foreach__foreach(void) { + int nobj = 0; + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); git_repository_odb(&_odb, _repo); - cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL)); + cl_git_pass(git_odb_foreach(_odb, foreach_cb, &nobj)); cl_assert_equal_i(47 + 1640, nobj); /* count + in-pack */ } void test_odb_foreach__one_pack(void) { git_odb_backend *backend = NULL; + int nobj = 0; cl_git_pass(git_odb_new(&_odb)); cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx"))); cl_git_pass(git_odb_add_backend(_odb, backend, 1)); _repo = NULL; - nobj = 0; - cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL)); + cl_git_pass(git_odb_foreach(_odb, foreach_cb, &nobj)); cl_assert(nobj == 1628); } static int foreach_stop_cb(const git_oid *oid, void *data) { - GIT_UNUSED(data); + int *nobj = data; + (*nobj)++; + GIT_UNUSED(oid); - nobj++; - - return (nobj == 1000); + return (*nobj == 1000) ? -321 : 0; } void test_odb_foreach__interrupt_foreach(void) { - nobj = 0; + int nobj = 0; + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); git_repository_odb(&_odb, _repo); - cl_assert_equal_i(GIT_EUSER, git_odb_foreach(_odb, foreach_stop_cb, NULL)); + cl_assert_equal_i(-321, git_odb_foreach(_odb, foreach_stop_cb, &nobj)); cl_assert(nobj == 1000); } diff --git a/tests/online/clone.c b/tests/online/clone.c index efc76d958..be4421ae5 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -273,7 +273,7 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload) GIT_UNUSED(payload); if (stats->received_objects > (stats->total_objects/2)) - return 1; + return 4321; return 0; } @@ -281,7 +281,8 @@ void test_online_clone__can_cancel(void) { g_options.remote_callbacks.transfer_progress = cancel_at_half; - cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER); + cl_git_fail_with( + git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), 4321); } diff --git a/tests/online/fetch.c b/tests/online/fetch.c index 5153a7ae0..7e9dfdbbe 100644 --- a/tests/online/fetch.c +++ b/tests/online/fetch.c @@ -129,7 +129,7 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload) GIT_UNUSED(payload); if (stats->received_objects > (stats->total_objects/2)) - return -1; + return -4321; return 0; } @@ -147,7 +147,7 @@ void test_online_fetch__can_cancel(void) git_remote_set_callbacks(remote, &callbacks); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_fail_with(git_remote_download(remote), GIT_EUSER); + cl_git_fail_with(git_remote_download(remote), -4321); git_remote_disconnect(remote); git_remote_free(remote); } diff --git a/tests/refs/foreachglob.c b/tests/refs/foreachglob.c index 2c458082f..c0f6ce763 100644 --- a/tests/refs/foreachglob.c +++ b/tests/refs/foreachglob.c @@ -81,14 +81,14 @@ static int interrupt_cb(const char *reference_name, void *payload) (*count)++; - return (*count == 11); + return (*count == 11) ? -1000 : 0; } void test_refs_foreachglob__can_cancel(void) { int count = 0; - cl_assert_equal_i(GIT_EUSER, git_reference_foreach_glob( + cl_assert_equal_i(-1000, git_reference_foreach_glob( repo, "*", interrupt_cb, &count) ); cl_assert_equal_i(11, count); diff --git a/tests/status/worktree.c b/tests/status/worktree.c index 34be6d34c..fd57fcc1e 100644 --- a/tests/status/worktree.c +++ b/tests/status/worktree.c @@ -552,7 +552,7 @@ static int cb_status__interrupt(const char *p, unsigned int s, void *payload) (*count)++; - return (*count == 8); + return (*count == 8) ? -111 : 0; } void test_status_worktree__interruptable_foreach(void) @@ -561,7 +561,7 @@ void test_status_worktree__interruptable_foreach(void) git_repository *repo = cl_git_sandbox_init("status"); cl_assert_equal_i( - GIT_EUSER, git_status_foreach(repo, cb_status__interrupt, &count) + -111, git_status_foreach(repo, cb_status__interrupt, &count) ); cl_assert_equal_i(8, count);