negotiation
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
diff --git a/include/git2/net.h b/include/git2/net.h
index ecf4f6c..c2260fc 100644
--- a/include/git2/net.h
+++ b/include/git2/net.h
@@ -59,7 +59,9 @@ enum git_whn {
*/
struct git_remote_head {
enum git_whn type;
+ int local; /** Exists locally */
git_oid oid;
+ git_oid loid;
char *name;
};
diff --git a/src/fetch.c b/src/fetch.c
index 21f52fc..b9ddaf1 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -26,6 +26,7 @@
#include "git2/remote.h"
#include "git2/oid.h"
#include "git2/refs.h"
+#include "git2/revwalk.h"
#include "common.h"
#include "transport.h"
@@ -50,9 +51,10 @@ int git_fetch_list_want(git_headarray *whn_list, git_repository *repo, git_remot
git_headarray refs, lrefs;
git_transport *t = remote->transport;
const git_refspec *spec;
- int error, i;
+ int error;
+ unsigned int i;
- error = git_vector_init(&list, 16, whn_cmp);
+ error = git_vector_init(&list, whn_list->len, whn_cmp);
if (error < GIT_SUCCESS)
return error;
@@ -99,11 +101,15 @@ int git_fetch_list_want(git_headarray *whn_list, git_repository *repo, git_remot
if (ref != NULL) {
if (!git_oid_cmp(&head->oid, git_reference_oid(ref)))
continue;
+
+ head->local = 1;
+ git_oid_cpy(&head->loid, git_reference_oid(ref));
}
/*
* Now we know we want to have that ref, so add it as a "want"
- * to the list.
+ * to the list, storing the local oid for that branch so we
+ * don't have to look for it again.
*/
head->type = GIT_WHN_WANT;
error = git_vector_insert(&list, head);
@@ -121,3 +127,67 @@ cleanup:
git_vector_free(&list);
return error;
}
+
+/* Push any (OID) ref it gets into the walker */
+static int push_stuff(const char *name, void *data)
+{
+ git_revwalk *walk = (git_revwalk *) data;
+ git_reference *ref;
+ git_repository *repo;
+ int error;
+
+ repo = git_revwalk_repository(walk);
+ error = git_reference_lookup(&ref, repo, name);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ return git_revwalk_push(walk, git_reference_oid(ref));
+}
+
+/*
+ * In this first version, we push all our refs in and start sending
+ * them out. When we get an ACK we hide that commit and continue
+ * traversing until we're done
+ */
+int git_fetch_negotiate(git_headarray *list, git_repository *repo, git_remote *remote)
+{
+ git_revwalk *walk;
+ int error;
+ unsigned int i;
+ char local[1024];
+ git_refspec *spec;
+
+ error = git_revwalk_new(&walk, repo);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to create walker");
+
+ for (i = 0; i < list->len; ++i) {
+ git_reference *ref;
+ git_remote_head *head = list->heads[i];
+
+ if (!head->local)
+ continue;
+
+ error = git_revwalk_push(walk, &head->loid);
+ if (error < GIT_SUCCESS) {
+ error = git__rethrow(error, "Failed to push a local OID");
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Now we have everything set up so we can start tell the server
+ * what we want and what we have.
+ */
+ git_pkt_send_wants(list);
+
+
+cleanup:
+ git_revwalk_free(walk);
+ return error;
+}
+
+int git_fetch_download_pack(git_remote *remote)
+{
+ return GIT_ENOTIMPLEMENTED;
+}
diff --git a/src/pkt.c b/src/pkt.c
index f75b833..06d1bc8 100644
--- a/src/pkt.c
+++ b/src/pkt.c
@@ -216,7 +216,7 @@ int git_pkt_send_flush(int s)
*/
#define WANT_PREFIX "0032want "
-int git_pkt_send_wants(git_headarray *refs)
+int git_pkt_send_wants(git_headarray *refs, int fd)
{
unsigned int i;
int ret = GIT_SUCCESS;