summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <carlos@cmartin.tk>2011-07-31 01:16:47 +0200
committerVicent Marti <tanoku@gmail.com>2011-08-18 02:34:07 +0200
commit7e1a94db11f38c87ae224821a8c570ffa1e11270 (patch)
tree2fef468cec5cff2e738c33078cad52ad58245fba
parentb4c9063040efdc2bbb2d32704234e0d9c2159b4e (diff)
downloadlibgit2-7e1a94db11f38c87ae224821a8c570ffa1e11270.tar.gz
Move have sending
Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
-rw-r--r--src/fetch.c57
-rw-r--r--src/pkt.c103
-rw-r--r--src/pkt.h19
-rw-r--r--src/transport.c8
-rw-r--r--src/transport.h4
-rw-r--r--src/transport_git.c14
6 files changed, 129 insertions, 76 deletions
diff --git a/src/fetch.c b/src/fetch.c
index c799c805f..61bcc1542 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -51,7 +51,7 @@ static int whn_cmp(const void *a, const void *b)
int git_fetch_list_want(git_headarray *whn_list, git_repository *repo, git_remote *remote)
{
git_vector list;
- git_headarray refs, lrefs;
+ git_headarray refs;
git_transport *t = remote->transport;
const git_refspec *spec;
int error;
@@ -159,31 +159,49 @@ int git_fetch_negotiate(git_headarray *list, git_repository *repo, git_remote *r
unsigned int i;
char local[1024];
git_refspec *spec;
+ git_reference *ref;
+ git_strarray refs;
+ git_oid oid;
- error = git_revwalk_new(&walk, repo);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to create walker");
+ /*
+ * Now we have everything set up so we can start tell the server
+ * what we want and what we have.
+ */
+ git_transport_send_wants(remote->transport, list);
- for (i = 0; i < list->len; ++i) {
- git_reference *ref;
- git_remote_head *head = list->heads[i];
+ error = git_reference_listall(&refs, repo, GIT_REF_LISTALL);
+ if (error < GIT_ERROR)
+ return git__rethrow(error, "Failed to list all references");
- if (!head->local)
- continue;
+ error = git_revwalk_new(&walk, repo);
+ if (error < GIT_ERROR) {
+ error = git__rethrow(error, "Failed to list all references");
+ goto cleanup;
+ }
- error = git_revwalk_push(walk, &head->loid);
- if (error < GIT_SUCCESS) {
- error = git__rethrow(error, "Failed to push a local OID");
+ for (i = 0; i < refs.count; ++i) {
+ error = git_reference_lookup(&ref, repo, refs.strings[i]);
+ if (error < GIT_ERROR) {
+ error = git__rethrow(error, "Failed to lookup %s", refs.strings[i]);
+ goto cleanup;
+ }
+
+ error = git_revwalk_push(walk, git_reference_oid(ref));
+ if (error < GIT_ERROR) {
+ error = git__rethrow(error, "Failed to push %s", refs.strings[i]);
goto cleanup;
}
}
+ git_strarray_free(&refs);
- /*
- * Now we have everything set up so we can start tell the server
- * what we want and what we have.
- */
- git_transport_send_wants(remote->transport, list);
- git_transport_send_haves(remote->transport, repo);
+ while ((error = git_revwalk_next(&oid, walk)) == GIT_SUCCESS) {
+ git_transport_send_have(remote->transport, &oid);
+ }
+ if (error == GIT_EREVWALKOVER)
+ error = GIT_SUCCESS;
+
+ /* TODO: git_pkt_send_flush(fd), or git_transport_flush() */
+ printf("Wound send 0000\n");
cleanup:
git_revwalk_free(walk);
@@ -192,5 +210,8 @@ cleanup:
int git_fetch_download_pack(git_remote *remote)
{
+ /*
+ * First, we ignore any ACKs we receive and wait for a NACK
+ */
return GIT_ENOTIMPLEMENTED;
}
diff --git a/src/pkt.c b/src/pkt.c
index fbb5dfb0a..61c011c6c 100644
--- a/src/pkt.c
+++ b/src/pkt.c
@@ -52,10 +52,38 @@ static int flush_pkt(git_pkt **out)
return GIT_SUCCESS;
}
+static int ack_pkt(git_pkt **out, const char *line, size_t len)
+{
+ git_pkt *pkt;
+
+ pkt = git__malloc(sizeof(git_pkt));
+ if (pkt == NULL)
+ return GIT_ENOMEM;
+
+ pkt->type = GIT_PKT_ACK;
+ *out = pkt;
+
+ return GIT_SUCCESS;
+}
+
+static int nack_pkt(git_pkt **out)
+{
+ git_pkt *pkt;
+
+ pkt = git__malloc(sizeof(git_pkt));
+ if (pkt == NULL)
+ return GIT_ENOMEM;
+
+ pkt->type = GIT_PKT_NACK;
+ *out = pkt;
+
+ return GIT_SUCCESS;
+}
+
/*
* Parse an other-ref line.
*/
-int ref_pkt(git_pkt **out, const char *line, size_t len)
+static int ref_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_ref *pkt;
int error, has_caps = 0;
@@ -185,11 +213,14 @@ int git_pkt_parse_line(git_pkt **head, const char *line, const char **out, size_
len -= PKT_LEN_SIZE; /* the encoded length includes its own size */
- /*
- * For now, we're just going to assume we're parsing references
- */
+ /* Assming the minimal size is actually 4 */
+ if (!git__prefixcmp(line, "ACK"))
+ error = ack_pkt(head, line, len);
+ else if (!git__prefixcmp(line, "NACK"))
+ error = nack_pkt(head);
+ else
+ error = ref_pkt(head, line, len);
- error = ref_pkt(head, line, len);
*out = line + len;
return error;
@@ -239,62 +270,32 @@ int git_pkt_send_wants(git_headarray *refs, int fd)
}
/* TODO: git_pkt_send_flush(fd) */
- printf("Wound send 0000\n");
+ printf("Would send 0000\n");
return ret;
}
+/*
+ * TODO: this should be a more generic function, maybe to be used by
+ * git_pkt_send_wants, as it's not performance-critical
+ */
#define HAVE_PREFIX "0032have "
-int git_pkt_send_haves(git_repository *repo, int fd)
+int git_pkt_send_have(git_oid *oid, int fd)
{
- unsigned int i;
int ret = GIT_SUCCESS;
- char buf[STRLEN(HAVE_PREFIX) + GIT_OID_HEXSZ + 2];
- git_oid oid;
- git_revwalk *walk;
- git_strarray refs;
- git_reference *ref;
- git_remote_head *head;
-
- memcpy(buf, HAVE_PREFIX, STRLEN(HAVE_PREFIX));
- buf[sizeof(buf) - 2] = '\n';
- buf[sizeof(buf) - 1] = '\0';
+ char buf[] = "0032have 0000000000000000000000000000000000000000\n";
- ret = git_reference_listall(&refs, repo, GIT_REF_LISTALL);
- if (ret < GIT_ERROR)
- return git__rethrow(ret, "Failed to list all references");
+ git_oid_fmt(buf + STRLEN(HAVE_PREFIX), oid);
+ printf("would send %s", buf);
- ret = git_revwalk_new(&walk, repo);
- if (ret < GIT_ERROR) {
- ret = git__rethrow(ret, "Failed to list all references");
- goto cleanup;
- }
-
- for (i = 0; i < refs.count; ++i) {
- ret = git_reference_lookup(&ref, repo, refs.strings[i]);
- if (ret < GIT_ERROR) {
- ret = git__rethrow(ret, "Failed to lookup %s", refs.strings[i]);
- goto cleanup;
- }
-
- ret = git_revwalk_push(walk, git_reference_oid(ref));
- if (ret < GIT_ERROR) {
- ret = git__rethrow(ret, "Failed to push %s", refs.strings[i]);
- goto cleanup;
- }
- }
-
- while ((ret = git_revwalk_next(&oid, walk)) == GIT_SUCCESS) {
- git_oid_fmt(buf + STRLEN(HAVE_PREFIX), &oid);
- printf("would send %s", buf);
- }
+ return ret;
+}
- /* TODO: git_pkt_send_flush(fd) */
- printf("Wound send 0000\n");
+int git_pkt_send_have(int fd)
+{
+ char buf[] = "0009done\n";
+ printf("Would send %s", buf);
-cleanup:
- git_revwalk_free(walk);
- git_strarray_free(&refs);
- return ret;
+ return GIT_SUCCESS;
}
diff --git a/src/pkt.h b/src/pkt.h
index 43407037c..b5d2a17da 100644
--- a/src/pkt.h
+++ b/src/pkt.h
@@ -34,6 +34,16 @@ enum git_pkt_type {
GIT_PKT_FLUSH,
GIT_PKT_REF,
GIT_PKT_HAVE,
+ GIT_PKT_ACK,
+ GIT_PKT_NACK,
+};
+
+/* Used for multi-ack */
+enum git_ack_status {
+ GIT_ACK_NONE,
+ GIT_ACK_CONTINUE,
+ GIT_ACK_COMMON,
+ GIT_ACK_READY
};
/* This would be a flush pkt */
@@ -55,10 +65,17 @@ typedef struct {
char *capabilities;
} git_pkt_ref;
+/* Useful later */
+typedef struct {
+ enum git_pkt_type type;
+ git_oid oid;
+ enum git_ack_status status;
+} git_pkt_ack;
+
int git_pkt_parse_line(git_pkt **head, const char *line, const char **out, size_t len);
int git_pkt_send_flush(int s);
-int git_pkt_send_haves(git_repository *repo, int fd);
int git_pkt_send_wants(git_headarray *refs, int fd);
+int git_pkt_send_have(git_oid *oid, int fd);
void git_pkt_free(git_pkt *pkt);
#endif
diff --git a/src/transport.c b/src/transport.c
index 53caf9e1b..6098989a8 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -85,11 +85,15 @@ int git_transport_send_wants(struct git_transport *transport, git_headarray *arr
return transport->send_wants(transport, array);
}
-int git_transport_send_haves(struct git_transport *transport, git_repository *repo)
+int git_transport_send_have(struct git_transport *transport, git_oid *oid)
{
- return transport->send_haves(transport, repo);
+ return transport->send_have(transport, oid);
}
+int git_transport_send_done(struct git_transport *transport)
+{
+ return transport->send_done(transport);
+}
int git_transport_close(git_transport *transport)
{
return transport->close(transport);
diff --git a/src/transport.h b/src/transport.h
index 6e3501b99..097b9ac0a 100644
--- a/src/transport.h
+++ b/src/transport.h
@@ -63,7 +63,7 @@ struct git_transport {
/**
* Send the list of 'have' refs
*/
- int (*send_haves)(struct git_transport *transport, git_repository *repo);
+ int (*send_have)(struct git_transport *transport, git_oid *oid);
/**
* Fetch the changes
*/
@@ -83,5 +83,7 @@ int git_transport_git(struct git_transport **transport);
int git_transport_dummy(struct git_transport **transport);
int git_transport_send_wants(struct git_transport *transport, git_headarray *array);
+int git_transport_send_have(struct git_transport *transport, git_oid *oid);
+int git_transport_send_done(struct git_transport *transport);
#endif
diff --git a/src/transport_git.c b/src/transport_git.c
index 0453ca0fd..4b183ed52 100644
--- a/src/transport_git.c
+++ b/src/transport_git.c
@@ -281,11 +281,18 @@ static int git_send_wants(git_transport *transport, git_headarray *array)
return git_pkt_send_wants(array, t->socket);
}
-static int git_send_haves(git_transport *transport, git_repository *repo)
+static int git_send_have(git_transport *transport, git_oid *oid)
{
transport_git *t = (transport_git *) transport;
- return git_pkt_send_haves(repo, t->socket);
+ return git_pkt_send_have(oid, t->socket);
+}
+
+static int git_send_done(git_transport *transport)
+{
+ transport_git *t = (transport_git *) transport;
+
+ return git_pkt_send_done(t->socket);
}
static int git_close(git_transport *transport)
@@ -333,7 +340,8 @@ int git_transport_git(git_transport **out)
t->parent.connect = git_connect;
t->parent.ls = git_ls;
t->parent.send_wants = git_send_wants;
- t->parent.send_haves = git_send_haves;
+ t->parent.send_have = git_send_have;
+ t->parent.send_done = git_send_done;
t->parent.close = git_close;
t->parent.free = git_free;