Commit 359dce72 by Carlos Martín Nieto

remote: make _ls return the list directly

The callback-based method of listing remote references dates back to the
beginning of the network code's lifetime, when we didn't know any
better.

We need to keep the list around for update_tips() after disconnect() so
let's make use of this to simply give the user a pointer to the array so
they can write straightforward code instead of having to go through a
callback.
parent 266af6d8
...@@ -4,21 +4,12 @@ ...@@ -4,21 +4,12 @@
#include <string.h> #include <string.h>
#include "common.h" #include "common.h"
/** Callback to show each item */
static int show_ref__cb(git_remote_head *head, void *payload)
{
char oid[GIT_OID_HEXSZ + 1] = {0};
(void)payload;
git_oid_fmt(oid, &head->oid);
printf("%s\t%s\n", oid, head->name);
return 0;
}
static int use_remote(git_repository *repo, char *name) static int use_remote(git_repository *repo, char *name)
{ {
git_remote *remote = NULL; git_remote *remote = NULL;
int error; int error;
const git_remote_head **refs;
size_t refs_len, i;
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
// Find the remote by name // Find the remote by name
...@@ -40,7 +31,18 @@ static int use_remote(git_repository *repo, char *name) ...@@ -40,7 +31,18 @@ static int use_remote(git_repository *repo, char *name)
if (error < 0) if (error < 0)
goto cleanup; goto cleanup;
error = git_remote_ls(remote, &show_ref__cb, NULL); /**
* Get the list of references on the remote and print out
* their name next to what they point to.
*/
if (git_remote_ls(&refs, &refs_len, remote) < 0)
goto cleanup;
for (i = 0; i < refs_len; i++) {
char oid[GIT_OID_HEXSZ + 1] = {0};
git_oid_fmt(oid, &refs[i]->oid);
printf("%s\t%s\n", oid, refs[i]->name);
}
cleanup: cleanup:
git_remote_free(remote); git_remote_free(remote);
......
...@@ -254,15 +254,16 @@ GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction); ...@@ -254,15 +254,16 @@ GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction);
* The remote (or more exactly its transport) must be connected. The * The remote (or more exactly its transport) must be connected. The
* memory belongs to the remote. * memory belongs to the remote.
* *
* If you a return a non-zero value from the callback, this will stop * The array will stay valid as long as the remote object exists and
* looping over the refs. * its transport isn't changed, but a copy is recommended for usage of
* the data.
* *
* @param out pointer to the array
* @param size the number of remote heads
* @param remote the remote * @param remote the remote
* @param list_cb function to call with each ref discovered at the remote * @return 0 on success, or an error code
* @param payload additional data to pass to the callback
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
*/ */
GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload); GIT_EXTERN(int) git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote);
/** /**
* Download and index the packfile * Download and index the packfile
......
...@@ -203,13 +203,13 @@ struct git_transport { ...@@ -203,13 +203,13 @@ struct git_transport {
int direction, int direction,
int flags); int flags);
/* This function may be called after a successful call to connect(). The /* This function may be called after a successful call to
* provided callback is invoked for each ref discovered on the remote * connect(). The array returned is owned by the transport and
* end. */ * is guranteed until the next call of a transport function. */
int (*ls)( int (*ls)(
git_transport *transport, const git_remote_head ***out,
git_headlist_cb list_cb, size_t *size,
void *payload); git_transport *transport);
/* Executes the push whose context is in the git_push object. */ /* Executes the push whose context is in the git_push object. */
int (*push)(git_transport *transport, git_push *push); int (*push)(git_transport *transport, git_push *push);
......
...@@ -176,25 +176,20 @@ static int update_head_to_new_branch( ...@@ -176,25 +176,20 @@ static int update_head_to_new_branch(
return error; return error;
} }
static int get_head_callback(git_remote_head *head, void *payload)
{
git_remote_head **destination = (git_remote_head **)payload;
/* Save the first entry, and terminate the enumeration */
*destination = head;
return 1;
}
static int update_head_to_remote(git_repository *repo, git_remote *remote) static int update_head_to_remote(git_repository *repo, git_remote *remote)
{ {
int retcode = -1; int retcode = -1;
size_t refs_len;
git_refspec dummy_spec; git_refspec dummy_spec;
git_remote_head *remote_head; const git_remote_head *remote_head, **refs;
struct head_info head_info; struct head_info head_info;
git_buf remote_master_name = GIT_BUF_INIT; git_buf remote_master_name = GIT_BUF_INIT;
if (git_remote_ls(&refs, &refs_len, remote) < 0)
return -1;
/* Did we just clone an empty repository? */ /* Did we just clone an empty repository? */
if (remote->refs.length == 0) { if (refs_len == 0) {
return setup_tracking_config( return setup_tracking_config(
repo, repo,
"master", "master",
...@@ -202,12 +197,8 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) ...@@ -202,12 +197,8 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
GIT_REFS_HEADS_MASTER_FILE); GIT_REFS_HEADS_MASTER_FILE);
} }
/* Get the remote's HEAD. This is always the first ref in remote->refs. */ /* Get the remote's HEAD. This is always the first ref in the list. */
remote_head = NULL; remote_head = refs[0];
if (!remote->transport->ls(remote->transport, get_head_callback, &remote_head))
return -1;
assert(remote_head); assert(remote_head);
git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid); git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid);
......
...@@ -19,52 +19,47 @@ ...@@ -19,52 +19,47 @@
#include "repository.h" #include "repository.h"
#include "refs.h" #include "refs.h"
struct filter_payload { static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, git_refspec *tagspec)
git_remote *remote;
const git_refspec *spec, *tagspec;
git_odb *odb;
};
static int filter_ref__cb(git_remote_head *head, void *payload)
{ {
struct filter_payload *p = payload;
int match = 0; int match = 0;
if (!git_reference_is_valid_name(head->name)) if (!git_reference_is_valid_name(head->name))
return 0; return 0;
if (p->remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
/* /*
* If tagopt is --tags, then we only use the default * If tagopt is --tags, then we only use the default
* tags refspec and ignore the remote's * tags refspec and ignore the remote's
*/ */
if (git_refspec_src_matches(p->tagspec, head->name)) if (git_refspec_src_matches(tagspec, head->name))
match = 1; match = 1;
else else
return 0; return 0;
} else if (git_remote__matching_refspec(p->remote, head->name)) } else if (git_remote__matching_refspec(remote, head->name))
match = 1; match = 1;
if (!match) if (!match)
return 0; return 0;
/* If we have the object, mark it so we don't ask for it */ /* If we have the object, mark it so we don't ask for it */
if (git_odb_exists(p->odb, &head->oid)) if (git_odb_exists(odb, &head->oid))
head->local = 1; head->local = 1;
else else
p->remote->need_pack = 1; remote->need_pack = 1;
return git_vector_insert(&p->remote->refs, head); return git_vector_insert(&remote->refs, head);
} }
static int filter_wants(git_remote *remote) static int filter_wants(git_remote *remote)
{ {
struct filter_payload p; git_remote_head **heads;
git_refspec tagspec, head; git_refspec tagspec, head;
int error = -1; int error = 0;
git_odb *odb;
size_t i, heads_len;
//git_vector_clear(&remote->refs); git_vector_clear(&remote->refs);
if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) if ((error = git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true)) < 0)
return error; return error;
/* /*
...@@ -73,8 +68,6 @@ static int filter_wants(git_remote *remote) ...@@ -73,8 +68,6 @@ static int filter_wants(git_remote *remote)
* not interested in any particular branch but just the remote's * not interested in any particular branch but just the remote's
* HEAD, which will be stored in FETCH_HEAD after the fetch. * HEAD, which will be stored in FETCH_HEAD after the fetch.
*/ */
p.tagspec = &tagspec;
p.remote = remote;
if (remote->active_refspecs.length == 0) { if (remote->active_refspecs.length == 0) {
if ((error = git_refspec__parse(&head, "HEAD", true)) < 0) if ((error = git_refspec__parse(&head, "HEAD", true)) < 0)
goto cleanup; goto cleanup;
...@@ -83,12 +76,16 @@ static int filter_wants(git_remote *remote) ...@@ -83,12 +76,16 @@ static int filter_wants(git_remote *remote)
goto cleanup; goto cleanup;
} }
git_vector_clear(&remote->refs); if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
goto cleanup;
if (git_repository_odb__weakptr(&p.odb, remote->repo) < 0) if (git_remote_ls((const git_remote_head ***)&heads, &heads_len, remote) < 0)
goto cleanup; goto cleanup;
error = git_remote_ls(remote, filter_ref__cb, &p); for (i = 0; i < heads_len; i++) {
if ((error = maybe_want(remote, heads[i], odb, &tagspec)) < 0)
break;
}
cleanup: cleanup:
git_refspec__free(&tagspec); git_refspec__free(&tagspec);
......
...@@ -616,16 +616,22 @@ on_error: ...@@ -616,16 +616,22 @@ on_error:
return error; return error;
} }
static int cb_filter_refs(git_remote_head *ref, void *data)
{
git_remote *remote = (git_remote *) data;
return git_vector_insert(&remote->refs, ref);
}
static int filter_refs(git_remote *remote) static int filter_refs(git_remote *remote)
{ {
const git_remote_head **heads;
size_t heads_len, i;
git_vector_clear(&remote->refs); git_vector_clear(&remote->refs);
return git_remote_ls(remote, cb_filter_refs, remote);
if (git_remote_ls(&heads, &heads_len, remote) < 0)
return -1;
for (i = 0; i < heads_len; i++) {
if (git_vector_insert(&remote->refs, heads[i]) < 0)
return -1;
}
return 0;
} }
int git_push_finish(git_push *push) int git_push_finish(git_push *push)
......
...@@ -620,11 +620,11 @@ on_error: ...@@ -620,11 +620,11 @@ on_error:
return -1; return -1;
} }
int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload) int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote)
{ {
assert(remote); assert(remote);
return remote->transport->ls(remote->transport, list_cb, payload); return remote->transport->ls(out, size, remote->transport);
} }
int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url) int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url)
...@@ -684,13 +684,6 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur ...@@ -684,13 +684,6 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur
return 0; return 0;
} }
static int store_refs(git_remote_head *head, void *payload)
{
git_vector *refs = (git_vector *)payload;
return git_vector_insert(refs, head);
}
/* DWIM `refspecs` based on `refs` and append the output to `out` */ /* DWIM `refspecs` based on `refs` and append the output to `out` */
static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs) static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs)
{ {
...@@ -736,15 +729,12 @@ int git_remote_download(git_remote *remote) ...@@ -736,15 +729,12 @@ int git_remote_download(git_remote *remote)
if (git_vector_init(&refs, 8, remote_head_cmp) < 0) if (git_vector_init(&refs, 8, remote_head_cmp) < 0)
return -1; return -1;
if (git_remote_ls(remote, store_refs, &refs) < 0) { if (git_remote_ls((const git_remote_head ***)&refs.contents, &refs.length, remote) < 0)
return -1; return -1;
}
free_refspecs(&remote->active_refspecs); free_refspecs(&remote->active_refspecs);
error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs); if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs) < 0)
git_vector_free(&refs);
if (error < 0)
return -1; return -1;
if ((error = git_fetch_negotiate(remote)) < 0) if ((error = git_fetch_negotiate(remote)) < 0)
...@@ -996,7 +986,7 @@ int git_remote_update_tips(git_remote *remote) ...@@ -996,7 +986,7 @@ int git_remote_update_tips(git_remote *remote)
if (git_vector_init(&refs, 16, NULL) < 0) if (git_vector_init(&refs, 16, NULL) < 0)
return -1; return -1;
if ((error = git_remote_ls(remote, store_refs, &refs)) < 0) if ((error = git_remote_ls((const git_remote_head ***)&refs.contents, &refs.length, remote)) < 0)
goto out; goto out;
if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
...@@ -1014,7 +1004,6 @@ int git_remote_update_tips(git_remote *remote) ...@@ -1014,7 +1004,6 @@ int git_remote_update_tips(git_remote *remote)
out: out:
git_refspec__free(&tagspec); git_refspec__free(&tagspec);
git_vector_free(&refs);
return error; return error;
} }
......
...@@ -213,21 +213,17 @@ static int local_connect( ...@@ -213,21 +213,17 @@ static int local_connect(
return 0; return 0;
} }
static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *payload) static int local_ls(const git_remote_head ***out, size_t *size, git_transport *transport)
{ {
transport_local *t = (transport_local *)transport; transport_local *t = (transport_local *)transport;
unsigned int i;
git_remote_head *head = NULL;
if (!t->have_refs) { if (!t->have_refs) {
giterr_set(GITERR_NET, "The transport has not yet loaded the refs"); giterr_set(GITERR_NET, "The transport has not yet loaded the refs");
return -1; return -1;
} }
git_vector_foreach(&t->refs, i, head) { *out = (const git_remote_head **) t->refs.contents;
if (list_cb(head, payload)) *size = t->refs.length;
return GIT_EUSER;
}
return 0; return 0;
} }
......
...@@ -74,6 +74,7 @@ static int git_smart__connect( ...@@ -74,6 +74,7 @@ static int git_smart__connect(
transport_smart *t = (transport_smart *)transport; transport_smart *t = (transport_smart *)transport;
git_smart_subtransport_stream *stream; git_smart_subtransport_stream *stream;
int error; int error;
size_t i;
git_pkt *pkt; git_pkt *pkt;
git_pkt_ref *first; git_pkt_ref *first;
git_smart_service_t service; git_smart_service_t service;
...@@ -140,6 +141,16 @@ static int git_smart__connect( ...@@ -140,6 +141,16 @@ static int git_smart__connect(
git_pkt_free((git_pkt *)first); git_pkt_free((git_pkt *)first);
} }
/* Keep a list of heads for _ls */
git_vector_foreach(&t->refs, i, pkt) {
git_pkt_ref *ref = (git_pkt_ref *) pkt;
if (pkt->type != GIT_PKT_REF)
continue;
if (git_vector_insert(&t->heads, &ref->head) < 0)
return -1;
}
if (t->rpc && git_smart__reset_stream(t, false) < 0) if (t->rpc && git_smart__reset_stream(t, false) < 0)
return -1; return -1;
...@@ -149,28 +160,17 @@ static int git_smart__connect( ...@@ -149,28 +160,17 @@ static int git_smart__connect(
return 0; return 0;
} }
static int git_smart__ls(git_transport *transport, git_headlist_cb list_cb, void *payload) static int git_smart__ls(const git_remote_head ***out, size_t *size, git_transport *transport)
{ {
transport_smart *t = (transport_smart *)transport; transport_smart *t = (transport_smart *)transport;
unsigned int i;
git_pkt *p = NULL;
if (!t->have_refs) { if (!t->have_refs) {
giterr_set(GITERR_NET, "The transport has not yet loaded the refs"); giterr_set(GITERR_NET, "The transport has not yet loaded the refs");
return -1; return -1;
} }
git_vector_foreach(&t->refs, i, p) { *out = (const git_remote_head **) t->heads.contents;
git_pkt_ref *pkt = NULL; *size = t->heads.length;
if (p->type != GIT_PKT_REF)
continue;
pkt = (git_pkt_ref *)p;
if (list_cb(&pkt->head, payload))
return GIT_EUSER;
}
return 0; return 0;
} }
...@@ -293,6 +293,7 @@ static void git_smart__free(git_transport *transport) ...@@ -293,6 +293,7 @@ static void git_smart__free(git_transport *transport)
/* Free the subtransport */ /* Free the subtransport */
t->wrapped->free(t->wrapped); t->wrapped->free(t->wrapped);
git_vector_free(&t->heads);
git_vector_foreach(refs, i, p) git_vector_foreach(refs, i, p)
git_pkt_free(p); git_pkt_free(p);
...@@ -340,6 +341,11 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) ...@@ -340,6 +341,11 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
return -1; return -1;
} }
if (git_vector_init(&t->heads, 16, ref_name_cmp) < 0) {
git__free(t);
return -1;
}
if (definition->callback(&t->wrapped, &t->parent) < 0) { if (definition->callback(&t->wrapped, &t->parent) < 0) {
git__free(t); git__free(t);
return -1; return -1;
......
...@@ -140,6 +140,7 @@ typedef struct { ...@@ -140,6 +140,7 @@ typedef struct {
git_smart_subtransport_stream *current_stream; git_smart_subtransport_stream *current_stream;
transport_smart_caps caps; transport_smart_caps caps;
git_vector refs; git_vector refs;
git_vector heads;
git_vector common; git_vector common;
git_atomic cancelled; git_atomic cancelled;
packetsize_cb packetsize_cb; packetsize_cb packetsize_cb;
......
...@@ -32,6 +32,7 @@ int git_smart__store_refs(transport_smart *t, int flushes) ...@@ -32,6 +32,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
/* Clear existing refs in case git_remote_connect() is called again /* Clear existing refs in case git_remote_connect() is called again
* after git_remote_disconnect(). * after git_remote_disconnect().
*/ */
git_vector_clear(&t->heads);
git_vector_foreach(refs, i, ref) { git_vector_foreach(refs, i, ref) {
git__free(ref->head.name); git__free(ref->head.name);
git__free(ref); git__free(ref);
......
...@@ -26,26 +26,6 @@ void test_network_remote_local__cleanup(void) ...@@ -26,26 +26,6 @@ void test_network_remote_local__cleanup(void)
cl_fixture_cleanup("remotelocal"); cl_fixture_cleanup("remotelocal");
} }
static int count_ref__cb(git_remote_head *head, void *payload)
{
int *count = (int *)payload;
(void)head;
(*count)++;
return 0;
}
static int ensure_peeled__cb(git_remote_head *head, void *payload)
{
GIT_UNUSED(payload);
if(strcmp(head->name, "refs/tags/test^{}") != 0)
return 0;
return git_oid_streq(&head->oid, "e90810b8df3e80c413d903f631643c716887138d");
}
static void connect_to_local_repository(const char *local_repository) static void connect_to_local_repository(const char *local_repository)
{ {
git_buf_sets(&file_path_buf, cl_git_path_url(local_repository)); git_buf_sets(&file_path_buf, cl_git_path_url(local_repository));
...@@ -65,39 +45,42 @@ void test_network_remote_local__connected(void) ...@@ -65,39 +45,42 @@ void test_network_remote_local__connected(void)
void test_network_remote_local__retrieve_advertised_references(void) void test_network_remote_local__retrieve_advertised_references(void)
{ {
int how_many_refs = 0; const git_remote_head **refs;
size_t refs_len;
connect_to_local_repository(cl_fixture("testrepo.git")); connect_to_local_repository(cl_fixture("testrepo.git"));
cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs)); cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
cl_assert_equal_i(how_many_refs, 28); cl_assert_equal_i(refs_len, 28);
} }
void test_network_remote_local__retrieve_advertised_references_after_disconnect(void) void test_network_remote_local__retrieve_advertised_references_after_disconnect(void)
{ {
int how_many_refs = 0; const git_remote_head **refs;
size_t refs_len;
connect_to_local_repository(cl_fixture("testrepo.git")); connect_to_local_repository(cl_fixture("testrepo.git"));
git_remote_disconnect(remote); git_remote_disconnect(remote);
cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs)); cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
cl_assert_equal_i(how_many_refs, 28); cl_assert_equal_i(refs_len, 28);
} }
void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void) void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void)
{ {
int how_many_refs = 0; const git_remote_head **refs;
size_t refs_len;
cl_fixture_sandbox("testrepo.git"); cl_fixture_sandbox("testrepo.git");
cl_git_pass(p_rename("testrepo.git", "spaced testrepo.git")); cl_git_pass(p_rename("testrepo.git", "spaced testrepo.git"));
connect_to_local_repository("spaced testrepo.git"); connect_to_local_repository("spaced testrepo.git");
cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs)); cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
cl_assert_equal_i(how_many_refs, 28); cl_assert_equal_i(refs_len, 28);
git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */ git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */
remote = NULL; remote = NULL;
...@@ -107,9 +90,17 @@ void test_network_remote_local__retrieve_advertised_references_from_spaced_repos ...@@ -107,9 +90,17 @@ void test_network_remote_local__retrieve_advertised_references_from_spaced_repos
void test_network_remote_local__nested_tags_are_completely_peeled(void) void test_network_remote_local__nested_tags_are_completely_peeled(void)
{ {
const git_remote_head **refs;
size_t refs_len, i;
connect_to_local_repository(cl_fixture("testrepo.git")); connect_to_local_repository(cl_fixture("testrepo.git"));
cl_git_pass(git_remote_ls(remote, &ensure_peeled__cb, NULL)); cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
for (i = 0; i < refs_len; i++) {
if (!strcmp(refs[i]->name, "refs/tags/test^{}"))
cl_git_pass(git_oid_streq(&refs[i]->oid, "e90810b8df3e80c413d903f631643c716887138d"));
}
} }
void test_network_remote_local__shorthand_fetch_refspec0(void) void test_network_remote_local__shorthand_fetch_refspec0(void)
......
...@@ -152,29 +152,20 @@ void test_online_fetch__can_cancel(void) ...@@ -152,29 +152,20 @@ void test_online_fetch__can_cancel(void)
git_remote_free(remote); git_remote_free(remote);
} }
int ls_cb(git_remote_head *rhead, void *payload)
{
int *nr = payload;
GIT_UNUSED(rhead);
(*nr)++;
return 0;
}
void test_online_fetch__ls_disconnected(void) void test_online_fetch__ls_disconnected(void)
{ {
const git_remote_head **refs;
size_t refs_len_before, refs_len_after;
git_remote *remote; git_remote *remote;
int nr_before = 0, nr_after = 0;
cl_git_pass(git_remote_create(&remote, _repo, "test", cl_git_pass(git_remote_create(&remote, _repo, "test",
"http://github.com/libgit2/TestGitRepository.git")); "http://github.com/libgit2/TestGitRepository.git"));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
cl_git_pass(git_remote_ls(remote, ls_cb, &nr_before)); cl_git_pass(git_remote_ls(&refs, &refs_len_before, remote));
git_remote_disconnect(remote); git_remote_disconnect(remote);
cl_git_pass(git_remote_ls(remote, ls_cb, &nr_after)); cl_git_pass(git_remote_ls(&refs, &refs_len_after, remote));
cl_assert_equal_i(nr_before, nr_after); cl_assert_equal_i(refs_len_before, refs_len_after);
git_remote_free(remote); git_remote_free(remote);
} }
...@@ -155,10 +155,11 @@ static void do_verify_push_status(git_push *push, const push_status expected[], ...@@ -155,10 +155,11 @@ static void do_verify_push_status(git_push *push, const push_status expected[],
*/ */
static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len)
{ {
git_vector actual_refs = GIT_VECTOR_INIT; const git_remote_head **actual_refs;
size_t actual_refs_len;
git_remote_ls(remote, record_ref_cb, &actual_refs); git_remote_ls(&actual_refs, &actual_refs_len, remote);
verify_remote_refs(&actual_refs, expected_refs, expected_refs_len); verify_remote_refs(actual_refs, actual_refs_len, expected_refs, expected_refs_len);
git_vector_free(&actual_refs); git_vector_free(&actual_refs);
} }
......
...@@ -69,26 +69,28 @@ int record_ref_cb(git_remote_head *head, void *payload) ...@@ -69,26 +69,28 @@ int record_ref_cb(git_remote_head *head, void *payload)
return git_vector_insert(refs, head); return git_vector_insert(refs, head);
} }
void verify_remote_refs(git_vector *actual_refs, const expected_ref expected_refs[], size_t expected_refs_len) void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len)
{ {
size_t i, j = 0; size_t i, j = 0;
git_buf msg = GIT_BUF_INIT; git_buf msg = GIT_BUF_INIT;
git_remote_head *actual; const git_remote_head *actual;
char *oid_str; char *oid_str;
bool master_present = false; bool master_present = false;
/* We don't care whether "master" is present on the other end or not */ /* We don't care whether "master" is present on the other end or not */
git_vector_foreach(actual_refs, i, actual) { for (i = 0; i < actual_refs_len; i++) {
actual = actual_refs[i];
if (!strcmp(actual->name, "refs/heads/master")) { if (!strcmp(actual->name, "refs/heads/master")) {
master_present = true; master_present = true;
break; break;
} }
} }
if (expected_refs_len + (master_present ? 1 : 0) != actual_refs->length) if (expected_refs_len + (master_present ? 1 : 0) != actual_refs_len)
goto failed; goto failed;
git_vector_foreach(actual_refs, i, actual) { for (i = 0; i < actual_refs_len; i++) {
actual = actual_refs[i];
if (master_present && !strcmp(actual->name, "refs/heads/master")) if (master_present && !strcmp(actual->name, "refs/heads/master"))
continue; continue;
...@@ -111,7 +113,8 @@ failed: ...@@ -111,7 +113,8 @@ failed:
} }
git_buf_puts(&msg, "\nACTUAL:\n"); git_buf_puts(&msg, "\nACTUAL:\n");
git_vector_foreach(actual_refs, i, actual) { for (i = 0; i < actual_refs_len; i++) {
actual = actual_refs[i];
if (master_present && !strcmp(actual->name, "refs/heads/master")) if (master_present && !strcmp(actual->name, "refs/heads/master"))
continue; continue;
......
...@@ -60,10 +60,11 @@ int record_ref_cb(git_remote_head *head, void *payload); ...@@ -60,10 +60,11 @@ int record_ref_cb(git_remote_head *head, void *payload);
* Verifies that refs on remote stored by record_ref_cb match the expected * Verifies that refs on remote stored by record_ref_cb match the expected
* names, oids, and order. * names, oids, and order.
* *
* @param actual_refs actual refs stored by record_ref_cb() * @param actual_refs actual refs in the remote
* @param actual_refs_len length of actual_refs
* @param expected_refs expected remote refs * @param expected_refs expected remote refs
* @param expected_refs_len length of expected_refs * @param expected_refs_len length of expected_refs
*/ */
void verify_remote_refs(git_vector *actual_refs, const expected_ref expected_refs[], size_t expected_refs_len); void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len);
#endif /* INCLUDE_cl_push_util_h__ */ #endif /* INCLUDE_cl_push_util_h__ */
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