Commit a62053a0 by Carlos Martín Nieto Committed by Vicent Martí

error-handling local transport

parent 5eb8affb
...@@ -26,115 +26,104 @@ static int add_ref(transport_local *t, const char *name) ...@@ -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)); git_oid_cpy(&head->oid, git_object_id(target));
git_object_free(obj);
git_object_free(target);
error = git_vector_insert(&t->refs, head); if (git_vector_insert(&t->refs, head) < 0)
if (error < GIT_SUCCESS) return -1;
goto out;
out: return 0;
git_reference_free(ref);
git_reference_free(resolved_ref);
on_error:
git_object_free(obj); git_object_free(obj);
git_object_free(peeled_tag_target); git_object_free(target);
if (head && error < GIT_SUCCESS) { return -1;
git__free(head->name);
git__free(head);
}
return error;
} }
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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -249,5 +235,5 @@ int git_transport_local(git_transport **out)
*out = (git_transport *) t; *out = (git_transport *) t;
return GIT_SUCCESS; return 0;
} }
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