mirror of
https://git.proxmox.com/git/libgit2
synced 2025-07-05 09:37:58 +00:00
error-handling local transport
This commit is contained in:
parent
5eb8affb38
commit
a62053a050
@ -26,115 +26,104 @@ static int add_ref(transport_local *t, const char *name)
|
|||||||
{
|
{
|
||||||
const char peeled[] = "^{}";
|
const char peeled[] = "^{}";
|
||||||
git_remote_head *head;
|
git_remote_head *head;
|
||||||
git_reference *ref, *resolved_ref;
|
git_reference *ref = NULL, *resolved_ref = NULL;
|
||||||
git_object *obj = NULL, *peeled_tag_target = NULL;
|
git_object *obj = NULL, *target = NULL;
|
||||||
int error = GIT_SUCCESS, peel_len, ret;
|
git_buf buf = GIT_BUF_INIT;
|
||||||
|
|
||||||
head = git__malloc(sizeof(git_remote_head));
|
if (git_reference_lookup(&ref, t->repo, name) < 0)
|
||||||
if (head == NULL)
|
return -1;
|
||||||
return GIT_ENOMEM;
|
|
||||||
|
|
||||||
head->name = git__strdup(name);
|
if (git_reference_resolve(&resolved_ref, ref) < 0) {
|
||||||
if (head->name == NULL) {
|
git_reference_free(ref);
|
||||||
error = GIT_ENOMEM;
|
return -1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error = git_reference_lookup(&ref, t->repo, name);
|
head = git__malloc(sizeof(git_remote_head));
|
||||||
if (error < GIT_SUCCESS)
|
GITERR_CHECK_ALLOC(head);
|
||||||
goto out;
|
|
||||||
|
|
||||||
error = git_reference_resolve(&resolved_ref, ref);
|
head->name = git__strdup(name);
|
||||||
if (error < GIT_SUCCESS)
|
GITERR_CHECK_ALLOC(head->name);
|
||||||
goto out;
|
|
||||||
|
|
||||||
git_oid_cpy(&head->oid, git_reference_oid(resolved_ref));
|
git_oid_cpy(&head->oid, git_reference_oid(resolved_ref));
|
||||||
|
|
||||||
error = git_vector_insert(&t->refs, head);
|
if (git_vector_insert(&t->refs, head) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
goto out;
|
|
||||||
|
git_reference_free(ref);
|
||||||
|
git_reference_free(resolved_ref);
|
||||||
|
|
||||||
/* If it's not a tag, we don't need to try to peel it */
|
/* If it's not a tag, we don't need to try to peel it */
|
||||||
if (git__prefixcmp(name, GIT_REFS_TAGS_DIR))
|
if (git__prefixcmp(name, GIT_REFS_TAGS_DIR))
|
||||||
goto out;
|
return 0;
|
||||||
|
|
||||||
error = git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJ_ANY);
|
if (git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJ_ANY) < 0)
|
||||||
if (error < GIT_SUCCESS) {
|
return -1;
|
||||||
git__rethrow(error, "Failed to lookup object");
|
|
||||||
}
|
|
||||||
|
|
||||||
head = NULL;
|
head = NULL;
|
||||||
|
|
||||||
/* If it's not an annotated tag, just get out */
|
/* If it's not an annotated tag, just get out */
|
||||||
if (git_object_type(obj) != GIT_OBJ_TAG)
|
if (git_object_type(obj) != GIT_OBJ_TAG) {
|
||||||
goto out;
|
git_object_free(obj);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* And if it's a tag, peel it, and add it to the list */
|
/* And if it's a tag, peel it, and add it to the list */
|
||||||
head = git__malloc(sizeof(git_remote_head));
|
head = git__malloc(sizeof(git_remote_head));
|
||||||
peel_len = strlen(name) + strlen(peeled);
|
GITERR_CHECK_ALLOC(head);
|
||||||
head->name = git__malloc(peel_len + 1);
|
if (git_buf_join(&buf, 0, name, peeled) < 0)
|
||||||
ret = p_snprintf(head->name, peel_len + 1, "%s%s", name, peeled);
|
return -1;
|
||||||
|
|
||||||
assert(ret < peel_len + 1);
|
head->name = git_buf_detach(&buf);
|
||||||
(void)ret;
|
|
||||||
|
|
||||||
error = git_tag_peel(&peeled_tag_target, (git_tag *) obj);
|
if (git_tag_peel(&target, (git_tag *) obj) < 0)
|
||||||
if (error < 0)
|
goto on_error;
|
||||||
goto out;
|
|
||||||
|
|
||||||
git_oid_cpy(&head->oid, git_object_id(peeled_tag_target));
|
|
||||||
|
|
||||||
error = git_vector_insert(&t->refs, head);
|
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
git_reference_free(ref);
|
|
||||||
git_reference_free(resolved_ref);
|
|
||||||
|
|
||||||
|
git_oid_cpy(&head->oid, git_object_id(target));
|
||||||
git_object_free(obj);
|
git_object_free(obj);
|
||||||
git_object_free(peeled_tag_target);
|
git_object_free(target);
|
||||||
if (head && error < GIT_SUCCESS) {
|
|
||||||
git__free(head->name);
|
|
||||||
git__free(head);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
if (git_vector_insert(&t->refs, head) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
on_error:
|
||||||
|
git_object_free(obj);
|
||||||
|
git_object_free(target);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int store_refs(transport_local *t)
|
static int store_refs(transport_local *t)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
git_strarray ref_names = {0};
|
git_strarray ref_names = {0};
|
||||||
|
|
||||||
assert(t);
|
assert(t);
|
||||||
|
|
||||||
error = git_vector_init(&t->refs, ref_names.count, NULL);
|
if (git_vector_init(&t->refs, ref_names.count, NULL) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return error;
|
|
||||||
|
|
||||||
error = git_reference_listall(&ref_names, t->repo, GIT_REF_LISTALL);
|
if (git_reference_listall(&ref_names, t->repo, GIT_REF_LISTALL) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
goto on_error;
|
||||||
return git__rethrow(error, "Failed to list remote heads");
|
|
||||||
|
|
||||||
/* Sort the references first */
|
/* Sort the references first */
|
||||||
git__tsort((void **)ref_names.strings, ref_names.count, &git__strcmp_cb);
|
git__tsort((void **)ref_names.strings, ref_names.count, &git__strcmp_cb);
|
||||||
|
|
||||||
/* Add HEAD */
|
/* Add HEAD */
|
||||||
error = add_ref(t, GIT_HEAD_FILE);
|
if (add_ref(t, GIT_HEAD_FILE) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
goto on_error;
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
for (i = 0; i < ref_names.count; ++i) {
|
for (i = 0; i < ref_names.count; ++i) {
|
||||||
error = add_ref(t, ref_names.strings[i]);
|
if (add_ref(t, ref_names.strings[i]) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
goto on_error;
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
return 0;
|
||||||
|
|
||||||
|
on_error:
|
||||||
|
git_vector_free(&t->refs);
|
||||||
git_strarray_free(&ref_names);
|
git_strarray_free(&ref_names);
|
||||||
return error;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *payload)
|
static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *payload)
|
||||||
@ -148,11 +137,10 @@ static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *pay
|
|||||||
|
|
||||||
git_vector_foreach(refs, i, h) {
|
git_vector_foreach(refs, i, h) {
|
||||||
if (list_cb(h, payload) < 0)
|
if (list_cb(h, payload) < 0)
|
||||||
return git__throw(GIT_ERROR,
|
return -1;
|
||||||
"The user callback returned an error code");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -171,32 +159,31 @@ static int local_connect(git_transport *transport, int direction)
|
|||||||
|
|
||||||
/* The repo layer doesn't want the prefix */
|
/* The repo layer doesn't want the prefix */
|
||||||
if (!git__prefixcmp(transport->url, "file://")) {
|
if (!git__prefixcmp(transport->url, "file://")) {
|
||||||
error = git_path_fromurl(&buf, transport->url);
|
if (git_path_fromurl(&buf, transport->url) < 0) {
|
||||||
if (error < GIT_SUCCESS) {
|
|
||||||
git_buf_free(&buf);
|
git_buf_free(&buf);
|
||||||
return git__rethrow(error, "Failed to parse remote path");
|
return -1;
|
||||||
}
|
}
|
||||||
path = git_buf_cstr(&buf);
|
path = git_buf_cstr(&buf);
|
||||||
|
|
||||||
} else /* We assume transport->url is already a path */
|
} else { /* We assume transport->url is already a path */
|
||||||
path = transport->url;
|
path = transport->url;
|
||||||
|
}
|
||||||
|
|
||||||
error = git_repository_open(&repo, path);
|
error = git_repository_open(&repo, path);
|
||||||
|
|
||||||
git_buf_free(&buf);
|
git_buf_free(&buf);
|
||||||
|
|
||||||
if (error < GIT_SUCCESS)
|
if (error < 0)
|
||||||
return git__rethrow(error, "Failed to open remote");
|
return -1;
|
||||||
|
|
||||||
t->repo = repo;
|
t->repo = repo;
|
||||||
|
|
||||||
error = store_refs(t);
|
if (store_refs(t) < 0)
|
||||||
if (error < GIT_SUCCESS)
|
return -1;
|
||||||
return git__rethrow(error, "Failed to retrieve references");
|
|
||||||
|
|
||||||
t->parent.connected = 1;
|
t->parent.connected = 1;
|
||||||
|
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_close(git_transport *transport)
|
static int local_close(git_transport *transport)
|
||||||
@ -206,7 +193,7 @@ static int local_close(git_transport *transport)
|
|||||||
git_repository_free(t->repo);
|
git_repository_free(t->repo);
|
||||||
t->repo = NULL;
|
t->repo = NULL;
|
||||||
|
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void local_free(git_transport *transport)
|
static void local_free(git_transport *transport)
|
||||||
@ -237,8 +224,7 @@ int git_transport_local(git_transport **out)
|
|||||||
transport_local *t;
|
transport_local *t;
|
||||||
|
|
||||||
t = git__malloc(sizeof(transport_local));
|
t = git__malloc(sizeof(transport_local));
|
||||||
if (t == NULL)
|
GITERR_CHECK_ALLOC(t);
|
||||||
return GIT_ENOMEM;
|
|
||||||
|
|
||||||
memset(t, 0x0, sizeof(transport_local));
|
memset(t, 0x0, sizeof(transport_local));
|
||||||
|
|
||||||
@ -249,5 +235,5 @@ int git_transport_local(git_transport **out)
|
|||||||
|
|
||||||
*out = (git_transport *) t;
|
*out = (git_transport *) t;
|
||||||
|
|
||||||
return GIT_SUCCESS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user