mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-06 00:30:16 +00:00
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.
This commit is contained in:
parent
96869a4edb
commit
dab89f9b68
@ -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;
|
||||
|
||||
|
118
src/clone.c
118
src/clone.c
@ -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;
|
||||
error = git_refspec_transform_l(
|
||||
&head_info->branchname, head_info->refspec, reference_name);
|
||||
|
||||
if (git_buf_len(&head_info->branchname) > 0) {
|
||||
if (git_buf_sets(
|
||||
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)) < 0)
|
||||
return -1;
|
||||
|
||||
head_info->found = 1;
|
||||
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;
|
||||
int error = create_tracking_branch(&tracking_branch, repo, target, name);
|
||||
|
||||
if ((error = create_tracking_branch(
|
||||
&tracking_branch,
|
||||
repo,
|
||||
target,
|
||||
name)) < 0)
|
||||
return error;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
21
src/ignore.c
21
src/ignore.c
@ -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;
|
||||
}
|
||||
|
12
src/index.c
12
src/index.c
@ -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(¬e_id, &annotated_id, iter))) {
|
||||
if (note_cb(¬e_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;
|
||||
|
27
src/refs.c
27
src/refs.c
@ -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;
|
||||
}
|
||||
|
49
src/remote.c
49
src/remote.c
@ -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) {
|
||||
/* 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)) {
|
||||
|
||||
if (callback(spec->string, payload) < 0) {
|
||||
error = GIT_EUSER;
|
||||
error = giterr_user_cancel();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
42
src/tag.c
42
src/tag.c
@ -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);
|
||||
|
13
src/tree.c
13
src/tree.c
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user