X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=transport.c;h=393e0e8fe233ca51dc4c5db94c55e81ee53baa52;hb=fae09a8084c9b51632726523b477a78dd28d7d7e;hp=1f840a0498f9fa013c4b10d874525fbca679b2de;hpb=e8dc37e0e30dbbed532b7471516d1ba5e6e08f27;p=git.git diff --git a/transport.c b/transport.c index 1f840a049..393e0e8fe 100644 --- a/transport.c +++ b/transport.c @@ -118,7 +118,7 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list) if (hexval(buffer[0]) > 0xf) continue; len = strlen(buffer); - if (buffer[len - 1] == '\n') + if (len && buffer[len - 1] == '\n') buffer[--len] = '\0'; if (len < 41) continue; @@ -428,7 +428,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons static struct ref *get_refs_via_curl(struct transport *transport) { - struct buffer buffer; + struct strbuf buffer = STRBUF_INIT; char *data, *start, *mid; char *ref_name; char *refs_url; @@ -441,50 +441,41 @@ static struct ref *get_refs_via_curl(struct transport *transport) struct ref *ref = NULL; struct ref *last_ref = NULL; - data = xmalloc(4096); - buffer.size = 4096; - buffer.posn = 0; - buffer.buffer = data; + if (!transport->data) + transport->data = get_http_walker(transport->url, + transport->remote); refs_url = xmalloc(strlen(transport->url) + 11); sprintf(refs_url, "%s/info/refs", transport->url); - http_init(); - slot = get_active_slot(); slot->results = &results; curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer); curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); curl_easy_setopt(slot->curl, CURLOPT_URL, refs_url); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL); - if (transport->remote->http_proxy) - curl_easy_setopt(slot->curl, CURLOPT_PROXY, - transport->remote->http_proxy); if (start_active_slot(slot)) { run_active_slot(slot); if (results.curl_result != CURLE_OK) { + strbuf_release(&buffer); if (missing_target(&results)) { - free(buffer.buffer); return NULL; } else { - free(buffer.buffer); error("%s", curl_errorstr); return NULL; } } } else { - free(buffer.buffer); + strbuf_release(&buffer); error("Unable to start request"); return NULL; } - http_cleanup(); - - data = buffer.buffer; + data = buffer.buf; start = NULL; mid = data; - while (i < buffer.posn) { + while (i < buffer.len) { if (!start) start = &data[i]; if (data[i] == '\t') @@ -507,7 +498,7 @@ static struct ref *get_refs_via_curl(struct transport *transport) i++; } - free(buffer.buffer); + strbuf_release(&buffer); return refs; } @@ -516,7 +507,8 @@ static int fetch_objs_via_curl(struct transport *transport, int nr_objs, struct ref **to_fetch) { if (!transport->data) - transport->data = get_http_walker(transport->url); + transport->data = get_http_walker(transport->url, + transport->remote); return fetch_objs_via_walker(transport, nr_objs, to_fetch); } @@ -568,7 +560,10 @@ static int close_bundle(struct transport *transport) struct git_transport_data { unsigned thin : 1; unsigned keep : 1; + unsigned followtags : 1; int depth; + struct child_process *conn; + int fd[2]; const char *uploadpack; const char *receivepack; }; @@ -586,6 +581,9 @@ static int set_git_option(struct transport *connection, } else if (!strcmp(name, TRANS_OPT_THIN)) { data->thin = !!value; return 0; + } else if (!strcmp(name, TRANS_OPT_FOLLOWTAGS)) { + data->followtags = !!value; + return 0; } else if (!strcmp(name, TRANS_OPT_KEEP)) { data->keep = !!value; return 0; @@ -599,20 +597,20 @@ static int set_git_option(struct transport *connection, return 1; } +static int connect_setup(struct transport *transport) +{ + struct git_transport_data *data = transport->data; + data->conn = git_connect(data->fd, transport->url, data->uploadpack, 0); + return 0; +} + static struct ref *get_refs_via_connect(struct transport *transport) { struct git_transport_data *data = transport->data; struct ref *refs; - int fd[2]; - char *dest = xstrdup(transport->url); - struct child_process *conn = git_connect(fd, dest, data->uploadpack, 0); - get_remote_heads(fd[0], &refs, 0, NULL, 0); - packet_flush(fd[1]); - - finish_connect(conn); - - free(dest); + connect_setup(transport); + get_remote_heads(data->fd[0], &refs, 0, NULL, 0); return refs; } @@ -623,28 +621,44 @@ static int fetch_refs_via_pack(struct transport *transport, struct git_transport_data *data = transport->data; char **heads = xmalloc(nr_heads * sizeof(*heads)); char **origh = xmalloc(nr_heads * sizeof(*origh)); - struct ref *refs; + const struct ref *refs; char *dest = xstrdup(transport->url); struct fetch_pack_args args; int i; + struct ref *refs_tmp = NULL; memset(&args, 0, sizeof(args)); args.uploadpack = data->uploadpack; args.keep_pack = data->keep; args.lock_pack = 1; args.use_thin_pack = data->thin; + args.include_tag = data->followtags; args.verbose = transport->verbose > 0; args.depth = data->depth; for (i = 0; i < nr_heads; i++) origh[i] = heads[i] = xstrdup(to_fetch[i]->name); - refs = fetch_pack(&args, dest, nr_heads, heads, &transport->pack_lockfile); + + if (!data->conn) { + connect_setup(transport); + get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0); + } + + refs = fetch_pack(&args, data->fd, data->conn, + refs_tmp ? refs_tmp : transport->remote_refs, + dest, nr_heads, heads, &transport->pack_lockfile); + close(data->fd[0]); + close(data->fd[1]); + if (finish_connect(data->conn)) + refs = NULL; + data->conn = NULL; + + free_refs(refs_tmp); for (i = 0; i < nr_heads; i++) free(origh[i]); free(origh); free(heads); - free_refs(refs); free(dest); return (refs ? 0 : -1); } @@ -667,7 +681,15 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const static int disconnect_git(struct transport *transport) { - free(transport->data); + struct git_transport_data *data = transport->data; + if (data->conn) { + packet_flush(data->fd[1]); + close(data->fd[0]); + close(data->fd[1]); + finish_connect(data->conn); + } + + free(data); return 0; } @@ -727,6 +749,7 @@ struct transport *transport_get(struct remote *remote, const char *url) ret->disconnect = disconnect_git; data->thin = 1; + data->conn = NULL; data->uploadpack = "git-upload-pack"; if (remote && remote->uploadpack) data->uploadpack = remote->uploadpack;