diff --git a/src/transports/local.c b/src/transports/local.c index 6cf0573e8..c433339a7 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -46,14 +46,12 @@ static int add_ref(transport_local *t, const char *name) if (error < GIT_SUCCESS) goto out; - git_oid_cpy(&head->oid, git_reference_oid(ref)); + git_oid_cpy(&head->oid, git_reference_oid(resolved_ref)); 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; @@ -63,6 +61,8 @@ static int add_ref(transport_local *t, const char *name) git__rethrow(error, "Failed to lookup object"); } + head = NULL; + /* If it's not an annotated tag, just get out */ if (git_object_type(obj) != GIT_OBJ_TAG) goto out; @@ -163,20 +163,30 @@ static int local_connect(git_transport *transport, int GIT_UNUSED(direction)) 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 + if (!git__prefixcmp(transport->url, "file://")) { + path = transport->url + strlen("file://"); + +#ifdef _MSC_VER + /* skip the leading slash on windows before the drive letter */ + if (*path != '/') + return git__throw(GIT_EINVALIDPATH, "Invalid local uri '%s'.", transport->url); + + path++; +#endif + + } 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; + 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; diff --git a/tests-clay/clay.h b/tests-clay/clay.h index 210273532..f58076790 100644 --- a/tests-clay/clay.h +++ b/tests-clay/clay.h @@ -126,6 +126,9 @@ extern void test_core_vector__0(void); extern void test_core_vector__1(void); extern void test_core_vector__2(void); extern void test_index_rename__single_file(void); +extern void test_network_remotelocal__cleanup(void); +extern void test_network_remotelocal__initialize(void); +extern void test_network_remotelocal__retrieve_advertised_references(void); extern void test_network_remotes__cleanup(void); extern void test_network_remotes__fnmatch(void); extern void test_network_remotes__initialize(void); diff --git a/tests-clay/clay_main.c b/tests-clay/clay_main.c index af9e08877..d2c954e22 100644 --- a/tests-clay/clay_main.c +++ b/tests-clay/clay_main.c @@ -199,6 +199,9 @@ static const struct clay_func _clay_cb_core_vector[] = { static const struct clay_func _clay_cb_index_rename[] = { {"single_file", &test_index_rename__single_file} }; +static const struct clay_func _clay_cb_network_remotelocal[] = { + {"retrieve_advertised_references", &test_network_remotelocal__retrieve_advertised_references} +}; static const struct clay_func _clay_cb_network_remotes[] = { {"fnmatch", &test_network_remotes__fnmatch}, {"parsing", &test_network_remotes__parsing}, @@ -397,6 +400,12 @@ static const struct clay_suite _clay_suites[] = { {NULL, NULL}, {NULL, NULL}, _clay_cb_index_rename, 1 + }, + { + "network::remotelocal", + {"initialize", &test_network_remotelocal__initialize}, + {"cleanup", &test_network_remotelocal__cleanup}, + _clay_cb_network_remotelocal, 1 }, { "network::remotes", @@ -520,8 +529,8 @@ static const struct clay_suite _clay_suites[] = { } }; -static size_t _clay_suite_count = 36; -static size_t _clay_callback_count = 120; +static size_t _clay_suite_count = 37; +static size_t _clay_callback_count = 121; /* Core test functions */ static void diff --git a/tests-clay/network/remotelocal.c b/tests-clay/network/remotelocal.c new file mode 100644 index 000000000..7dad39a4b --- /dev/null +++ b/tests-clay/network/remotelocal.c @@ -0,0 +1,71 @@ +#include "clay_libgit2.h" +#include "transport.h" +#include "buffer.h" +#include "path.h" + +static git_repository *repo; +static git_buf file_path_buf = GIT_BUF_INIT; +static git_remote *remote; + +static void build_local_file_url(git_buf *out, const char *fixture) +{ + git_buf path_buf = GIT_BUF_INIT; + + cl_git_pass(git_path_prettify_dir(&path_buf, cl_fixture(fixture), NULL)); + cl_git_pass(git_buf_puts(out, "file://")); + +#ifdef _MSC_VER + /* + * A FILE uri matches the following format: file://[host]/path + * where "host" can be empty and "path" is an absolute path to the resource. + * + * In this test, no hostname is used, but we have to ensure the leading triple slashes: + * + * *nix: file:///usr/home/... + * Windows: file:///C:/Users/... + */ + cl_git_pass(git_buf_putc(out, '/')); +#endif + + cl_git_pass(git_buf_puts(out, git_buf_cstr(&path_buf))); + + git_buf_free(&path_buf); +} + +void test_network_remotelocal__initialize(void) +{ + cl_fixture("remotelocal"); + cl_git_pass(git_repository_init(&repo, "remotelocal/", 0)); + cl_assert(repo != NULL); + + build_local_file_url(&file_path_buf, "testrepo.git"); + + cl_git_pass(git_remote_new(&remote, repo, git_buf_cstr(&file_path_buf), NULL)); + cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH)); +} + +void test_network_remotelocal__cleanup(void) +{ + git_remote_free(remote); + git_buf_free(&file_path_buf); + git_repository_free(repo); + cl_fixture_cleanup("remotelocal"); +} + +static int count_ref__cb(git_remote_head *head, void *payload) +{ + int *count = (int *)payload; + + (*count)++; + + return GIT_SUCCESS; +} + +void test_network_remotelocal__retrieve_advertised_references(void) +{ + int how_many_refs = 0; + + cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs)); + + cl_assert(how_many_refs == 12); /* 1 HEAD + 9 refs + 2 peeled tags */ +}