Skip to content

Commit

Permalink
Reduce the number of connects when fetching
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Daniel Barkalow authored and Junio C Hamano committed Feb 5, 2008
1 parent 7a2078b commit ba22785
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 48 deletions.
75 changes: 40 additions & 35 deletions builtin-fetch-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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")) {
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -706,9 +705,33 @@ 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);
conn = git_connect(fd, (char *)dest, args.uploadpack,
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
* consumed all of them by matching the remote.
* Otherwise, 'git-fetch remote no-such-ref' would
* silently succeed without issuing an error.
*/
for (i = 0; i < nr_heads; i++)
if (heads[i] && heads[i][0]) {
error("no such remote ref %s", heads[i]);
ret = 1;
}
}
while (ref) {
printf("%s %s\n",
sha1_to_hex(ref->old_sha1), ref->name);
Expand All @@ -719,16 +742,15 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
}

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)
{
int i, ret;
int fd[2];
struct child_process *conn;
struct ref *ref;
struct stat st;
struct ref *ref_cpy;

fetch_pack_setup();
memcpy(&args, my_args, sizeof(args));
Expand All @@ -737,29 +759,15 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
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);

if (!ret && nr_heads) {
/* If the heads to pull were given, we should have
* consumed all of them by matching the remote.
* Otherwise, 'git-fetch remote no-such-ref' would
* silently succeed without issuing an error.
*/
for (i = 0; i < nr_heads; i++)
if (heads[i] && heads[i][0]) {
error("no such remote ref %s", heads[i]);
ret = 1;
}
if (!ref) {
packet_flush(fd[1]);
die("no matching remote head");
}
ref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);

if (!ret && args.depth > 0) {
if (args.depth > 0) {
struct cache_time mtime;
char *shallow = git_path("shallow");
int fd;
Expand Down Expand Up @@ -787,8 +795,5 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
}
}

if (ret)
ref = NULL;

return ref;
return ref_cpy;
}
2 changes: 2 additions & 0 deletions builtin-fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,8 @@ static int do_fetch(struct transport *transport,

free_refs(fetch_map);

transport_disconnect(transport);

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions builtin-ls-remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions fetch-pack.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
51 changes: 38 additions & 13 deletions transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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);
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit ba22785

Please sign in to comment.