Reduce the number of connects when fetching
This shares the connection between getting the remote ref list and getting objects in the first batch. (A second connection is still used to follow tags). When we do not fetch objects (i.e. either ls-remote disconnects after getting list of refs, or we decide we are already up-to-date), we clean up the connection properly; otherwise the connection is left open in need of cleaning up to avoid getting an error message from the remote end when ssh is used. Signed-off-by: Daniel Barkalow <barkalow@iabervon.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
7a2078b4b0
commit
ba227857d2
@ -7,6 +7,7 @@
|
||||
#include "pack.h"
|
||||
#include "sideband.h"
|
||||
#include "fetch-pack.h"
|
||||
#include "remote.h"
|
||||
#include "run-command.h"
|
||||
|
||||
static int transfer_unpack_limit = -1;
|
||||
@ -548,14 +549,14 @@ static int get_pack(int xd[2], char **pack_lockfile)
|
||||
}
|
||||
|
||||
static struct ref *do_fetch_pack(int fd[2],
|
||||
const struct ref *orig_ref,
|
||||
int nr_match,
|
||||
char **match,
|
||||
char **pack_lockfile)
|
||||
{
|
||||
struct ref *ref;
|
||||
struct ref *ref = copy_ref_list(orig_ref);
|
||||
unsigned char sha1[20];
|
||||
|
||||
get_remote_heads(fd[0], &ref, 0, NULL, 0);
|
||||
if (is_repository_shallow() && !server_supports("shallow"))
|
||||
die("Server does not support shallow clients");
|
||||
if (server_supports("multi_ack")) {
|
||||
@ -573,10 +574,6 @@ static struct ref *do_fetch_pack(int fd[2],
|
||||
fprintf(stderr, "Server supports side-band\n");
|
||||
use_sideband = 1;
|
||||
}
|
||||
if (!ref) {
|
||||
packet_flush(fd[1]);
|
||||
die("no matching remote head");
|
||||
}
|
||||
if (everything_local(&ref, nr_match, match)) {
|
||||
packet_flush(fd[1]);
|
||||
goto all_done;
|
||||
@ -650,8 +647,10 @@ static void fetch_pack_setup(void)
|
||||
int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i, ret, nr_heads;
|
||||
struct ref *ref;
|
||||
struct ref *ref = NULL;
|
||||
char *dest = NULL, **heads;
|
||||
int fd[2];
|
||||
struct child_process *conn;
|
||||
|
||||
nr_heads = 0;
|
||||
heads = NULL;
|
||||
@ -706,45 +705,20 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
|
||||
if (!dest)
|
||||
usage(fetch_pack_usage);
|
||||
|
||||
ref = fetch_pack(&args, dest, nr_heads, heads, NULL);
|
||||
ret = !ref;
|
||||
|
||||
while (ref) {
|
||||
printf("%s %s\n",
|
||||
sha1_to_hex(ref->old_sha1), ref->name);
|
||||
ref = ref->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ref *fetch_pack(struct fetch_pack_args *my_args,
|
||||
const char *dest,
|
||||
int nr_heads,
|
||||
char **heads,
|
||||
char **pack_lockfile)
|
||||
{
|
||||
int i, ret;
|
||||
int fd[2];
|
||||
struct child_process *conn;
|
||||
struct ref *ref;
|
||||
struct stat st;
|
||||
|
||||
fetch_pack_setup();
|
||||
memcpy(&args, my_args, sizeof(args));
|
||||
if (args.depth > 0) {
|
||||
if (stat(git_path("shallow"), &st))
|
||||
st.st_mtime = 0;
|
||||
}
|
||||
|
||||
conn = git_connect(fd, (char *)dest, args.uploadpack,
|
||||
args.verbose ? CONNECT_VERBOSE : 0);
|
||||
if (heads && nr_heads)
|
||||
nr_heads = remove_duplicates(nr_heads, heads);
|
||||
ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
ret = finish_connect(conn);
|
||||
args.verbose ? CONNECT_VERBOSE : 0);
|
||||
if (conn) {
|
||||
get_remote_heads(fd[0], &ref, 0, NULL, 0);
|
||||
|
||||
ref = fetch_pack(&args, fd, conn, ref, dest, nr_heads, heads, NULL);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
if (finish_connect(conn))
|
||||
ref = NULL;
|
||||
} else {
|
||||
ref = NULL;
|
||||
}
|
||||
ret = !ref;
|
||||
|
||||
if (!ret && nr_heads) {
|
||||
/* If the heads to pull were given, we should have
|
||||
@ -758,8 +732,42 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
while (ref) {
|
||||
printf("%s %s\n",
|
||||
sha1_to_hex(ref->old_sha1), ref->name);
|
||||
ref = ref->next;
|
||||
}
|
||||
|
||||
if (!ret && args.depth > 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ref *fetch_pack(struct fetch_pack_args *my_args,
|
||||
int fd[], struct child_process *conn,
|
||||
const struct ref *ref,
|
||||
const char *dest,
|
||||
int nr_heads,
|
||||
char **heads,
|
||||
char **pack_lockfile)
|
||||
{
|
||||
struct stat st;
|
||||
struct ref *ref_cpy;
|
||||
|
||||
fetch_pack_setup();
|
||||
memcpy(&args, my_args, sizeof(args));
|
||||
if (args.depth > 0) {
|
||||
if (stat(git_path("shallow"), &st))
|
||||
st.st_mtime = 0;
|
||||
}
|
||||
|
||||
if (heads && nr_heads)
|
||||
nr_heads = remove_duplicates(nr_heads, heads);
|
||||
if (!ref) {
|
||||
packet_flush(fd[1]);
|
||||
die("no matching remote head");
|
||||
}
|
||||
ref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);
|
||||
|
||||
if (args.depth > 0) {
|
||||
struct cache_time mtime;
|
||||
char *shallow = git_path("shallow");
|
||||
int fd;
|
||||
@ -787,8 +795,5 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
|
||||
}
|
||||
}
|
||||
|
||||
if (ret)
|
||||
ref = NULL;
|
||||
|
||||
return ref;
|
||||
return ref_cpy;
|
||||
}
|
||||
|
@ -557,6 +557,8 @@ static int do_fetch(struct transport *transport,
|
||||
|
||||
free_refs(fetch_map);
|
||||
|
||||
transport_disconnect(transport);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -94,6 +94,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
|
||||
transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);
|
||||
|
||||
ref = transport_get_remote_refs(transport);
|
||||
transport_disconnect(transport);
|
||||
|
||||
if (!ref)
|
||||
return 1;
|
||||
|
@ -16,6 +16,8 @@ struct fetch_pack_args
|
||||
};
|
||||
|
||||
struct ref *fetch_pack(struct fetch_pack_args *args,
|
||||
int fd[], struct child_process *conn,
|
||||
const struct ref *ref,
|
||||
const char *dest,
|
||||
int nr_heads,
|
||||
char **heads,
|
||||
|
51
transport.c
51
transport.c
@ -563,6 +563,8 @@ struct git_transport_data {
|
||||
unsigned thin : 1;
|
||||
unsigned keep : 1;
|
||||
int depth;
|
||||
struct child_process *conn;
|
||||
int fd[2];
|
||||
const char *uploadpack;
|
||||
const char *receivepack;
|
||||
};
|
||||
@ -593,20 +595,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;
|
||||
}
|
||||
@ -617,7 +619,7 @@ 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;
|
||||
@ -632,13 +634,27 @@ static int fetch_refs_via_pack(struct transport *transport,
|
||||
|
||||
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);
|
||||
|
||||
refs = transport_get_remote_refs(transport);
|
||||
if (!data->conn) {
|
||||
struct ref *refs_tmp;
|
||||
connect_setup(transport);
|
||||
get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0);
|
||||
free_refs(refs_tmp);
|
||||
}
|
||||
|
||||
refs = fetch_pack(&args, data->fd, data->conn, 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;
|
||||
|
||||
for (i = 0; i < nr_heads; i++)
|
||||
free(origh[i]);
|
||||
free(origh);
|
||||
free(heads);
|
||||
free_refs(refs);
|
||||
free(dest);
|
||||
return (refs ? 0 : -1);
|
||||
}
|
||||
@ -661,7 +677,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;
|
||||
}
|
||||
|
||||
@ -721,6 +745,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;
|
||||
|
Loading…
Reference in New Issue
Block a user