diff options
author | Carlos Martín Nieto <carlos@cmartin.tk> | 2011-07-31 01:16:47 +0200 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2011-08-18 02:34:07 +0200 |
commit | 7e1a94db11f38c87ae224821a8c570ffa1e11270 (patch) | |
tree | 2fef468cec5cff2e738c33078cad52ad58245fba | |
parent | b4c9063040efdc2bbb2d32704234e0d9c2159b4e (diff) | |
download | libgit2-7e1a94db11f38c87ae224821a8c570ffa1e11270.tar.gz |
Move have sending
Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
-rw-r--r-- | src/fetch.c | 57 | ||||
-rw-r--r-- | src/pkt.c | 103 | ||||
-rw-r--r-- | src/pkt.h | 19 | ||||
-rw-r--r-- | src/transport.c | 8 | ||||
-rw-r--r-- | src/transport.h | 4 | ||||
-rw-r--r-- | src/transport_git.c | 14 |
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; } @@ -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; } @@ -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; |