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>
Daniel Barkalow committed
Feb 4, 2008 at 13:26 UTC
ba227857d24029917f1e939647d826037f026205
5 files changed
+83
-48
builtin-fetch-pack.c
+40
-35
@@ -7,6 +7,7 @@
7
#include "pack.h"
8
#include "sideband.h"
9
#include "fetch-pack.h"
10
+#include "remote.h"
11
#include "run-command.h"
12
13
static int transfer_unpack_limit = -1;
@@ -548,14 +549,14 @@ static int get_pack(int xd[2], char **pack_lockfile)
549
}
550
551
static struct ref *do_fetch_pack(int fd[2],
552
+ const struct ref *orig_ref,
553
int nr_match,
554
char **match,
555
char **pack_lockfile)
556
{
555
- struct ref *ref;
557
+ struct ref *ref = copy_ref_list(orig_ref);
558
unsigned char sha1[20];
559
558
- get_remote_heads(fd[0], &ref, 0, NULL, 0);
560
if (is_repository_shallow() && !server_supports("shallow"))
561
die("Server does not support shallow clients");
562
if (server_supports("multi_ack")) {
@@ -573,10 +574,6 @@ static struct ref *do_fetch_pack(int fd[2],
574
fprintf(stderr, "Server supports side-band\n");
575
use_sideband = 1;
576
}
576
- if (!ref) {
577
- packet_flush(fd[1]);
578
- die("no matching remote head");
579
- }
577
if (everything_local(&ref, nr_match, match)) {
578
packet_flush(fd[1]);
579
goto all_done;
@@ -650,8 +647,10 @@ static void fetch_pack_setup(void)
647
int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
648
{
649
int i, ret, nr_heads;
653
- struct ref *ref;
650
+ struct ref *ref = NULL;
651
char *dest = NULL, **heads;
652
+ int fd[2];
653
+ struct child_process *conn;
654
655
nr_heads = 0;
656
heads = NULL;
@@ -706,9 +705,33 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
705
if (!dest)
706
usage(fetch_pack_usage);
707
709
- ref = fetch_pack(&args, dest, nr_heads, heads, NULL);
708
+ conn = git_connect(fd, (char *)dest, args.uploadpack,
709
+ args.verbose ? CONNECT_VERBOSE : 0);
710
+ if (conn) {
711
+ get_remote_heads(fd[0], &ref, 0, NULL, 0);
712
+
713
+ ref = fetch_pack(&args, fd, conn, ref, dest, nr_heads, heads, NULL);
714
+ close(fd[0]);
715
+ close(fd[1]);
716
+ if (finish_connect(conn))
717
+ ref = NULL;
718
+ } else {
719
+ ref = NULL;
720
+ }
721
ret = !ref;
722
723
+ if (!ret && nr_heads) {
724
+ /* If the heads to pull were given, we should have
725
+ * consumed all of them by matching the remote.
726
+ * Otherwise, 'git-fetch remote no-such-ref' would
727
+ * silently succeed without issuing an error.
728
+ */
729
+ for (i = 0; i < nr_heads; i++)
730
+ if (heads[i] && heads[i][0]) {
731
+ error("no such remote ref %s", heads[i]);
732
+ ret = 1;
733
+ }
734
+ }
735
while (ref) {
736
printf("%s %s\n",
737
sha1_to_hex(ref->old_sha1), ref->name);
@@ -719,16 +742,15 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
742
}
743
744
struct ref *fetch_pack(struct fetch_pack_args *my_args,
745
+ int fd[], struct child_process *conn,
746
+ const struct ref *ref,
747
const char *dest,
748
int nr_heads,
749
char **heads,
750
char **pack_lockfile)
751
{
727
- int i, ret;
728
- int fd[2];
729
- struct child_process *conn;
730
- struct ref *ref;
752
struct stat st;
753
+ struct ref *ref_cpy;
754
755
fetch_pack_setup();
756
memcpy(&args, my_args, sizeof(args));
@@ -737,29 +759,15 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
759
st.st_mtime = 0;
760
}
761
740
- conn = git_connect(fd, (char *)dest, args.uploadpack,
741
- args.verbose ? CONNECT_VERBOSE : 0);
762
if (heads && nr_heads)
763
nr_heads = remove_duplicates(nr_heads, heads);
744
- ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile);
745
- close(fd[0]);
746
- close(fd[1]);
747
- ret = finish_connect(conn);
748
-
749
- if (!ret && nr_heads) {
750
- /* If the heads to pull were given, we should have
751
- * consumed all of them by matching the remote.
752
- * Otherwise, 'git-fetch remote no-such-ref' would
753
- * silently succeed without issuing an error.
754
- */
755
- for (i = 0; i < nr_heads; i++)
756
- if (heads[i] && heads[i][0]) {
757
- error("no such remote ref %s", heads[i]);
758
- ret = 1;
759
- }
764
+ if (!ref) {
765
+ packet_flush(fd[1]);
766
+ die("no matching remote head");
767
}
768
+ ref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);
769
762
- if (!ret && args.depth > 0) {
770
+ if (args.depth > 0) {
771
struct cache_time mtime;
772
char *shallow = git_path("shallow");
773
int fd;
@@ -787,8 +795,5 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
795
}
796
}
797
790
- if (ret)
791
- ref = NULL;
792
-
793
- return ref;
798
+ return ref_cpy;
799
}
builtin-fetch.c
+2
@@ -557,6 +557,8 @@ static int do_fetch(struct transport *transport,
557
558
free_refs(fetch_map);
559
560
+ transport_disconnect(transport);
561
+
562
return 0;
563
}
564
builtin-ls-remote.c
+1
@@ -94,6 +94,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
94
transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);
95
96
ref = transport_get_remote_refs(transport);
97
+ transport_disconnect(transport);
98
99
if (!ref)
100
return 1;
fetch-pack.h
+2
@@ -16,6 +16,8 @@ struct fetch_pack_args
16
};
17
18
struct ref *fetch_pack(struct fetch_pack_args *args,
19
+ int fd[], struct child_process *conn,
20
+ const struct ref *ref,
21
const char *dest,
22
int nr_heads,
23
char **heads,
transport.c
+38
-13
@@ -563,6 +563,8 @@ struct git_transport_data {
563
unsigned thin : 1;
564
unsigned keep : 1;
565
int depth;
566
+ struct child_process *conn;
567
+ int fd[2];
568
const char *uploadpack;
569
const char *receivepack;
570
};
@@ -593,20 +595,20 @@ static int set_git_option(struct transport *connection,
595
return 1;
596
}
597
598
+static int connect_setup(struct transport *transport)
599
+{
600
+ struct git_transport_data *data = transport->data;
601
+ data->conn = git_connect(data->fd, transport->url, data->uploadpack, 0);
602
+ return 0;
603
+}
604
+
605
static struct ref *get_refs_via_connect(struct transport *transport)
606
{
607
struct git_transport_data *data = transport->data;
608
struct ref *refs;
600
- int fd[2];
601
- char *dest = xstrdup(transport->url);
602
- struct child_process *conn = git_connect(fd, dest, data->uploadpack, 0);
609
604
- get_remote_heads(fd[0], &refs, 0, NULL, 0);
605
- packet_flush(fd[1]);
606
-
607
- finish_connect(conn);
608
-
609
- free(dest);
610
+ connect_setup(transport);
611
+ get_remote_heads(data->fd[0], &refs, 0, NULL, 0);
612
613
return refs;
614
}
@@ -617,7 +619,7 @@ static int fetch_refs_via_pack(struct transport *transport,
619
struct git_transport_data *data = transport->data;
620
char **heads = xmalloc(nr_heads * sizeof(*heads));
621
char **origh = xmalloc(nr_heads * sizeof(*origh));
620
- struct ref *refs;
622
+ const struct ref *refs;
623
char *dest = xstrdup(transport->url);
624
struct fetch_pack_args args;
625
int i;
@@ -632,13 +634,27 @@ static int fetch_refs_via_pack(struct transport *transport,
634
635
for (i = 0; i < nr_heads; i++)
636
origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
635
- refs = fetch_pack(&args, dest, nr_heads, heads, &transport->pack_lockfile);
637
+
638
+ refs = transport_get_remote_refs(transport);
639
+ if (!data->conn) {
640
+ struct ref *refs_tmp;
641
+ connect_setup(transport);
642
+ get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0);
643
+ free_refs(refs_tmp);
644
+ }
645
+
646
+ refs = fetch_pack(&args, data->fd, data->conn, transport->remote_refs,
647
+ dest, nr_heads, heads, &transport->pack_lockfile);
648
+ close(data->fd[0]);
649
+ close(data->fd[1]);
650
+ if (finish_connect(data->conn))
651
+ refs = NULL;
652
+ data->conn = NULL;
653
654
for (i = 0; i < nr_heads; i++)
655
free(origh[i]);
656
free(origh);
657
free(heads);
641
- free_refs(refs);
658
free(dest);
659
return (refs ? 0 : -1);
660
}
@@ -661,7 +677,15 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const
677
678
static int disconnect_git(struct transport *transport)
679
{
664
- free(transport->data);
680
+ struct git_transport_data *data = transport->data;
681
+ if (data->conn) {
682
+ packet_flush(data->fd[1]);
683
+ close(data->fd[0]);
684
+ close(data->fd[1]);
685
+ finish_connect(data->conn);
686
+ }
687
+
688
+ free(data);
689
return 0;
690
}
691
@@ -721,6 +745,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
745
ret->disconnect = disconnect_git;
746
747
data->thin = 1;
748
+ data->conn = NULL;
749
data->uploadpack = "git-upload-pack";
750
if (remote && remote->uploadpack)
751
data->uploadpack = remote->uploadpack;