From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
"René Scharfe" <rene.scharfe@lsrfire.ath.cx>,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH v3 9/9] archive-zip: streaming for deflated files
Date: Thu, 3 May 2012 08:51:08 +0700 [thread overview]
Message-ID: <1336009868-7411-10-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1336009868-7411-1-git-send-email-pclouds@gmail.com>
From: René Scharfe <rene.scharfe@lsrfire.ath.cx>
After an entry has been streamed out, its CRC and sizes are written as
part of a data descriptor.
For simplicity, we make the buffer for the compressed chunks twice as
big as for the uncompressed ones, to be sure the result fit in even
if deflate makes them bigger.
t5000 verifies output. t1050 makes sure the command always respects
core.bigfilethreshold
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
archive-zip.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++-
t/t1050-large.sh | 4 +++
t/t5000-tar-tree.sh | 7 +++++
3 files changed, 74 insertions(+), 1 deletions(-)
diff --git a/archive-zip.c b/archive-zip.c
index 1c6c39d..f5af81f 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -211,7 +211,7 @@ static int write_zip_entry(struct archiver_args *args,
compressed_size = size;
if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
- size > big_file_threshold && method == 0) {
+ size > big_file_threshold) {
stream = open_istream(sha1, &type, &size, NULL);
if (!stream)
return error("cannot stream blob %s",
@@ -308,6 +308,68 @@ static int write_zip_entry(struct archiver_args *args,
zip_offset += ZIP_DATA_DESC_SIZE;
set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
+ } else if (stream && method == 8) {
+ unsigned char buf[STREAM_BUFFER_SIZE];
+ ssize_t readlen;
+ git_zstream zstream;
+ int result;
+ size_t out_len;
+ unsigned char compressed[STREAM_BUFFER_SIZE * 2];
+
+ memset(&zstream, 0, sizeof(zstream));
+ git_deflate_init(&zstream, args->compression_level);
+
+ compressed_size = 0;
+ zstream.next_out = compressed;
+ zstream.avail_out = sizeof(compressed);
+
+ for (;;) {
+ readlen = read_istream(stream, buf, sizeof(buf));
+ if (readlen <= 0)
+ break;
+ crc = crc32(crc, buf, readlen);
+
+ zstream.next_in = buf;
+ zstream.avail_in = readlen;
+ result = git_deflate(&zstream, 0);
+ if (result != Z_OK)
+ die("deflate error (%d)", result);
+ out = compressed;
+ if (!compressed_size)
+ out += 2;
+ out_len = zstream.next_out - out;
+
+ if (out_len > 0) {
+ write_or_die(1, out, out_len);
+ compressed_size += out_len;
+ zstream.next_out = compressed;
+ zstream.avail_out = sizeof(compressed);
+ }
+
+ }
+ close_istream(stream);
+ if (readlen)
+ return readlen;
+
+ zstream.next_in = buf;
+ zstream.avail_in = 0;
+ result = git_deflate(&zstream, Z_FINISH);
+ if (result != Z_STREAM_END)
+ die("deflate error (%d)", result);
+
+ git_deflate_end(&zstream);
+ out = compressed;
+ if (!compressed_size)
+ out += 2;
+ out_len = zstream.next_out - out - 4;
+ write_or_die(1, out, out_len);
+ compressed_size += out_len;
+ zip_offset += compressed_size;
+
+ write_zip_data_desc(size, compressed_size, crc);
+ zip_offset += ZIP_DATA_DESC_SIZE;
+
+ set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
} else if (compressed_size > 0) {
write_or_die(1, out, compressed_size);
zip_offset += compressed_size;
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 9db54b5..55ed955 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -142,4 +142,8 @@ test_expect_success 'zip achiving, store only' '
git archive --format=zip -0 HEAD >/dev/null
'
+test_expect_success 'zip achiving, deflate' '
+ git archive --format=zip HEAD >/dev/null
+'
+
test_done
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 3b54c38..94f2eba 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -250,6 +250,13 @@ test_expect_success UNZIP 'git archive -0 --format=zip on large files' '
(mkdir large && cd large && $UNZIP ../large.zip)
'
+test_expect_success UNZIP 'git archive --format=zip on large files' '
+ test_config core.bigfilethreshold 1 &&
+ git archive --format=zip HEAD >large-compressed.zip &&
+ (mkdir large-compressed && cd large-compressed && $UNZIP ../large-compressed.zip) &&
+ test_cmp large-compressed/a/bin/sh large/a/bin/sh
+'
+
test_expect_success \
'git archive --list outside of a git repo' \
'GIT_DIR=some/non-existing/directory git archive --list'
--
1.7.3.1.256.g2539c.dirty
next prev parent reply other threads:[~2012-05-03 1:53 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-03 1:50 [PATCH v3 0/9] Large file support for git-archive Nguyễn Thái Ngọc Duy
2012-05-03 1:51 ` [PATCH v3 1/9] streaming: void pointer instead of char pointer Nguyễn Thái Ngọc Duy
2012-05-03 1:51 ` [PATCH v3 2/9] archive-tar: turn write_tar_entry into blob-writing only Nguyễn Thái Ngọc Duy
2012-05-03 1:51 ` [PATCH v3 3/9] archive-tar: unindent write_tar_entry by one level Nguyễn Thái Ngọc Duy
2012-05-03 1:51 ` [PATCH v3 4/9] archive: delegate blob reading to backend Nguyễn Thái Ngọc Duy
2012-05-03 1:51 ` [PATCH v3 5/9] archive-tar: stream large blobs to tar file Nguyễn Thái Ngọc Duy
2012-05-03 1:51 ` [PATCH v3 6/9] archive-zip: remove uncompressed_size Nguyễn Thái Ngọc Duy
2012-05-03 1:51 ` [PATCH v3 7/9] archive-zip: factor out helpers for writing sizes and CRC Nguyễn Thái Ngọc Duy
2012-05-03 1:51 ` [PATCH v3 8/9] archive-zip: streaming for stored files Nguyễn Thái Ngọc Duy
2012-05-03 1:51 ` Nguyễn Thái Ngọc Duy [this message]
2012-05-03 8:52 ` [PATCH 10/9] t5000: rationalize unzip tests René Scharfe
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=1336009868-7411-10-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=rene.scharfe@lsrfire.ath.cx \
/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).