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

[PATCH 2/3] bulk-checkin: do not write the same object twice

From
Junio C Hamano <gitster@pobox.com>
Date
Nov 18, 2011, 07:11 UTC
Message-ID
<1321600317-30546-3-git-send-email-gitster@pobox.com>
In-Reply-To
<1321600317-30546-1-git-send-email-gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 bulk-checkin.c   |   28 ++++++++++++++++++++++++----
 t/t1050-large.sh |   20 +++++++++++++-------
 2 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/bulk-checkin.c b/bulk-checkin.c
index c7e693e..82166ba 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -52,6 +52,17 @@ static void finish_bulk_checkin(struct bulk_checkin_state *state)
 	reprepare_packed_git();
 }
 
+static int already_written(struct bulk_checkin_state *state, unsigned char sha1[])
+{
+	int i;
+
+	/* Might want to keep the list sorted */
+	for (i = 0; i < state->nr_written; i++)
+		if (!hashcmp(state->written[i]->sha1, sha1))
+			return 1;
+	return 0;
+}
+
 static void deflate_to_pack(struct bulk_checkin_state *state,
 			    unsigned char sha1[],
 			    int fd, size_t size, enum object_type type,
@@ -64,6 +75,7 @@ static void deflate_to_pack(struct bulk_checkin_state *state,
 	int write_object = (flags & HASH_WRITE_OBJECT);
 	int status = Z_OK;
 	struct pack_idx_entry *idx = NULL;
+	struct sha1file_checkpoint checkpoint;
 
 	hdrlen = sprintf((char *)obuf, "%s %" PRIuMAX,
 			 typename(type), (uintmax_t)size) + 1;
@@ -73,6 +85,7 @@ static void deflate_to_pack(struct bulk_checkin_state *state,
 	if (write_object) {
 		idx = xcalloc(1, sizeof(*idx));
 		idx->offset = state->offset;
+		sha1file_checkpoint(state->f, &checkpoint);
 		crc32_begin(state->f);
 	}
 	memset(&s, 0, sizeof(s));
@@ -121,10 +134,17 @@ static void deflate_to_pack(struct bulk_checkin_state *state,
 	git_SHA1_Final(sha1, &ctx);
 	if (write_object) {
 		idx->crc32 = crc32_end(state->f);
-		hashcpy(idx->sha1, sha1);
-		ALLOC_GROW(state->written,
-			   state->nr_written + 1, state->alloc_written);
-		state->written[state->nr_written++] = idx;
+
+		if (already_written(state, sha1)) {
+			sha1file_truncate(state->f, &checkpoint);
+			state->offset = checkpoint.offset;
+			free(idx);
+		} else {
+			hashcpy(idx->sha1, sha1);
+			ALLOC_GROW(state->written,
+				   state->nr_written + 1, state->alloc_written);
+			state->written[state->nr_written++] = idx;
+		}
 	}
 }
 
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 36def25..fbd5ced 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -7,22 +7,28 @@ test_description='adding and checking out large blobs'
 
 test_expect_success setup '
 	git config core.bigfilethreshold 200k &&
-	echo X | dd of=large bs=1k seek=2000 &&
+	echo X | dd of=large1 bs=1k seek=2000 &&
+	echo X | dd of=large2 bs=1k seek=2000 &&
 	echo Y | dd of=huge bs=1k seek=2500
 '
 
 test_expect_success 'add a large file or two' '
-	git add large huge &&
+	git add large1 huge large2 &&
 	# make sure we got a single packfile and no loose objects
-	bad= count=0 &&
+	bad= count=0 idx= &&
 	for p in .git/objects/pack/pack-*.pack
 	do
 		count=$(( $count + 1 ))
-		test -f "$p" && continue
+		if test -f "$p" && idx=${p%.pack}.idx && test -f "$idx"
+		then
+			continue
+		fi
 		bad=t
 	done &&
 	test -z "$bad" &&
 	test $count = 1 &&
+	cnt=$(git show-index <"$idx" | wc -l) &&
+	test $cnt = 2 &&
 	for l in .git/objects/??/??????????????????????????????????????
 	do
 		test -f "$l" || continue
@@ -32,10 +38,10 @@ test_expect_success 'add a large file or two' '
 '
 
 test_expect_success 'checkout a large file' '
-	large=$(git rev-parse :large) &&
-	git update-index --add --cacheinfo 100644 $large another &&
+	large1=$(git rev-parse :large1) &&
+	git update-index --add --cacheinfo 100644 $large1 another &&
 	git checkout another &&
-	cmp large another ;# this must not be test_cmp
+	cmp large1 another ;# this must not be test_cmp
 '
 
 test_done
-- 
1.7.8.rc3.111.g7d421
Previous: Junio C HamanoNext: Junio C Hamano
Message 8 of 10 in “Bulk check-in”
  1. 0/4 Bulk check-inJunio C Hamano, Oct 28, 2011
  2. 1/4 write_pack_header(): a helper functionJunio C Hamano, Oct 28, 2011
  3. 2/4 create_tmp_packfile(): a helper functionJunio C Hamano, Oct 28, 2011
  4. 3/4 finish_tmp_packfile(): a helper functionJunio C Hamano, Oct 28, 2011
  5. 4/4 Bulk check-inJunio C Hamano, Oct 28, 2011
  6. 0/3 bulk-checkin continuedJunio C Hamano, Nov 18, 2011
  7. 1/3 csum-file: introduce sha1file_checkpointJunio C Hamano, Nov 18, 2011
  8. 2/3 bulk-checkin: do not write the same object twiceJunio C Hamano, Nov 18, 2011
  9. 3/3 bulk-checkin: do not write an object that already existsJunio C Hamano, Nov 18, 2011
  10. bulk-checkin: honor pack.packsizelimitJunio C Hamano, Nov 24, 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.