local transport: sort the refs before resolving them By pre-sorting the references, they are already in the right order if we want to peel them. With this, we get output-parity with git.git's ls-remote. Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
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
diff --git a/src/transport_local.c b/src/transport_local.c
index 2cc78ca..0e9f71b 100644
--- a/src/transport_local.c
+++ b/src/transport_local.c
@@ -8,17 +8,12 @@
#include "refs.h"
#include "transport.h"
-typedef struct {
- git_vector *vec;
- git_repository *repo;
-} callback_data;
-
-static int compare_heads(const void *a, const void *b)
+static int cmp_refs(const void *a, const void *b)
{
- const git_remote_head *heada = *(const git_remote_head **)a;
- const git_remote_head *headb = *(const git_remote_head **)b;
+ const char *stra = *(const char **) a;
+ const char *strb = *(const char **) b;
- return strcmp(heada->name, headb->name);
+ return strcmp(stra, strb);
}
/*
@@ -50,11 +45,8 @@ static int local_connect(git_transport *transport, git_net_direction GIT_UNUSED(
return GIT_SUCCESS;
}
-static int heads_cb(const char *name, void *ptr)
+static int add_ref(const char *name, git_repository *repo, git_vector *vec)
{
- callback_data *data = ptr;
- git_vector *vec = data->vec;
- git_repository *repo = data->repo;
const char peeled[] = "^{}";
git_remote_head *head;
git_reference *ref;
@@ -125,27 +117,45 @@ static int heads_cb(const char *name, void *ptr)
static int local_ls(git_transport *transport, git_headarray *array)
{
int error;
+ unsigned int i;
git_repository *repo;
git_vector vec;
- callback_data data;
+ git_strarray refs;
assert(transport && transport->connected);
repo = transport->private;
- error = git_vector_init(&vec, 16, compare_heads);
+
+ error = git_reference_listall(&refs, repo, GIT_REF_LISTALL);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to list remote heads");
+
+ error = git_vector_init(&vec, refs.count, NULL);
if (error < GIT_SUCCESS)
return error;
- data.vec = &vec;
- data.repo = repo;
- error = git_reference_foreach(repo, GIT_REF_LISTALL, heads_cb, &data);
+ /* Sort the references first */
+ qsort(refs.strings, refs.count, sizeof(char *), cmp_refs);
+
+ /* Add HEAD */
+ error = add_ref(GIT_HEAD_FILE, repo, &vec);
if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to list remote heads");
+ goto out;
+
+ for (i = 0; i < refs.count; ++i) {
+ error = add_ref(refs.strings[i], repo, &vec);
+ if (error < GIT_SUCCESS)
+ goto out;
+ }
- git_vector_sort(&vec);
array->len = vec.length;
array->heads = (git_remote_head **) vec.contents;
+ out:
+ if (error < GIT_SUCCESS) {
+ git_strarray_free(&refs);
+ }
+
return error;
}