Commit dab89f9b by Russell Belfer

Further EUSER and error propagation fixes

This continues auditing all the places where GIT_EUSER is being
returned and making sure to clear any existing error using the
new giterr_user_cancel helper.  As a result, places that relied
on intercepting GIT_EUSER but having the old error preserved also
needed to be cleaned up to correctly stash and then retrieve the
actual error.

Additionally, as I encountered places where error codes were not
being propagated correctly, I tried to fix them up.  A number of
those fixes are included in the this commit as well.
parent 96869a4e
......@@ -480,6 +480,7 @@ 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(
......@@ -523,7 +524,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 error;
return giterr_capture(&info->error, error);
}
static int collect_attr_files(
......@@ -535,7 +536,7 @@ static int collect_attr_files(
int error;
git_buf dir = GIT_BUF_INIT;
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info;
attr_walk_up_info info = { NULL };
if (git_attr_cache__init(repo) < 0 ||
git_vector_init(files, 4, NULL) < 0)
......@@ -569,6 +570,8 @@ 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;
......
......@@ -107,6 +107,7 @@ struct head_info {
git_buf branchname;
const git_refspec *refspec;
bool found;
git_error_state error;
};
static int reference_matches_remote_head(
......@@ -115,43 +116,38 @@ static int reference_matches_remote_head(
{
struct head_info *head_info = (struct head_info *)payload;
git_oid oid;
int error;
/* TODO: Should we guard against references
* which name doesn't start with refs/heads/ ?
*/
/* Stop looking if we've already found a match */
if (head_info->found)
error = git_reference_name_to_id(&oid, head_info->repo, reference_name);
if (error == GIT_ENOTFOUND) {
/* If the reference doesn't exists, it obviously cannot match the
* expected oid. */
giterr_clear();
return 0;
if (git_reference_name_to_id(
&oid,
head_info->repo,
reference_name) < 0) {
/* If the reference doesn't exists, it obviously cannot match the expected oid. */
giterr_clear();
return 0;
}
if (git_oid__cmp(&head_info->remote_head_oid, &oid) == 0) {
if (!error && !git_oid__cmp(&head_info->remote_head_oid, &oid)) {
/* Determine the local reference name from the remote tracking one */
if (git_refspec_transform_l(
&head_info->branchname,
head_info->refspec,
reference_name) < 0)
return -1;
if (git_buf_len(&head_info->branchname) > 0) {
if (git_buf_sets(
&head_info->branchname,
git_buf_cstr(&head_info->branchname) + strlen(GIT_REFS_HEADS_DIR)) < 0)
return -1;
error = git_refspec_transform_l(
&head_info->branchname, head_info->refspec, reference_name);
head_info->found = 1;
if (!error &&
git_buf_len(&head_info->branchname) > 0 &&
!(error = git_buf_sets(
&head_info->branchname,
git_buf_cstr(&head_info->branchname) +
strlen(GIT_REFS_HEADS_DIR))))
{
head_info->found = true;
error = GIT_ITEROVER;
}
}
return 0;
return giterr_capture(&head_info->error, error);
}
static int update_head_to_new_branch(
......@@ -160,16 +156,11 @@ static int update_head_to_new_branch(
const char *name)
{
git_reference *tracking_branch = NULL;
int error;
if ((error = create_tracking_branch(
&tracking_branch,
repo,
target,
name)) < 0)
return error;
int error = create_tracking_branch(&tracking_branch, repo, target, name);
error = git_repository_set_head(repo, git_reference_name(tracking_branch));
if (!error)
error = git_repository_set_head(
repo, git_reference_name(tracking_branch));
git_reference_free(tracking_branch);
......@@ -178,34 +169,30 @@ static int update_head_to_new_branch(
static int update_head_to_remote(git_repository *repo, git_remote *remote)
{
int retcode = -1;
int error = 0;
size_t refs_len;
git_refspec dummy_spec;
const git_remote_head *remote_head, **refs;
struct head_info head_info;
git_buf remote_master_name = GIT_BUF_INIT;
if (git_remote_ls(&refs, &refs_len, remote) < 0)
return -1;
if ((error = git_remote_ls(&refs, &refs_len, remote)) < 0)
return error;
/* Did we just clone an empty repository? */
if (refs_len == 0) {
if (refs_len == 0)
return setup_tracking_config(
repo,
"master",
GIT_REMOTE_ORIGIN,
GIT_REFS_HEADS_MASTER_FILE);
}
repo, "master", GIT_REMOTE_ORIGIN, GIT_REFS_HEADS_MASTER_FILE);
/* Get the remote's HEAD. This is always the first ref in the list. */
remote_head = refs[0];
assert(remote_head);
memset(&head_info, 0, sizeof(head_info));
git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid);
git_buf_init(&head_info.branchname, 16);
head_info.repo = repo;
head_info.refspec = git_remote__matching_refspec(remote, GIT_REFS_HEADS_MASTER_FILE);
head_info.found = 0;
head_info.refspec =
git_remote__matching_refspec(remote, GIT_REFS_HEADS_MASTER_FILE);
if (head_info.refspec == NULL) {
memset(&dummy_spec, 0, sizeof(git_refspec));
......@@ -213,50 +200,53 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
}
/* Determine the remote tracking reference name from the local master */
if (git_refspec_transform_r(
if ((error = git_refspec_transform_r(
&remote_master_name,
head_info.refspec,
GIT_REFS_HEADS_MASTER_FILE) < 0)
return -1;
GIT_REFS_HEADS_MASTER_FILE)) < 0)
return error;
/* Check to see if the remote HEAD points to the remote master */
if (reference_matches_remote_head(git_buf_cstr(&remote_master_name), &head_info) < 0)
goto cleanup;
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 (head_info.found) {
retcode = update_head_to_new_branch(
error = update_head_to_new_branch(
repo,
&head_info.remote_head_oid,
git_buf_cstr(&head_info.branchname));
goto cleanup;
}
/* Not master. Check all the other refs. */
if (git_reference_foreach_name(
repo,
reference_matches_remote_head,
&head_info) < 0)
goto cleanup;
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;
if (head_info.found) {
retcode = update_head_to_new_branch(
error = update_head_to_new_branch(
repo,
&head_info.remote_head_oid,
git_buf_cstr(&head_info.branchname));
goto cleanup;
} else {
retcode = git_repository_set_head_detached(
repo,
&head_info.remote_head_oid);
goto cleanup;
error = git_repository_set_head_detached(
repo, &head_info.remote_head_oid);
}
cleanup:
git_buf_free(&remote_master_name);
git_buf_free(&head_info.branchname);
return retcode;
return error;
}
static int update_head_to_branch(
......
......@@ -269,8 +269,8 @@ int git_repository_fetchhead_foreach(git_repository *repo,
else
ref_name = NULL;
if ((cb(ref_name, remote_url, &oid, is_merge, payload)) != 0) {
error = GIT_EUSER;
if (cb(ref_name, remote_url, &oid, is_merge, payload) != 0) {
error = giterr_user_cancel();
goto done;
}
}
......
......@@ -74,10 +74,20 @@ 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)
{
git_ignores *ign = (git_ignores *)ref;
return push_ignore_file(ign->repo, ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
struct ignores_walk_up_data *data = ref;
return giterr_capture(
&data->error,
push_ignore_file(
data->ign->repo, data->ign, &data->ign->ign_path,
path->ptr, GIT_IGNORE_FILE) );
}
static int get_internal_ignores(git_attr_file **ign, git_repository *repo)
......@@ -132,8 +142,13 @@ 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, ignores);
&ignores->dir, workdir, push_one_ignore, &data);
if (error == GIT_EUSER)
error = giterr_restore(&data.error);
if (error < 0)
goto cleanup;
}
......
......@@ -2036,6 +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;
}
git_vector_sort(&entries);
git_index_clear(index);
......@@ -2116,8 +2122,7 @@ int git_index_add_all(
if (error > 0) /* return > 0 means skip this one */
continue;
if (error < 0) { /* return < 0 means abort */
giterr_clear();
error = GIT_EUSER;
error = giterr_user_cancel();
break;
}
}
......@@ -2205,8 +2210,7 @@ static int index_apply_to_all(
continue;
}
if (error < 0) { /* return < 0 means abort */
giterr_clear();
error = GIT_EUSER;
error = giterr_user_cancel();
break;
}
}
......
......@@ -387,10 +387,8 @@ 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)) {
giterr_clear();
return GIT_EUSER;
}
idx->progress_cb(stats, idx->progress_payload))
return giterr_user_cancel();
return 0;
}
......
......@@ -254,7 +254,8 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l
return 0;
}
int git_repository_mergehead_foreach(git_repository *repo,
int git_repository_mergehead_foreach(
git_repository *repo,
git_repository_mergehead_foreach_cb cb,
void *payload)
{
......@@ -287,7 +288,7 @@ int git_repository_mergehead_foreach(git_repository *repo,
goto cleanup;
if (cb(&oid, payload) != 0) {
error = GIT_EUSER;
error = giterr_user_cancel();
goto cleanup;
}
......
......@@ -584,7 +584,7 @@ int git_note_foreach(
while (!(error = git_note_next(&note_id, &annotated_id, iter))) {
if (note_cb(&note_id, &annotated_id, payload)) {
error = GIT_EUSER;
error = giterr_user_cancel();
break;
}
}
......
......@@ -32,6 +32,7 @@ struct unpacked {
struct tree_walk_context {
git_packbuilder *pb;
git_buf buf;
git_error_state error;
};
struct pack_write_context {
......@@ -220,12 +221,15 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
if (pb->progress_cb) {
double current_time = git__timer();
if ((current_time - pb->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) {
double elapsed = current_time - pb->last_progress_report_time;
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)) {
giterr_clear();
return GIT_EUSER;
}
if (pb->progress_cb(
GIT_PACKBUILDER_ADDING_OBJECTS,
pb->nr_objects, 0, pb->progress_cb_payload))
return giterr_user_cancel();
}
}
......@@ -1284,21 +1288,22 @@ const git_oid *git_packbuilder_hash(git_packbuilder *pb)
return &pb->pack_oid;
}
static int cb_tree_walk(const char *root, const git_tree_entry *entry, void *payload)
static int cb_tree_walk(
const char *root, const git_tree_entry *entry, void *payload)
{
int error;
struct tree_walk_context *ctx = payload;
/* A commit inside a tree represents a submodule commit and should be skipped. */
if (git_tree_entry_type(entry) == GIT_OBJ_COMMIT)
return 0;
if (git_buf_sets(&ctx->buf, root) < 0 ||
git_buf_puts(&ctx->buf, git_tree_entry_name(entry)) < 0)
return -1;
if (!(error = git_buf_sets(&ctx->buf, root)) &&
!(error = git_buf_puts(&ctx->buf, git_tree_entry_name(entry))))
error = git_packbuilder_insert(
ctx->pb, git_tree_entry_id(entry), git_buf_cstr(&ctx->buf));
return git_packbuilder_insert(ctx->pb,
git_tree_entry_id(entry),
git_buf_cstr(&ctx->buf));
return giterr_capture(&ctx->error, error);
}
int git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid *oid)
......@@ -1318,22 +1323,20 @@ int git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid *oid)
int git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid *oid)
{
git_tree *tree;
int error;
git_tree *tree = NULL;
struct tree_walk_context context = { pb, GIT_BUF_INIT };
if (git_tree_lookup(&tree, pb->repo, oid) < 0 ||
git_packbuilder_insert(pb, oid, NULL) < 0)
return -1;
if (!(error = git_tree_lookup(&tree, pb->repo, oid)) &&
!(error = git_packbuilder_insert(pb, oid, NULL)))
error = git_tree_walk(tree, GIT_TREEWALK_PRE, cb_tree_walk, &context);
if (git_tree_walk(tree, GIT_TREEWALK_PRE, cb_tree_walk, &context) < 0) {
git_tree_free(tree);
git_buf_free(&context.buf);
return -1;
}
if (error == GIT_EUSER)
error = giterr_restore(&context.error);
git_tree_free(tree);
git_buf_free(&context.buf);
return 0;
return error;
}
uint32_t git_packbuilder_object_count(git_packbuilder *pb)
......
......@@ -1042,10 +1042,9 @@ int git_pack_foreach_entry(
{
const unsigned char *index = p->index_map.data, *current;
uint32_t i;
int error = 0;
if (index == NULL) {
int error;
if ((error = pack_index_open(p)) < 0)
return error;
......@@ -1062,7 +1061,6 @@ int git_pack_foreach_entry(
if (p->oids == NULL) {
git_vector offsets, oids;
int error;
if ((error = git_vector_init(&oids, p->num_objects, NULL)))
return error;
......@@ -1090,7 +1088,7 @@ int git_pack_foreach_entry(
for (i = 0; i < p->num_objects; i++)
if (cb(p->oids[i], data))
return GIT_EUSER;
return giterr_user_cancel();
return 0;
}
......
......@@ -663,7 +663,7 @@ int git_push_status_foreach(git_push *push,
git_vector_foreach(&push->status, i, status) {
if (cb(status->ref, status->msg, data) < 0)
return GIT_EUSER;
return giterr_user_cancel();
}
return 0;
......
......@@ -513,20 +513,19 @@ int git_reference_foreach(
git_reference *ref;
int error;
if (git_reference_iterator_new(&iter, repo) < 0)
return -1;
if ((error = git_reference_iterator_new(&iter, repo)) < 0)
return error;
while ((error = git_reference_next(&ref, iter)) == 0) {
if (callback(ref, payload)) {
error = GIT_EUSER;
goto out;
error = giterr_user_cancel();
break;
}
}
if (error == GIT_ITEROVER)
error = 0;
out:
git_reference_iterator_free(iter);
return error;
}
......@@ -540,20 +539,19 @@ int git_reference_foreach_name(
const char *refname;
int error;
if (git_reference_iterator_new(&iter, repo) < 0)
return -1;
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 = GIT_EUSER;
goto out;
error = giterr_user_cancel();
break;
}
}
if (error == GIT_ITEROVER)
error = 0;
out:
git_reference_iterator_free(iter);
return error;
}
......@@ -568,20 +566,19 @@ int git_reference_foreach_glob(
const char *refname;
int error;
if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
return -1;
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 = GIT_EUSER;
goto out;
error = giterr_user_cancel();
break;
}
}
if (error == GIT_ITEROVER)
error = 0;
out:
git_reference_iterator_free(iter);
return error;
}
......
......@@ -1370,46 +1370,43 @@ static int rename_fetch_refspecs(
if (git_buf_printf(&base, "+refs/heads/*:refs/remotes/%s/*", remote->name) < 0)
goto cleanup;
if ((error = git_repository_config__weakptr(&config, remote->repo)) < 0)
goto cleanup;
git_vector_foreach(&remote->refspecs, i, spec) {
if (spec->push)
continue;
/* Every refspec is a problem refspec for an in-memory remote */
if (!remote->name) {
if (callback(spec->string, payload) < 0) {
error = GIT_EUSER;
goto cleanup;
}
continue;
}
/* Every refspec is a problem refspec for an in-memory remote, OR */
/* Does the dst part of the refspec follow the expected format? */
if (!remote->name ||
strcmp(git_buf_cstr(&base), spec->string)) {
/* Does the dst part of the refspec follow the extected standard format? */
if (strcmp(git_buf_cstr(&base), spec->string)) {
if (callback(spec->string, payload) < 0) {
error = GIT_EUSER;
error = giterr_user_cancel();
goto cleanup;
}
continue;
}
/* If we do want to move it to the new section */
if (git_buf_printf(&val, "+refs/heads/*:refs/remotes/%s/*", new_name) < 0)
goto cleanup;
if (git_buf_printf(&var, "remote.%s.fetch", new_name) < 0)
goto cleanup;
git_buf_clear(&val);
git_buf_clear(&var);
if (git_repository_config__weakptr(&config, remote->repo) < 0)
if (git_buf_printf(
&val, "+refs/heads/*:refs/remotes/%s/*", new_name) < 0 ||
git_buf_printf(&var, "remote.%s.fetch", new_name) < 0)
{
error = -1;
goto cleanup;
}
if (git_config_set_string(config, git_buf_cstr(&var), git_buf_cstr(&val)) < 0)
if ((error = git_config_set_string(
config, git_buf_cstr(&var), git_buf_cstr(&val))) < 0)
goto cleanup;
}
error = 0;
cleanup:
git_buf_free(&base);
git_buf_free(&var);
......@@ -1445,11 +1442,11 @@ int git_remote_rename(
new_name,
callback,
payload)) < 0)
return error;
return error;
remote->name = git__strdup(new_name);
GITERR_CHECK_ALLOC(remote->name);
if (!remote->name) return 0;
return git_remote_save(remote);
}
......@@ -1476,11 +1473,13 @@ int git_remote_rename(
new_name,
callback,
payload)) < 0)
return error;
return error;
}
git__free(remote->name);
remote->name = git__strdup(new_name);
GITERR_CHECK_ALLOC(remote->name);
return 0;
}
......
......@@ -112,12 +112,13 @@ static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commi
static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
{
int error;
git_object *obj;
git_otype type;
git_commit_list_node *commit;
if (git_object_lookup(&obj, walk->repo, oid, GIT_OBJ_ANY) < 0)
return -1;
if ((error = git_object_lookup(&obj, walk->repo, oid, GIT_OBJ_ANY)) < 0)
return error;
type = git_object_type(obj);
git_object_free(obj);
......@@ -168,13 +169,15 @@ 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 push_ref(data->walk, refname, data->hide);
return giterr_capture(
&data->error, push_ref(data->walk, refname, data->hide) );
}
static int push_glob(git_revwalk *walk, const char *glob, int hide)
......@@ -191,6 +194,8 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
git_buf_joinpath(&buf, GIT_REFS_DIR, glob);
else
git_buf_puts(&buf, glob);
if (git_buf_oom(&buf))
return -1;
/* If no '?', '*' or '[' exist, we append '/ *' to the glob */
wildcard = strcspn(glob, "?*[");
......@@ -199,12 +204,12 @@ 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));
if (git_buf_oom(&buf))
error = -1;
else
error = git_reference_foreach_glob(
walk->repo, git_buf_cstr(&buf), push_glob_cb, &data);
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;
......
......@@ -586,8 +586,8 @@ int git_stash_foreach(
git_reflog_entry_message(entry),
git_reflog_entry_id_new(entry),
payload)) {
error = GIT_EUSER;
break;
error = giterr_user_cancel();
break;
}
}
......
......@@ -414,8 +414,7 @@ int git_status_foreach_ext(
status_entry->index_to_workdir->old_file.path;
if (cb(path, status_entry->status, payload) != 0) {
error = GIT_EUSER;
giterr_clear();
error = giterr_user_cancel();
break;
}
}
......
......@@ -414,24 +414,29 @@ 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)
{
int error;
git_oid oid;
tag_cb_data *d = (tag_cb_data *)data;
if (git__prefixcmp(ref, GIT_REFS_TAGS_DIR) != 0)
return 0; /* no tag */
if (git_reference_name_to_id(&oid, d->repo, ref) < 0)
return -1;
if (!(error = git_reference_name_to_id(&oid, d->repo, ref))) {
if (d->cb(ref, &oid, d->cb_data))
error = giterr_user_cancel();
}
return d->cb(ref, &oid, d->cb_data);
return giterr_capture(&d->error, 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);
......@@ -439,8 +444,14 @@ 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));
return git_reference_foreach_name(repo, &tags_cb, &data);
error = git_reference_foreach_name(repo, &tags_cb, &data);
if (error == GIT_EUSER)
error = giterr_restore(&data.error);
return error;
}
typedef struct {
......@@ -455,8 +466,14 @@ static int tag_list_cb(const char *tag_name, git_oid *oid, void *data)
tag_filter_data *filter = (tag_filter_data *)data;
GIT_UNUSED(oid);
if (!*filter->pattern || p_fnmatch(filter->pattern, tag_name + GIT_REFS_TAGS_DIR_LEN, 0) == 0)
return git_vector_insert(filter->taglist, git__strdup(tag_name + GIT_REFS_TAGS_DIR_LEN));
if (!*filter->pattern ||
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;
return git_vector_insert(filter->taglist, matched);
}
return 0;
}
......@@ -469,16 +486,23 @@ int git_tag_list_match(git_strarray *tag_names, const char *pattern, git_reposit
assert(tag_names && repo && pattern);
if (git_vector_init(&taglist, 8, NULL) < 0)
return -1;
if ((error = git_vector_init(&taglist, 8, NULL)) < 0)
return error;
filter.taglist = &taglist;
filter.pattern = pattern;
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) {
git_vector_free(&taglist);
return -1;
return error;
}
tag_names->strings = (char **)taglist.contents;
......
......@@ -93,18 +93,19 @@ static int git_stream_read(
size_t buf_size,
size_t *bytes_read)
{
int error;
git_stream *s = (git_stream *)stream;
gitno_buffer buf;
*bytes_read = 0;
if (!s->sent_command && send_command(s) < 0)
return -1;
if (!s->sent_command && (error = send_command(s)) < 0)
return error;
gitno_buffer_setup(&s->socket, &buf, buffer, buf_size);
if (gitno_recv(&buf) < 0)
return -1;
if ((error = gitno_recv(&buf)) < 0)
return error;
*bytes_read = buf.offset;
......@@ -116,10 +117,11 @@ static int git_stream_write(
const char *buffer,
size_t len)
{
int error;
git_stream *s = (git_stream *)stream;
if (!s->sent_command && send_command(s) < 0)
return -1;
if (!s->sent_command && (error = send_command(s)) < 0)
return error;
return gitno_send(&s->socket, buffer, len, 0);
}
......@@ -140,7 +142,7 @@ static void git_stream_free(git_smart_subtransport_stream *stream)
}
git__free(s->url);
git__free(s);
git__free(s);
}
static int git_stream_alloc(
......@@ -182,18 +184,21 @@ static int _git_uploadpack_ls(
char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
const char *stream_url = url;
git_stream *s;
int error = -1;
int error;
*stream = NULL;
if (!git__prefixcmp(url, prefix_git))
stream_url += strlen(prefix_git);
if (git_stream_alloc(t, stream_url, cmd_uploadpack, stream) < 0)
return -1;
if ((error = git_stream_alloc(t, stream_url, cmd_uploadpack, stream)) < 0)
return error;
s = (git_stream *)*stream;
if (!(error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT))) {
if (!(error = gitno_extract_url_parts(
&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT))) {
if (!(error = gitno_connect(&s->socket, host, port, 0)))
t->current_stream = s;
......
......@@ -27,8 +27,7 @@ static int git_smart__recv_cb(gitno_buffer *buf)
if (t->packetsize_cb(bytes_read, t->packetsize_payload)) {
git_atomic_set(&t->cancelled, 1);
giterr_clear();
return GIT_EUSER;
return giterr_user_cancel();
}
return (int)(buf->offset - old_len);
......
......@@ -884,14 +884,12 @@ 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 > 0) {
error = 0;
continue;
}
if (error < 0) {
giterr_clear();
return GIT_EUSER;
}
}
if (git_tree_entry__is_tree(entry)) {
......@@ -918,11 +916,8 @@ static int tree_walk(
git_buf_truncate(path, path_len);
}
if (!preorder && callback(path->ptr, entry, payload) < 0) {
giterr_clear();
error = GIT_EUSER;
break;
}
if (!preorder && callback(path->ptr, entry, payload) < 0)
return giterr_user_cancel();
}
return error;
......
......@@ -350,15 +350,24 @@ void test_core_path__10_fromurl(void)
typedef struct {
int expect_idx;
int cancel_after;
char **expect;
} check_walkup_info;
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;
}
info->cancel_after--;
cl_assert(info->expect[info->expect_idx] != NULL);
cl_assert_equal_s(info->expect[info->expect_idx], path->ptr);
info->expect_idx++;
return 0;
}
......@@ -381,6 +390,7 @@ void test_core_path__11_walkup(void)
check_walkup_info info;
info.expect = expect;
info.cancel_after = -1;
for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
......@@ -400,6 +410,42 @@ void test_core_path__11_walkup(void)
git_buf_free(&p);
}
void test_core_path__11a_walkup_cancel(void)
{
git_buf p = GIT_BUF_INIT;
int cancel[] = { 3, 2, 1, 0 };
char *expect[] = {
"/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "[CANCEL]", NULL,
"/a/b/c/d/e", "/a/b/c/d/", "[CANCEL]", NULL,
"/a/b/c/d/e", "[CANCEL]", NULL,
"[CANCEL]", NULL,
NULL
};
char *root[] = { NULL, NULL, "/", "", NULL };
int i, j;
check_walkup_info info;
info.expect = expect;
for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
git_buf_sets(&p, expect[i]);
info.cancel_after = cancel[j];
info.expect_idx = i;
cl_assert_equal_i(
GIT_EUSER,
git_path_walk_up(&p, root[j], check_one_walkup_step, &info)
);
/* skip to next run of expectations */
while (expect[i] != NULL) i++;
}
git_buf_free(&p);
}
void test_core_path__12_offset_to_path_root(void)
{
cl_assert(git_path_root("non/rooted/path") == -1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment