Commit 7e1a94db by Carlos Martín Nieto Committed by Vicent Marti

Move have sending

Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
parent b4c90630
...@@ -51,7 +51,7 @@ static int whn_cmp(const void *a, const void *b) ...@@ -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) int git_fetch_list_want(git_headarray *whn_list, git_repository *repo, git_remote *remote)
{ {
git_vector list; git_vector list;
git_headarray refs, lrefs; git_headarray refs;
git_transport *t = remote->transport; git_transport *t = remote->transport;
const git_refspec *spec; const git_refspec *spec;
int error; int error;
...@@ -159,31 +159,49 @@ int git_fetch_negotiate(git_headarray *list, git_repository *repo, git_remote *r ...@@ -159,31 +159,49 @@ int git_fetch_negotiate(git_headarray *list, git_repository *repo, git_remote *r
unsigned int i; unsigned int i;
char local[1024]; char local[1024];
git_refspec *spec; git_refspec *spec;
git_reference *ref;
git_strarray refs;
git_oid oid;
error = git_revwalk_new(&walk, repo); /*
if (error < GIT_SUCCESS) * Now we have everything set up so we can start tell the server
return git__rethrow(error, "Failed to create walker"); * what we want and what we have.
*/
git_transport_send_wants(remote->transport, list);
for (i = 0; i < list->len; ++i) { error = git_reference_listall(&refs, repo, GIT_REF_LISTALL);
git_reference *ref; if (error < GIT_ERROR)
git_remote_head *head = list->heads[i]; return git__rethrow(error, "Failed to list all references");
if (!head->local) error = git_revwalk_new(&walk, repo);
continue; if (error < GIT_ERROR) {
error = git__rethrow(error, "Failed to list all references");
goto cleanup;
}
error = git_revwalk_push(walk, &head->loid); for (i = 0; i < refs.count; ++i) {
if (error < GIT_SUCCESS) { error = git_reference_lookup(&ref, repo, refs.strings[i]);
error = git__rethrow(error, "Failed to push a local OID"); 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; goto cleanup;
} }
} }
git_strarray_free(&refs);
/* while ((error = git_revwalk_next(&oid, walk)) == GIT_SUCCESS) {
* Now we have everything set up so we can start tell the server git_transport_send_have(remote->transport, &oid);
* what we want and what we have. }
*/ if (error == GIT_EREVWALKOVER)
git_transport_send_wants(remote->transport, list); error = GIT_SUCCESS;
git_transport_send_haves(remote->transport, repo);
/* TODO: git_pkt_send_flush(fd), or git_transport_flush() */
printf("Wound send 0000\n");
cleanup: cleanup:
git_revwalk_free(walk); git_revwalk_free(walk);
...@@ -192,5 +210,8 @@ cleanup: ...@@ -192,5 +210,8 @@ cleanup:
int git_fetch_download_pack(git_remote *remote) int git_fetch_download_pack(git_remote *remote)
{ {
/*
* First, we ignore any ACKs we receive and wait for a NACK
*/
return GIT_ENOTIMPLEMENTED; return GIT_ENOTIMPLEMENTED;
} }
...@@ -52,10 +52,38 @@ static int flush_pkt(git_pkt **out) ...@@ -52,10 +52,38 @@ static int flush_pkt(git_pkt **out)
return GIT_SUCCESS; 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. * 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; git_pkt_ref *pkt;
int error, has_caps = 0; int error, has_caps = 0;
...@@ -185,11 +213,14 @@ int git_pkt_parse_line(git_pkt **head, const char *line, const char **out, size_ ...@@ -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 */ len -= PKT_LEN_SIZE; /* the encoded length includes its own size */
/* /* Assming the minimal size is actually 4 */
* For now, we're just going to assume we're parsing references 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; *out = line + len;
return error; return error;
...@@ -239,62 +270,32 @@ int git_pkt_send_wants(git_headarray *refs, int fd) ...@@ -239,62 +270,32 @@ int git_pkt_send_wants(git_headarray *refs, int fd)
} }
/* TODO: git_pkt_send_flush(fd) */ /* TODO: git_pkt_send_flush(fd) */
printf("Wound send 0000\n"); printf("Would send 0000\n");
return ret; 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 " #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; int ret = GIT_SUCCESS;
char buf[STRLEN(HAVE_PREFIX) + GIT_OID_HEXSZ + 2]; char buf[] = "0032have 0000000000000000000000000000000000000000\n";
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); git_oid_fmt(buf + STRLEN(HAVE_PREFIX), oid);
if (ret < GIT_ERROR) printf("would send %s", buf);
return git__rethrow(ret, "Failed to list all references");
ret = git_revwalk_new(&walk, repo); return ret;
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) */ int git_pkt_send_have(int fd)
printf("Wound send 0000\n"); {
char buf[] = "0009done\n";
printf("Would send %s", buf);
cleanup: return GIT_SUCCESS;
git_revwalk_free(walk);
git_strarray_free(&refs);
return ret;
} }
...@@ -34,6 +34,16 @@ enum git_pkt_type { ...@@ -34,6 +34,16 @@ enum git_pkt_type {
GIT_PKT_FLUSH, GIT_PKT_FLUSH,
GIT_PKT_REF, GIT_PKT_REF,
GIT_PKT_HAVE, 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 */ /* This would be a flush pkt */
...@@ -55,10 +65,17 @@ typedef struct { ...@@ -55,10 +65,17 @@ typedef struct {
char *capabilities; char *capabilities;
} git_pkt_ref; } 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_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_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_wants(git_headarray *refs, int fd);
int git_pkt_send_have(git_oid *oid, int fd);
void git_pkt_free(git_pkt *pkt); void git_pkt_free(git_pkt *pkt);
#endif #endif
...@@ -85,11 +85,15 @@ int git_transport_send_wants(struct git_transport *transport, git_headarray *arr ...@@ -85,11 +85,15 @@ int git_transport_send_wants(struct git_transport *transport, git_headarray *arr
return transport->send_wants(transport, array); 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) int git_transport_close(git_transport *transport)
{ {
return transport->close(transport); return transport->close(transport);
......
...@@ -63,7 +63,7 @@ struct git_transport { ...@@ -63,7 +63,7 @@ struct git_transport {
/** /**
* Send the list of 'have' refs * 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 * Fetch the changes
*/ */
...@@ -83,5 +83,7 @@ int git_transport_git(struct git_transport **transport); ...@@ -83,5 +83,7 @@ int git_transport_git(struct git_transport **transport);
int git_transport_dummy(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_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 #endif
...@@ -281,11 +281,18 @@ static int git_send_wants(git_transport *transport, git_headarray *array) ...@@ -281,11 +281,18 @@ static int git_send_wants(git_transport *transport, git_headarray *array)
return git_pkt_send_wants(array, t->socket); 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; 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) static int git_close(git_transport *transport)
...@@ -333,7 +340,8 @@ int git_transport_git(git_transport **out) ...@@ -333,7 +340,8 @@ int git_transport_git(git_transport **out)
t->parent.connect = git_connect; t->parent.connect = git_connect;
t->parent.ls = git_ls; t->parent.ls = git_ls;
t->parent.send_wants = git_send_wants; 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.close = git_close;
t->parent.free = git_free; t->parent.free = git_free;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment