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

[PATCH] send-pack: do not give up when remote has insanely large number of refs.

From
Junio C Hamano <junkio@cox.net>
Date
Feb 22, 2006, 09:51 UTC
Message-ID
<7v1wxvsovj.fsf_-_@assigned-by-dhcp.cox.net>
In-Reply-To
<7virr8t82n.fsf@assigned-by-dhcp.cox.net>

Stephen C. Tweedie noticed that we give up running rev-list when we see too many refs on the remote side. Limit the number of negative references we give to rev-list and continue.

Not sending any negative references to rev-list is very bad -- we may be pushing a ref that is new to the other end.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
  Junio C Hamano <junkio@cox.net> writes:
  > That is, something like this.
  > -- >8 --
  > Do not give up...
  Ah, crap.  Sorry about that.  This one has been tested at least.
 send-pack.c |   38 ++++++++++++++++++++++++++++----------
 1 files changed, 28 insertions(+), 10 deletions(-)
797656e58ddbd82ac461a5142ed726db3a4d0ac0
diff --git a/send-pack.c b/send-pack.c
index 990be3f..b58bbab 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -37,26 +37,44 @@ static void exec_pack_objects(void)
 
 static void exec_rev_list(struct ref *refs)
 {
+	struct ref *ref;
 	static char *args[1000];
-	int i = 0;
+	int i = 0, j;
 
 	args[i++] = "rev-list";	/* 0 */
 	args[i++] = "--objects";	/* 1 */
-	while (refs) {
-		char *buf = malloc(100);
-		if (i > 900)
+
+	/* First send the ones we care about most */
+	for (ref = refs; ref; ref = ref->next) {
+		if (900 < i)
 			die("git-rev-list environment overflow");
-		if (!is_zero_sha1(refs->old_sha1) &&
-		    has_sha1_file(refs->old_sha1)) {
+		if (!is_zero_sha1(ref->new_sha1)) {
+			char *buf = malloc(100);
 			args[i++] = buf;
-			snprintf(buf, 50, "^%s", sha1_to_hex(refs->old_sha1));
+			snprintf(buf, 50, "%s", sha1_to_hex(ref->new_sha1));
 			buf += 50;
+			if (!is_zero_sha1(ref->old_sha1) &&
+			    has_sha1_file(ref->old_sha1)) {
+				args[i++] = buf;
+				snprintf(buf, 50, "^%s",
+					 sha1_to_hex(ref->old_sha1));
+			}
 		}
-		if (!is_zero_sha1(refs->new_sha1)) {
+	}
+
+	/* Then a handful of the remainder
+	 * NEEDSWORK: we would be better off if used the newer ones first.
+	 */
+	for (ref = refs, j = i + 16;
+	     i < 900 && i < j && ref;
+	     ref = ref->next) {
+		if (is_zero_sha1(ref->new_sha1) &&
+		    !is_zero_sha1(ref->old_sha1) &&
+		    has_sha1_file(ref->old_sha1)) {
+			char *buf = malloc(42);
 			args[i++] = buf;
-			snprintf(buf, 50, "%s", sha1_to_hex(refs->new_sha1));
+			snprintf(buf, 42, "^%s", sha1_to_hex(ref->old_sha1));
 		}
-		refs = refs->next;
 	}
 	args[i] = NULL;
 	execv_git_cmd(args);
-- 
1.2.2.g882e
Previous: Junio C HamanoNext: Stephen C. Tweedie
Message 5 of 7 in “Git cannot push to repository with too many tags/heads”
  1. Stephen C. TweedieFeb 21, 2006
  2. Don't sent objects for refs we're not going to update.Stephen C. Tweedie, Feb 21, 2006
  3. Junio C HamanoFeb 22, 2006
  4. Junio C HamanoFeb 22, 2006
  5. send-pack: do not give up when remote has insanely large number of refs.Junio C Hamano, Feb 22, 2006
  6. Stephen C. TweedieFeb 22, 2006
  7. Junio C HamanoFeb 22, 2006

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.