remote: add test to retrieve the advertised references from a local repository and fix related implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
diff --git a/src/transports/local.c b/src/transports/local.c
index 6cf0573..c433339 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 2102735..f580767 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 af9e088..d2c954e 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},
@@ -399,6 +402,12 @@ static const struct clay_suite _clay_suites[] = {
_clay_cb_index_rename, 1
},
{
+ "network::remotelocal",
+ {"initialize", &test_network_remotelocal__initialize},
+ {"cleanup", &test_network_remotelocal__cleanup},
+ _clay_cb_network_remotelocal, 1
+ },
+ {
"network::remotes",
{"initialize", &test_network_remotes__initialize},
{"cleanup", &test_network_remotes__cleanup},
@@ -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 0000000..7dad39a
--- /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 */
+}