From fc3e3c5577d177279b928ac23d3925de29a41056 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 5 Oct 2011 20:12:12 +0200 Subject: [PATCH] git transport: don't loose received data MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Using a different buffer in each function means that some data might get lost. Store all the data in a buffer in the transport object. Take this opportunity to use the generic download-pack function. Signed-off-by: Carlos Martín Nieto --- src/transport_git.c | 121 ++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 83 deletions(-) diff --git a/src/transport_git.c b/src/transport_git.c index e32b33350..7b65936a5 100644 --- a/src/transport_git.c +++ b/src/transport_git.c @@ -19,6 +19,7 @@ #include "netops.h" #include "filebuf.h" #include "repository.h" +#include "fetch.h" typedef struct { git_transport parent; @@ -26,6 +27,8 @@ typedef struct { git_vector refs; git_remote_head **heads; git_transport_caps caps; + char buff[1024]; + gitno_buffer buf; #ifdef GIT_WIN32 WSADATA wsd; #endif @@ -122,28 +125,25 @@ static int do_connect(transport_git *t, const char *url) */ static int store_refs(transport_git *t) { - gitno_buffer buf; - int s = t->socket; + gitno_buffer *buf = &t->buf; git_vector *refs = &t->refs; int error = GIT_SUCCESS; - char buffer[1024]; const char *line_end, *ptr; git_pkt *pkt; - gitno_buffer_setup(&buf, buffer, sizeof(buffer), s); while (1) { - error = gitno_recv(&buf); + error = gitno_recv(buf); if (error < GIT_SUCCESS) return git__rethrow(GIT_EOSERR, "Failed to receive data"); if (error == GIT_SUCCESS) /* Orderly shutdown, so exit */ return GIT_SUCCESS; - ptr = buf.data; + ptr = buf->data; while (1) { - if (buf.offset == 0) + if (buf->offset == 0) break; - error = git_pkt_parse_line(&pkt, ptr, &line_end, buf.offset); + error = git_pkt_parse_line(&pkt, ptr, &line_end, buf->offset); /* * If the error is GIT_ESHORTBUFFER, it means the buffer * isn't long enough to satisfy the request. Break out and @@ -158,7 +158,7 @@ static int store_refs(transport_git *t) } /* Get rid of the part we've used already */ - gitno_consume(&buf, line_end); + gitno_consume(buf, line_end); error = git_vector_insert(refs, pkt); if (error < GIT_SUCCESS) @@ -225,6 +225,8 @@ static int git_connect(git_transport *transport, int direction) if (error < GIT_SUCCESS) return error; + gitno_buffer_setup(&t->buf, t->buff, sizeof(t->buff), t->socket); + t->parent.connected = 1; error = store_refs(t); if (error < GIT_SUCCESS) @@ -274,15 +276,12 @@ static int git_negotiate_fetch(git_transport *transport, git_repository *repo, g git_oid oid; int error; unsigned int i; - char buff[128]; - gitno_buffer buf; + gitno_buffer *buf = &t->buf; error = git_pkt_send_wants(wants, &t->caps, t->socket); if (error < GIT_SUCCESS) return git__rethrow(error, "Failed to send wants list"); - gitno_buffer_setup(&buf, buff, sizeof(buff), t->socket); - error = git_reference_listall(&refs, repo, GIT_REF_LISTALL); if (error < GIT_ERROR) return git__rethrow(error, "Failed to list all references"); @@ -325,12 +324,12 @@ static int git_negotiate_fetch(git_transport *transport, git_repository *repo, g error = git_pkt_send_have(&oid, t->socket); i++; if (i % 20 == 0) { - const char *ptr = buf.data, *line_end; + const char *ptr = buf->data, *line_end; git_pkt *pkt; git_pkt_send_flush(t->socket); while (1) { /* Wait for max. 1 second */ - error = gitno_select_in(&buf, 1, 0); + error = gitno_select_in(buf, 1, 0); if (error < GIT_SUCCESS) { error = git__throw(GIT_EOSERR, "Error in select"); } else if (error == 0) { @@ -342,12 +341,12 @@ static int git_negotiate_fetch(git_transport *transport, git_repository *repo, g break; } - error = gitno_recv(&buf); + error = gitno_recv(buf); if (error < GIT_SUCCESS) { error = git__rethrow(error, "Error receiving data"); goto cleanup; } - error = git_pkt_parse_line(&pkt, ptr, &line_end, buf.offset); + error = git_pkt_parse_line(&pkt, ptr, &line_end, buf->offset); if (error == GIT_ESHORTBUFFER) continue; if (error < GIT_SUCCESS) { @@ -355,7 +354,7 @@ static int git_negotiate_fetch(git_transport *transport, git_repository *repo, g goto cleanup; } - gitno_consume(&buf, line_end); + gitno_consume(buf, line_end); if (pkt->type == GIT_PKT_ACK) { error = GIT_SUCCESS; @@ -378,6 +377,7 @@ done: cleanup: git_revwalk_free(walk); + return error; } @@ -395,93 +395,48 @@ static int git_send_done(git_transport *transport) return git_pkt_send_done(t->socket); } -static int store_pack(char **out, gitno_buffer *buf, git_repository *repo) -{ - git_filebuf file; - int error; - char path[GIT_PATH_MAX], suff[] = "/objects/pack/pack-received\0"; - off_t off = 0; - - strcpy(path, repo->path_repository); - off += strlen(repo->path_repository); - strcat(path, suff); - //memcpy(path + off, suff, GIT_PATH_MAX - off - strlen(suff) - 1); - - if (memcmp(buf->data, "PACK", strlen("PACK"))) { - return git__throw(GIT_ERROR, "The pack doesn't start with the signature"); - } - - error = git_filebuf_open(&file, path, GIT_FILEBUF_TEMPORARY); - if (error < GIT_SUCCESS) - goto cleanup; - - while (1) { - /* Part of the packfile has been received, don't loose it */ - error = git_filebuf_write(&file, buf->data, buf->offset); - if (error < GIT_SUCCESS) - goto cleanup; - - gitno_consume_n(buf, buf->offset); - error = gitno_recv(buf); - if (error < GIT_SUCCESS) - goto cleanup; - if (error == 0) /* Orderly shutdown */ - break; - } - - *out = git__strdup(file.path_lock); - if (*out == NULL) { - error = GIT_ENOMEM; - goto cleanup; - } - - /* A bit dodgy, but we need to keep the pack at the temporary path */ - error = git_filebuf_commit_at(&file, file.path_lock); -cleanup: - if (error < GIT_SUCCESS) - git_filebuf_cleanup(&file); - - return error; -} - static int git_download_pack(char **out, git_transport *transport, git_repository *repo) { transport_git *t = (transport_git *) transport; - int s = t->socket, error = GIT_SUCCESS; - gitno_buffer buf; - char buffer[1024]; + int error = GIT_SUCCESS; + gitno_buffer *buf = &t->buf; git_pkt *pkt; const char *line_end, *ptr; - gitno_buffer_setup(&buf, buffer, sizeof(buffer), s); /* * For now, we ignore everything and wait for the pack */ while (1) { - error = gitno_recv(&buf); - if (error < GIT_SUCCESS) - return git__rethrow(GIT_EOSERR, "Failed to receive data"); - if (error == 0) /* Orderly shutdown */ - return GIT_SUCCESS; - - ptr = buf.data; + ptr = buf->data; /* Whilst we're searching for the pack */ while (1) { - if (buf.offset == 0) + if (buf->offset == 0) { break; - error = git_pkt_parse_line(&pkt, ptr, &line_end, buf.offset); + } + + error = git_pkt_parse_line(&pkt, ptr, &line_end, buf->offset); if (error == GIT_ESHORTBUFFER) break; + if (error < GIT_SUCCESS) return error; - if (pkt->type == GIT_PKT_PACK) - return store_pack(out, &buf, repo); + if (pkt->type == GIT_PKT_PACK) { + return git_fetch__download_pack(out, buf->data, buf->offset, t->socket, repo); + } /* For now we don't care about anything */ free(pkt); - gitno_consume(&buf, line_end); + gitno_consume(buf, line_end); + } + + error = gitno_recv(buf); + if (error < GIT_SUCCESS) + return git__rethrow(GIT_EOSERR, "Failed to receive data"); + if (error == 0) { /* Orderly shutdown */ + return GIT_SUCCESS; } + } } -- 2.39.5