git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Tan <jonathantanmy@google.com>
To: git@vger.kernel.org
Cc: bmwill@google.com, gitster@pobox.com,
	Jonathan Tan <jonathantanmy@google.com>
Subject: [PATCH v3 4/7] fetch-pack: use ref adv. to prune "have" sent
Date: Thu, 14 Jun 2018 15:54:25 -0700	[thread overview]
Message-ID: <be3774cd799b7ff538fefc2171bc46c164f2eae6.1529016350.git.jonathantanmy@google.com> (raw)
In-Reply-To: <cover.1529016350.git.jonathantanmy@google.com>

In negotiation using protocol v2, fetch-pack sometimes does not make
full use of the information obtained in the ref advertisement:
specifically, that if the server advertises a commit that the client
also has, the client never needs to inform the server that it has the
commit's parents, since it can just tell the server that it has the
advertised commit and it knows that the server can and will infer the
rest.

This is because, in do_fetch_pack_v2(), rev_list_insert_ref_oid() is
invoked before mark_complete_and_common_ref(). This means that if we
have a commit that is both our ref and their ref, it would be enqueued
by rev_list_insert_ref_oid() as SEEN, and since it is thus already SEEN,
mark_complete_and_common_ref() would not enqueue it.

If mark_complete_and_common_ref() were invoked first, as it is in
do_fetch_pack() for protocol v0, then mark_complete_and_common_ref()
would enqueue it with COMMON_REF | SEEN. The addition of COMMON_REF
ensures that its parents are not sent as "have" lines.

Change the order in do_fetch_pack_v2() to be consistent with
do_fetch_pack(), and to avoid sending unnecessary "have" lines.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 fetch-pack.c          |  6 +++---
 t/t5500-fetch-pack.sh | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/fetch-pack.c b/fetch-pack.c
index 60adfc073..806c40021 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -1392,9 +1392,6 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
 				for_each_ref(clear_marks, NULL);
 			marked = 1;
 
-			for_each_ref(rev_list_insert_ref_oid, NULL);
-			for_each_cached_alternate(insert_one_alternate_object);
-
 			/* Filter 'ref' by 'sought' and those that aren't local */
 			mark_complete_and_common_ref(args, &ref);
 			filter_refs(args, &ref, sought, nr_sought);
@@ -1402,6 +1399,9 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
 				state = FETCH_DONE;
 			else
 				state = FETCH_SEND_REQUEST;
