diff --git a/src/fetch.c b/src/fetch.c index 59beb1ea3..c799c805f 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -38,8 +38,8 @@ */ static int whn_cmp(const void *a, const void *b) { - git_remote_head *heada = *(git_remote_head **)(a); - git_remote_head *headb = *(git_remote_head **)(b); + git_remote_head *heada = (git_remote_head *) a; + git_remote_head *headb = (git_remote_head *) b; return headb->type - heada->type; } @@ -57,7 +57,7 @@ int git_fetch_list_want(git_headarray *whn_list, git_repository *repo, git_remot int error; unsigned int i; - error = git_vector_init(&list, whn_list->len, whn_cmp); + error = git_vector_init(&list, 16, whn_cmp); if (error < GIT_SUCCESS) return error; @@ -182,8 +182,8 @@ int git_fetch_negotiate(git_headarray *list, git_repository *repo, git_remote *r * Now we have everything set up so we can start tell the server * what we want and what we have. */ - git_remote_send_wants(remote, list); - + git_transport_send_wants(remote->transport, list); + git_transport_send_haves(remote->transport, repo); cleanup: git_revwalk_free(walk); diff --git a/src/pkt.c b/src/pkt.c index 06d1bc87b..fbb5dfb0a 100644 --- a/src/pkt.c +++ b/src/pkt.c @@ -27,6 +27,8 @@ #include "git2/types.h" #include "git2/errors.h" +#include "git2/refs.h" +#include "git2/revwalk.h" #include "pkt.h" #include "util.h" @@ -229,9 +231,70 @@ int git_pkt_send_wants(git_headarray *refs, int fd) for (i = 0; i < refs->len; ++i) { head = refs->heads[i]; + if (head->type != GIT_WHN_WANT) + continue; + git_oid_fmt(buf + STRLEN(WANT_PREFIX), &head->oid); - printf("would send %s\n", buf); + printf("would send %s", buf); } + /* TODO: git_pkt_send_flush(fd) */ + printf("Wound send 0000\n"); + + return ret; +} + +#define HAVE_PREFIX "0032have " + +int git_pkt_send_haves(git_repository *repo, 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'; + + ret = git_reference_listall(&refs, repo, GIT_REF_LISTALL); + if (ret < GIT_ERROR) + return git__rethrow(ret, "Failed to list all references"); + + 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); + } + + /* TODO: git_pkt_send_flush(fd) */ + printf("Wound send 0000\n"); + +cleanup: + git_revwalk_free(walk); + git_strarray_free(&refs); return ret; } diff --git a/src/pkt.h b/src/pkt.h index 6dc5486cd..43407037c 100644 --- a/src/pkt.h +++ b/src/pkt.h @@ -57,6 +57,8 @@ typedef struct { 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); void git_pkt_free(git_pkt *pkt); #endif diff --git a/src/remote.c b/src/remote.c index 997da00ce..2812f5de6 100644 --- a/src/remote.c +++ b/src/remote.c @@ -31,11 +31,6 @@ #include "repository.h" #include "remote.h" -int git_remote_send_wants(git_remote *remote, git_headarray *list) -{ - return git_transport_send_wants(remote->transport, list); -} - static int refspec_parse(git_refspec *refspec, const char *str) { char *delim; diff --git a/src/remote.h b/src/remote.h index e0c3fbf8d..129671fd2 100644 --- a/src/remote.h +++ b/src/remote.h @@ -1,9 +1,9 @@ #ifndef INCLUDE_remote_h__ #define INCLUDE_remote_h__ -#include "remote.h" #include "refspec.h" #include "transport.h" +#include "repository.h" struct git_remote { char *name; @@ -13,6 +13,4 @@ struct git_remote { git_transport *transport; }; -int git_remote_send_wants(git_remote *remote, git_headarray *list); - #endif diff --git a/src/transport.c b/src/transport.c index 96b79ddf4..53caf9e1b 100644 --- a/src/transport.c +++ b/src/transport.c @@ -85,6 +85,11 @@ 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) +{ + return transport->send_haves(transport, repo); +} + int git_transport_close(git_transport *transport) { return transport->close(transport); diff --git a/src/transport.h b/src/transport.h index 9105ea453..6e3501b99 100644 --- a/src/transport.h +++ b/src/transport.h @@ -60,6 +60,10 @@ struct git_transport { * Send the list of 'want' refs */ int (*send_wants)(struct git_transport *transport, git_headarray *list); + /** + * Send the list of 'have' refs + */ + int (*send_haves)(struct git_transport *transport, git_repository *repo); /** * Fetch the changes */ diff --git a/src/transport_git.c b/src/transport_git.c index 41b95ec2a..0453ca0fd 100644 --- a/src/transport_git.c +++ b/src/transport_git.c @@ -281,6 +281,13 @@ 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) +{ + transport_git *t = (transport_git *) transport; + + return git_pkt_send_haves(repo, t->socket); +} + static int git_close(git_transport *transport) { transport_git *t = (transport_git*) transport; @@ -326,6 +333,7 @@ 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.close = git_close; t->parent.free = git_free;