Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- archive-tar.c | 38 +++++++++++++++++++++++++++++++++++--- t/t1050-large.sh | 4 ++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/archive-tar.c b/archive-tar.c index 61821f4..865ef6d 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -4,6 +4,7 @@ #include "cache.h" #include "tar.h" #include "archive.h" +#include "streaming.h" #include "run-command.h" #define RECORDSIZE (512) @@ -62,6 +63,29 @@ static void write_blocked(const void *data, unsigned long size) write_if_needed(); } +static int stream_blob_to_file(const unsigned char *sha1) +{ + struct git_istream *st; + enum object_type type; + unsigned long sz; + + st = open_istream(sha1, &type, &sz, NULL); + if (!st) + return error("cannot stream blob %s", sha1_to_hex(sha1)); + for (;;) { + char buf[BLOCKSIZE]; + ssize_t readlen; + + readlen = read_istream(st, buf, sizeof(buf)); + + if (readlen <= 0) + return readlen; + write_blocked(buf, readlen); + } + close_istream(st); + return 0; +} + /* * The end of tar archives is marked by 2*512 nul bytes and after that * follows the rest of the block (if any). @@ -203,7 +227,11 @@ static int write_tar_entry(struct archiver_args *args, } else memcpy(header.name, path, pathlen); - if (S_ISLNK(mode) || S_ISREG(mode)) { + if (S_ISREG(mode) && !args->convert && + sha1_object_info(sha1, &size) == OBJ_BLOB && + size > big_file_threshold) + buffer = NULL; + else if (S_ISLNK(mode) || S_ISREG(mode)) { enum object_type type; buffer = sha1_file_to_archive(args, path, sha1, old_mode, &type, &size); if (!buffer) @@ -233,8 +261,12 @@ static int write_tar_entry(struct archiver_args *args, } strbuf_release(&ext_header); write_blocked(&header, sizeof(header)); - if (S_ISREG(mode) && buffer && size > 0) - write_blocked(buffer, size); + if (S_ISREG(mode) && size > 0) { + if (buffer) + write_blocked(buffer, size); + else + err = stream_blob_to_file(sha1); + } return err; } diff --git a/t/t1050-large.sh b/t/t1050-large.sh index 4d127f1..fe47554 100755 --- a/t/t1050-large.sh +++ b/t/t1050-large.sh @@ -134,4 +134,8 @@ test_expect_success 'repack' ' git repack -ad ' +test_expect_success 'tar achiving' ' + git archive --format=tar HEAD >/dev/null +' + test_done -- 1.7.8.36.g69ee2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html