summaryrefslogtreecommitdiff
path: root/src/transports/local.c
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-11-28 08:40:40 +0100
committerVicent Marti <tanoku@gmail.com>2011-11-28 08:40:40 +0100
commitd88d4311c7e08ad0d38edae006b50e2a548c937d (patch)
tree1b26cee0c3d383043902c599893299fd8fdc5302 /src/transports/local.c
parentc94785a9f373b6604402ba6a301b828b80ab8cd8 (diff)
downloadlibgit2-d88d4311c7e08ad0d38edae006b50e2a548c937d.tar.gz
remote: Cleanup the remotes coderepo-ownership
- Hide the remaining transports code - Drop `git_headarray`, switch to using a callback to list refs. Makes the code cleaner.
Diffstat (limited to 'src/transports/local.c')
-rw-r--r--src/transports/local.c167
1 files changed, 86 insertions, 81 deletions
diff --git a/src/transports/local.c b/src/transports/local.c
index afc17e55f..f50a96173 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -6,7 +6,6 @@
*/
#include "common.h"
#include "git2/types.h"
-#include "git2/transport.h"
#include "git2/net.h"
#include "git2/repository.h"
#include "git2/object.h"
@@ -18,39 +17,10 @@
typedef struct {
git_transport parent;
git_repository *repo;
- git_vector *refs;
+ git_vector refs;
} transport_local;
-/*
- * 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))
-{
- git_repository *repo;
- int error;
- transport_local *t = (transport_local *) transport;
- const char *path;
- const char file_prefix[] = "file://";
- GIT_UNUSED_ARG(direction);
-
- /* The repo layer doesn't want the prefix */
- if (!git__prefixcmp(transport->url, file_prefix))
- path = transport->url + strlen(file_prefix);
- else
- path = transport->url;
-
- error = git_repository_open(&repo, path);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to open remote");
-
- t->repo = repo;
- t->parent.connected = 1;
-
- return GIT_SUCCESS;
-}
-
-static int add_ref(const char *name, git_repository *repo, git_vector *vec)
+static int add_ref(transport_local *t, const char *name)
{
const char peeled[] = "^{}";
git_remote_head *head;
@@ -68,7 +38,7 @@ static int add_ref(const char *name, git_repository *repo, git_vector *vec)
goto out;
}
- error = git_reference_lookup(&ref, repo, name);
+ error = git_reference_lookup(&ref, t->repo, name);
if (error < GIT_SUCCESS)
goto out;
@@ -78,15 +48,17 @@ static int add_ref(const char *name, git_repository *repo, git_vector *vec)
git_oid_cpy(&head->oid, git_reference_oid(ref));
- error = git_vector_insert(vec, head);
+ error = git_vector_insert(&t->refs, head);
if (error < GIT_SUCCESS)
goto out;
+ head = NULL;
+
/* 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;
- error = git_object_lookup(&obj, repo, &head->oid, GIT_OBJ_ANY);
+ error = git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJ_ANY);
if (error < GIT_SUCCESS) {
git__rethrow(error, "Failed to lookup object");
}
@@ -100,13 +72,12 @@ static int add_ref(const char *name, git_repository *repo, git_vector *vec)
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);
- if (ret >= peel_len + 1) {
- error = git__throw(GIT_ERROR, "The string is magically to long");
- }
+
+ assert(ret < peel_len + 1);
git_oid_cpy(&head->oid, git_tag_target_oid((git_tag *) obj));
- error = git_vector_insert(vec, head);
+ error = git_vector_insert(&t->refs, head);
if (error < GIT_SUCCESS)
goto out;
@@ -115,70 +86,108 @@ static int add_ref(const char *name, git_repository *repo, git_vector *vec)
git_reference_free(resolved_ref);
git_object_free(obj);
- if (error < GIT_SUCCESS) {
+ if (head && error < GIT_SUCCESS) {
git__free(head->name);
git__free(head);
}
+
return error;
}
-static int local_ls(git_transport *transport, git_headarray *array)
+static int store_refs(transport_local *t)
{
int error;
unsigned int i;
- git_repository *repo;
- git_vector *vec;
- git_strarray refs;
- transport_local *t = (transport_local *) transport;
+ git_strarray ref_names = {0};
- assert(transport && transport->connected);
-
- repo = t->repo;
+ assert(t);
- error = git_reference_listall(&refs, repo, GIT_REF_LISTALL);
+ error = git_vector_init(&t->refs, ref_names.count, NULL);
if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to list remote heads");
-
- vec = git__malloc(sizeof(git_vector));
- if (vec == NULL) {
- error = GIT_ENOMEM;
- goto out;
- }
+ return error;
- error = git_vector_init(vec, refs.count, NULL);
+ error = git_reference_listall(&ref_names, t->repo, GIT_REF_LISTALL);
if (error < GIT_SUCCESS)
- return error;
+ return git__rethrow(error, "Failed to list remote heads");
/* Sort the references first */
- git__tsort((void **)refs.strings, refs.count, &git__strcmp_cb);
+ git__tsort((void **)ref_names.strings, ref_names.count, &git__strcmp_cb);
/* Add HEAD */
- error = add_ref(GIT_HEAD_FILE, repo, vec);
+ error = add_ref(t, GIT_HEAD_FILE);
if (error < GIT_SUCCESS)
- goto out;
+ goto cleanup;
- for (i = 0; i < refs.count; ++i) {
- error = add_ref(refs.strings[i], repo, vec);
+ for (i = 0; i < ref_names.count; ++i) {
+ error = add_ref(t, ref_names.strings[i]);
if (error < GIT_SUCCESS)
- goto out;
+ goto cleanup;
}
- array->len = vec->length;
- array->heads = (git_remote_head **)vec->contents;
+cleanup:
+ git_strarray_free(&ref_names);
+ return error;
+}
- t->refs = vec;
+static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *payload)
+{
+ transport_local *t = (transport_local *) transport;
+ git_vector *refs = &t->refs;
+ unsigned int i;
+ git_remote_head *h;
- out:
+ assert(transport && transport->connected);
- git_strarray_free(&refs);
+ 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 error;
+ return GIT_SUCCESS;
+}
+
+
+/*
+ * 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))
+{
+ git_repository *repo;
+ int error;
+ transport_local *t = (transport_local *) transport;
+ const char *path;
+ const char file_prefix[] = "file://";
+ GIT_UNUSED_ARG(direction);
+
+ /* The repo layer doesn't want the prefix */
+ if (!git__prefixcmp(transport->url, file_prefix))
+ path = transport->url + strlen(file_prefix);
+ else
+ path = transport->url;
+
+ error = git_repository_open(&repo, path);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to open remote");
+
+ error = store_refs(t);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to retrieve references");
+
+ t->repo = repo;
+ t->parent.connected = 1;
+
+ return GIT_SUCCESS;
}
static int local_close(git_transport *GIT_UNUSED(transport))
{
- /* Nothing to do */
- GIT_UNUSED_ARG(transport);
+ transport_local *t = (transport_local *)transport;
+
+ git_repository_free(t->repo);
+ t->repo = NULL;
+
return GIT_SUCCESS;
}
@@ -186,21 +195,17 @@ static void local_free(git_transport *transport)
{
unsigned int i;
transport_local *t = (transport_local *) transport;
- git_vector *vec = t->refs;
+ git_vector *vec = &t->refs;
git_remote_head *h;
assert(transport);
- if (t->refs != NULL) {
- git_vector_foreach (vec, i, h) {
- git__free(h->name);
- git__free(h);
- }
- git_vector_free(vec);
- git__free(vec);
+ git_vector_foreach (vec, i, h) {
+ git__free(h->name);
+ git__free(h);
}
+ git_vector_free(vec);
- git_repository_free(t->repo);
git__free(t->parent.url);
git__free(t);
}