+
+			for_each_ref(rev_list_insert_ref_oid, NULL);
+			for_each_cached_alternate(insert_one_alternate_object);
 			break;
 		case FETCH_SEND_REQUEST:
 			if (send_fetch_request(fd[1], args, ref, &common,
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index d4f435155..e0cdc295d 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -755,6 +755,39 @@ test_expect_success 'fetching deepen' '
 	)
 '
 
+test_expect_success 'use ref advertisement to prune "have" lines sent' '
+	rm -rf server client &&
+	git init server &&
+	test_commit -C server both_have_1 &&
+	git -C server tag -d both_have_1 &&
+	test_commit -C server both_have_2 &&
+
+	git clone server client &&
+	test_commit -C server server_has &&
+	test_commit -C client client_has &&
+
+	# In both protocol v0 and v2, ensure that the parent of both_have_2 is
+	# not sent as a "have" line. The client should know that the server has
+	# both_have_2, so it only needs to inform the server that it has
+	# both_have_2, and the server can infer the rest.
+
+	rm -f trace &&
+	cp -r client clientv0 &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -C clientv0 \
+		fetch origin server_has both_have_2 &&
+	grep "have $(git -C client rev-parse client_has)" trace &&
+	grep "have $(git -C client rev-parse both_have_2)" trace &&
+	! grep "have $(git -C client rev-parse both_have_2^)" trace &&
+
+	rm -f trace &&
+	cp -r client clientv2 &&
+	GIT_TRACE_PACKET="$(pwd)/trace" git -C clientv2 -c protocol.version=2 \
+		fetch origin server_has both_have_2 &&
+	grep "have $(git -C client rev-parse client_has)" trace &&
+	grep "have $(git -C client rev-parse both_have_2)" trace &&
+	! grep "have $(git -C client rev-parse both_have_2^)" trace
+'
+
 test_expect_success 'filtering by size' '
 	rm -rf server client &&
 	test_create_repo server &&
-- 
2.17.0.582.gccdcbd54c4


  parent reply	other threads:[~2018-06-14 22:54 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-04 17:29 [PATCH 0/6] Refactor fetch negotiation into its own API Jonathan Tan
2018-06-04 17:29 ` [PATCH 1/6] fetch-pack: clear marks before everything_local() Jonathan Tan
2018-06-05 23:08   ` Jonathan Nieder
2018-06-06  0:32     ` Jonathan Tan
2018-06-04 17:29 ` [PATCH 2/6] fetch-pack: truly stop negotiation upon ACK ready Jonathan Tan
2018-06-05 23:16   ` Jonathan Nieder
2018-06-05 23:18     ` Jonathan Nieder
2018-06-06  0:38     ` Jonathan Tan
2018-06-04 17:29 ` [PATCH 3/6] fetch-pack: in protocol v2, enqueue commons first Jonathan Tan
2018-06-05 23:30   ` Jonathan Nieder
2018-06-06  2:10     ` Jonathan Tan
2018-06-04 17:29 ` [PATCH 4/6] fetch-pack: make negotiation-related vars local Jonathan Tan
2018-06-05 23:35   ` Jonathan Nieder
2018-06-06  2:12     ` Jonathan Tan
2018-06-04 17:29 ` [PATCH 5/6] fetch-pack: move common check and marking together Jonathan Tan
2018-06-06  0:01   ` Jonathan Nieder
2018-06-06  2:12     ` Jonathan Tan
2018-06-04 17:29 ` [PATCH 6/6] fetch-pack: introduce negotiator API Jonathan Tan
2018-06-06  0:37   ` Jonathan Nieder
2018-06-06  2:17     ` Jonathan Tan
2018-06-06 20:47 ` [PATCH v2 0/8] Refactor fetch negotiation into its own API Jonathan Tan
2018-06-06 20:47   ` [PATCH v2 1/8] fetch-pack: split up everything_local() Jonathan Tan
2018-06-14 17:26     ` Brandon Williams
2018-06-06 20:47   ` [PATCH v2 2/8] fetch-pack: clear marks before re-marking Jonathan Tan
2018-06-06 20:47   ` [PATCH v2 3/8] fetch-pack: directly end negotiation if ACK ready Jonathan Tan
2018-06-14 17:29     ` Brandon Williams
2018-06-14 17:34       ` Brandon Williams
2018-06-06 20:47   ` [PATCH v2 4/8] fetch-pack: use ref adv. to prune "have" sent Jonathan Tan
2018-06-14 17:32     ` Brandon Williams
2018-06-14 19:52     ` Junio C Hamano
2018-06-06 20:47   ` [PATCH v2 5/8] fetch-pack: make negotiation-related vars local Jonathan Tan
2018-06-14 17:38     ` Brandon Williams
2018-06-14 19:36     ` Junio C Hamano
2018-06-06 20:47   ` [PATCH v2 6/8] fetch-pack: move common check and marking together Jonathan Tan
2018-06-06 20:47   ` [PATCH v2 7/8] fetch-pack: introduce negotiator API Jonathan Tan
2018-06-06 20:47   ` [PATCH v2 8/8] negotiator/default: use better style in comments Jonathan Tan
2018-06-14 17:39     ` Brandon Williams
2018-06-14 22:54 ` [PATCH v3 0/7] Refactor fetch negotiation into its own API Jonathan Tan
2018-06-14 22:54   ` [PATCH v3 1/7] fetch-pack: split up everything_local() Jonathan Tan
2018-06-14 22:54   ` [PATCH v3 2/7] fetch-pack: clear marks before re-marking Jonathan Tan
2018-06-14 22:54   ` [PATCH v3 3/7] fetch-pack: directly end negotiation if ACK ready Jonathan Tan
2018-06-15 16:04     ` Junio C Hamano
2018-06-14 22:54   ` Jonathan Tan [this message]
2018-06-14 22:54   ` [PATCH v3 5/7] fetch-pack: make negotiation-related vars local Jonathan Tan
2018-06-14 22:54   ` [PATCH v3 6/7] fetch-pack: move common check and marking together Jonathan Tan
2018-06-14 22:54   ` [PATCH v3 7/7] fetch-pack: introduce negotiator API Jonathan Tan
2018-06-25 18:24   ` [PATCH v3 0/7] Refactor fetch negotiation into its own API Brandon Williams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=be3774cd799b7ff538fefc2171bc46c164f2eae6.1529016350.git.jonathantanmy@google.com \
    --to=jonathantanmy@google.com \
    --cc=bmwill@google.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).