@matheusbsbs / matheus-bagliano / commits / ba227857d2
Fork 0

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;