diff options
Diffstat (limited to 'src/transports/local.c')
-rw-r--r-- | src/transports/local.c | 160 |
1 files changed, 76 insertions, 84 deletions
diff --git a/src/transports/local.c b/src/transports/local.c index a2135e73e..000993e69 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011 the libgit2 contributors + * Copyright (C) 2009-2012 the libgit2 contributors * * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. @@ -26,110 +26,94 @@ static int add_ref(transport_local *t, const char *name) { const char peeled[] = "^{}"; git_remote_head *head; - git_reference *ref, *resolved_ref; - git_object *obj = NULL; - int error = GIT_SUCCESS, peel_len, ret; + git_object *obj = NULL, *target = NULL; + git_buf buf = GIT_BUF_INIT; head = git__malloc(sizeof(git_remote_head)); - if (head == NULL) - return GIT_ENOMEM; + GITERR_CHECK_ALLOC(head); head->name = git__strdup(name); - if (head->name == NULL) { - error = GIT_ENOMEM; - goto out; - } - - error = git_reference_lookup(&ref, t->repo, name); - if (error < GIT_SUCCESS) - goto out; - - error = git_reference_resolve(&resolved_ref, ref); - if (error < GIT_SUCCESS) - goto out; + GITERR_CHECK_ALLOC(head->name); - git_oid_cpy(&head->oid, git_reference_oid(resolved_ref)); - - error = git_vector_insert(&t->refs, head); - if (error < GIT_SUCCESS) - goto out; + if (git_reference_name_to_oid(&head->oid, t->repo, name) < 0 || + git_vector_insert(&t->refs, head) < 0) + { + git__free(head->name); + git__free(head); + return -1; + } /* If it's not a tag, we don't need to try to peel it */ 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 (error < GIT_SUCCESS) { - git__rethrow(error, "Failed to lookup object"); - } + if (git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJ_ANY) < 0) + return -1; head = NULL; /* If it's not an annotated tag, just get out */ - if (git_object_type(obj) != GIT_OBJ_TAG) - goto out; + if (git_object_type(obj) != GIT_OBJ_TAG) { + git_object_free(obj); + return 0; + } /* And if it's a tag, peel it, and add it to the list */ head = git__malloc(sizeof(git_remote_head)); - peel_len = strlen(name) + strlen(peeled); - head->name = git__malloc(peel_len + 1); - ret = p_snprintf(head->name, peel_len + 1, "%s%s", name, peeled); + GITERR_CHECK_ALLOC(head); + if (git_buf_join(&buf, 0, name, peeled) < 0) + return -1; - assert(ret < peel_len + 1); - (void)ret; + head->name = git_buf_detach(&buf); - git_oid_cpy(&head->oid, git_tag_target_oid((git_tag *) obj)); + if (git_tag_peel(&target, (git_tag *) obj) < 0) + goto on_error; - error = git_vector_insert(&t->refs, head); - if (error < GIT_SUCCESS) - goto out; + git_oid_cpy(&head->oid, git_object_id(target)); + git_object_free(obj); + git_object_free(target); - out: - git_reference_free(ref); - git_reference_free(resolved_ref); + if (git_vector_insert(&t->refs, head) < 0) + return -1; - git_object_free(obj); - if (head && error < GIT_SUCCESS) { - git__free(head->name); - git__free(head); - } + return 0; - return error; +on_error: + git_object_free(obj); + git_object_free(target); + return -1; } static int store_refs(transport_local *t) { - int error; unsigned int i; git_strarray ref_names = {0}; assert(t); - error = git_vector_init(&t->refs, ref_names.count, NULL); - if (error < GIT_SUCCESS) - return error; - - error = git_reference_listall(&ref_names, t->repo, GIT_REF_LISTALL); - if (error < GIT_SUCCESS) - return git__rethrow(error, "Failed to list remote heads"); + if (git_reference_list(&ref_names, t->repo, GIT_REF_LISTALL) < 0 || + git_vector_init(&t->refs, (unsigned int)ref_names.count, NULL) < 0) + goto on_error; /* Sort the references first */ git__tsort((void **)ref_names.strings, ref_names.count, &git__strcmp_cb); /* Add HEAD */ - error = add_ref(t, GIT_HEAD_FILE); - if (error < GIT_SUCCESS) - goto cleanup; + if (add_ref(t, GIT_HEAD_FILE) < 0) + goto on_error; for (i = 0; i < ref_names.count; ++i) { - error = add_ref(t, ref_names.strings[i]); - if (error < GIT_SUCCESS) - goto cleanup; + if (add_ref(t, ref_names.strings[i]) < 0) + goto on_error; } -cleanup: git_strarray_free(&ref_names); - return error; + return 0; + +on_error: + git_vector_free(&t->refs); + git_strarray_free(&ref_names); + return -1; } static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *payload) @@ -143,18 +127,17 @@ static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *pay git_vector_foreach(refs, i, h) { if (list_cb(h, payload) < 0) - return git__throw(GIT_ERROR, - "The user callback returned an error code"); + return -1; } - return GIT_SUCCESS; + return 0; } /* * Try to open the url as a git directory. The direction doesn't * matter in this case because we're calulating the heads ourselves. */ -static int local_connect(git_transport *transport, int GIT_UNUSED(direction)) +static int local_connect(git_transport *transport, int direction) { git_repository *repo; int error; @@ -162,46 +145,55 @@ static int local_connect(git_transport *transport, int GIT_UNUSED(direction)) const char *path; git_buf buf = GIT_BUF_INIT; - GIT_UNUSED_ARG(direction); + GIT_UNUSED(direction); /* The repo layer doesn't want the prefix */ if (!git__prefixcmp(transport->url, "file://")) { - error = git_path_fromurl(&buf, transport->url); - if (error < GIT_SUCCESS) { + if (git_path_fromurl(&buf, transport->url) < 0) { git_buf_free(&buf); - return git__rethrow(error, "Failed to parse remote path"); + return -1; } 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; + } error = git_repository_open(&repo, path); git_buf_free(&buf); - if (error < GIT_SUCCESS) - return git__rethrow(error, "Failed to open remote"); + if (error < 0) + return -1; t->repo = repo; - error = store_refs(t); - if (error < GIT_SUCCESS) - return git__rethrow(error, "Failed to retrieve references"); + if (store_refs(t) < 0) + return -1; t->parent.connected = 1; - return GIT_SUCCESS; + return 0; +} + +static int local_negotiate_fetch(git_transport *transport, git_repository *repo, const git_vector *wants) +{ + GIT_UNUSED(transport); + GIT_UNUSED(repo); + GIT_UNUSED(wants); + + giterr_set(GITERR_NET, "Fetch via local transport isn't implemented. Sorry"); + return -1; } -static int local_close(git_transport *GIT_UNUSED(transport)) +static int local_close(git_transport *transport) { transport_local *t = (transport_local *)transport; git_repository_free(t->repo); t->repo = NULL; - return GIT_SUCCESS; + return 0; } static void local_free(git_transport *transport) @@ -232,17 +224,17 @@ int git_transport_local(git_transport **out) transport_local *t; t = git__malloc(sizeof(transport_local)); - if (t == NULL) - return GIT_ENOMEM; + GITERR_CHECK_ALLOC(t); memset(t, 0x0, sizeof(transport_local)); t->parent.connect = local_connect; t->parent.ls = local_ls; + t->parent.negotiate_fetch = local_negotiate_fetch; t->parent.close = local_close; t->parent.free = local_free; *out = (git_transport *) t; - return GIT_SUCCESS; + return 0; } |