git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/4 v1] upload-pack: More aggressively send 'ACK %s ready'

From
Shawn O. Pearce <spearce@spearce.org>
Date
Mar 15, 2011, 00:59 UTC
Message-ID
<1300150780-7487-2-git-send-email-spearce@spearce.org>
In-Reply-To
<1300150780-7487-1-git-send-email-spearce@spearce.org>

If a client is merely following the remote (and has not made any new commits itself), all "have %s" lines sent by the client will be common to the server. As all lines are common upload-pack never calls ok_to_give_up() and does not compute if it has a good cut point in the commit graph.

Without this computation the following client is going to send all tagged commits, as these were determined to be COMMON_REF during the initial advertisement, but the client does not parse their history to transitively pass the COMMON flag and empty its queue of commits.

For git.git with 339 commit tags, it takes clients 11 rounds of negotation to fully send all tagged commits and exhaust its queue of things to send as common. This is pretty slow for a client that has not done any local development activity.

Force computing ok_to_give_up() and send "ACK %s ready" at the end of the current round if this round only contained common objects and ok_to_give_up() was therefore not called. This may allow the client to break early, avoiding transmission of the COMMON_REFs.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 Unchanged from v1.
 upload-pack.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/upload-pack.c b/upload-pack.c
index b40a43f..2a0f19e 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -429,6 +429,8 @@ static int get_common_commits(void)
 	static char line[1000];
 	unsigned char sha1[20];
 	char last_hex[41];
+	int got_common = 0;
+	int got_other = 0;
 
 	save_commit_buffer = 0;
 
@@ -437,16 +439,22 @@ static int get_common_commits(void)
 		reset_timeout();
 
 		if (!len) {
+			if (multi_ack == 2 && got_common
+					&& !got_other && ok_to_give_up())
+				packet_write(1, "ACK %s ready\n", last_hex);
 			if (have_obj.nr == 0 || multi_ack)
 				packet_write(1, "NAK\n");
 			if (stateless_rpc)
 				exit(0);
+			got_common = 0;
+			got_other = 0;
 			continue;
 		}
 		strip(line, len);
 		if (!prefixcmp(line, "have ")) {
 			switch (got_sha1(line+5, sha1)) {
 			case -1: /* they have what we do not */
+				got_other = 1;
 				if (multi_ack && ok_to_give_up()) {
 					const char *hex = sha1_to_hex(sha1);
 					if (multi_ack == 2)
@@ -456,6 +464,7 @@ static int get_common_commits(void)
 				}
 				break;
 			default:
+				got_common = 1;
 				memcpy(last_hex, sha1_to_hex(sha1), 41);
 				if (multi_ack == 2)
 					packet_write(1, "ACK %s common\n", last_hex);
-- 
1.7.4.1.35.ga52fb.dirty
Previous: Shawn O. PearceNext: Shawn O. Pearce
Message 2 of 4 in “fetch-pack: Finish negotation if remote replies "ACK %s ready"”
  1. 1/4 fetch-pack: Finish negotation if remote replies "ACK %s ready"Shawn O. Pearce, Mar 15, 2011
  2. 2/4 upload-pack: More aggressively send 'ACK %s ready'Shawn O. Pearce, Mar 15, 2011
  3. 3/4 fetch-pack: Implement no-done capabilityShawn O. Pearce, Mar 15, 2011
  4. 4/4 upload-pack: Implement no-done capabilityShawn O. Pearce, Mar 15, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.