summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <carlos@cmartin.tk>2011-09-13 23:28:42 +0200
committerVicent Marti <tanoku@gmail.com>2011-10-12 21:33:18 +0200
commit747bf5f14c8fa3d26cfcdc093ea9c1c553ed09c6 (patch)
tree6fd11ad4d5a977657598ce0f6eb1b0bd5d9d9dae
parent34bfb4b0d40b17e51d25df726a80226ccbc8dec7 (diff)
downloadlibgit2-747bf5f14c8fa3d26cfcdc093ea9c1c553ed09c6.tar.gz
http: Start negotiate_fetch
-rw-r--r--src/transport-http.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/transport-http.c b/src/transport-http.c
index cc1293900..109c9ee86 100644
--- a/src/transport-http.c
+++ b/src/transport-http.c
@@ -14,6 +14,7 @@
#include "netops.h"
#include "buffer.h"
#include "pkt.h"
+#include "refs.h"
enum last_cb {
NONE,
@@ -37,6 +38,7 @@ typedef struct {
char *host;
char *port;
char *service;
+ git_transport_caps caps;
#ifdef GIT_WIN32
WSADATA wsd;
#endif
@@ -54,6 +56,8 @@ static int gen_request(git_buf *buf, const char *url, const char *host, const ch
git_buf_puts(buf, "User-Agent: git/1.0 (libgit2 " LIBGIT2_VERSION ")\r\n");
git_buf_printf(buf, "Host: %s\r\n", host);
git_buf_puts(buf, "Accept: */*\r\n" "Pragma: no-cache\r\n\r\n");
+ if (strncmp(service, "POST", strlen("POST")))
+ git_buf_puts(buf, "Content-Encoding: chunked");
if (git_buf_oom(buf))
return GIT_ENOMEM;
@@ -337,6 +341,92 @@ static int http_ls(git_transport *transport, git_headarray *array)
return GIT_SUCCESS;
}
+static int http_send_wants(git_transport *transport, git_headarray *array)
+{
+ transport_http *t = (transport_http *) transport;
+ const char *prefix = "http://", *url = t->parent.url;
+ git_buf request = GIT_BUF_INIT;
+ int error;
+
+ /* TODO: Store url in the transport */
+ if (!git__prefixcmp(url, prefix))
+ url += strlen(prefix);
+
+ error = do_connect(t, t->host, t->port);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Faile to connect to host");
+
+ error = gen_request(&request, url, t->host, "POST", "upload-pack");
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to generate request");
+
+ error = gitno_send(t->socket, request.ptr, request.size, 0);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to send request");
+
+ return git_pkt_send_wants(array, &t->caps, t->socket, 1);
+}
+
+static int http_negotiate_fetch(git_transport *transport, git_repository *repo, git_headarray *GIT_UNUSED(list))
+{
+ transport_http *t = (transport_http *) transport;
+ GIT_UNUSED_ARG(list);
+ int error;
+ unsigned int i;
+ char buff[128];
+ gitno_buffer buf;
+ git_strarray refs;
+ git_revwalk *walk;
+ git_reference *ref;
+ git_oid oid;
+
+ gitno_buffer_setup(&buf, buff, sizeof(buff), t->socket);
+
+ error = git_reference_listall(&refs, repo, GIT_REF_LISTALL);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to list references");
+
+ error = git_revwalk_new(&walk, repo);
+ if (error < GIT_ERROR) {
+ error = git__rethrow(error, "Failed to list all references");
+ goto cleanup;
+ }
+ git_revwalk_sorting(walk, GIT_SORT_TIME);
+
+ for (i = 0; i < refs.count; ++i) {
+ /* No tags */
+ if (!git__prefixcmp(refs.strings[i], GIT_REFS_TAGS_DIR))
+ continue;
+
+ 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;
+ }
+
+ if (git_reference_type(ref) == GIT_REF_SYMBOLIC)
+ continue;
+ 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);
+
+ i = 0;
+ while ((error = git_revwalk_next(&oid, walk)) == GIT_SUCCESS) {
+ error = git_pkt_send_have(&oid, t->socket, 1);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to send have");
+ i++;
+ }
+
+cleanup:
+ git_revwalk_free(walk);
+ return error;
+}
+
static int http_close(git_transport *transport)
{
transport_http *t = (transport_http *) transport;
@@ -391,6 +481,8 @@ int git_transport_http(git_transport **out)
t->parent.connect = http_connect;
t->parent.ls = http_ls;
+ t->parent.send_wants = http_send_wants;
+ t->parent.negotiate_fetch = http_negotiate_fetch;
t->parent.close = http_close;
t->parent.free = http_free;