Skip to content

Commit 4ea94a8

Browse files
r1walzdscho
authored andcommitted
archive: optionally use zlib directly for gzip compression
As we already link to the zlib library, we can perform the compression without even requiring gzip on the host machine. Note: the `-n` flag that `git archive` passed to `gzip` wants to ensure that a reproducible file is written, i.e. no filename or mtime will be recorded in the compressed output. This is already the default for zlib's `gzopen()` function (if the file name or mtime should be recorded, the `deflateSetHeader()` function would have to be called instead). Note also that the `gzFile` datatype is defined as a pointer in `zlib.h`, i.e. we can rely on the fact that it can be `NULL`. At this point, this new mode is hidden behind the pseudo command `:zlib`: assign this magic string to the `archive.tgz.command` config setting to enable it. Signed-off-by: Rohit Ashiwal <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent ac2b248 commit 4ea94a8

File tree

1 file changed

+37
-10
lines changed

1 file changed

+37
-10
lines changed

archive-tar.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ static unsigned long offset;
1717

1818
static int tar_umask = 002;
1919

20+
static gzFile gzip;
21+
2022
static int write_tar_filter_archive(const struct archiver *ar,
2123
struct archiver_args *args);
2224

@@ -40,7 +42,10 @@ static int write_tar_filter_archive(const struct archiver *ar,
4042

4143
/* writes out the whole block, or dies if fails */
4244
static void write_block_or_die(const char *block) {
43-
write_or_die(1, block, BLOCKSIZE);
45+
if (!gzip)
46+
write_or_die(1, block, BLOCKSIZE);
47+
else if (gzwrite(gzip, block, (unsigned) BLOCKSIZE) != BLOCKSIZE)
48+
die(_("gzwrite failed"));
4449
}
4550

4651
/* writes out the whole block, but only if it is full */
@@ -459,18 +464,40 @@ static int write_tar_filter_archive(const struct archiver *ar,
459464
filter.use_shell = 1;
460465
filter.in = -1;
461466

462-
if (start_command(&filter) < 0)
463-
die_errno(_("unable to start '%s' filter"), argv[0]);
464-
close(1);
465-
if (dup2(filter.in, 1) < 0)
466-
die_errno(_("unable to redirect descriptor"));
467-
close(filter.in);
467+
if (!strcmp(":zlib", ar->data)) {
468+
struct strbuf mode = STRBUF_INIT;
469+
470+
strbuf_addstr(&mode, "wb");
471+
472+
if (args->compression_level >= 0 && args->compression_level <= 9)
473+
strbuf_addf(&mode, "%d", args->compression_level);
474+
475+
gzip = gzdopen(fileno(stdout), mode.buf);
476+
if (!gzip)
477+
die(_("Could not gzdopen stdout"));
478+
strbuf_release(&mode);
479+
} else {
480+
if (start_command(&filter) < 0)
481+
die_errno(_("unable to start '%s' filter"), argv[0]);
482+
close(1);
483+
if (dup2(filter.in, 1) < 0)
484+
die_errno(_("unable to redirect descriptor"));
485+
close(filter.in);
486+
}
468487

469488
r = write_tar_archive(ar, args);
470489

471-
close(1);
472-
if (finish_command(&filter) != 0)
473-
die(_("'%s' filter reported error"), argv[0]);
490+
if (gzip) {
491+
int ret = gzclose(gzip);
492+
if (ret == Z_ERRNO)
493+
die_errno(_("gzclose failed"));
494+
else if (ret != Z_OK)
495+
die(_("gzclose failed (%d)"), ret);
496+
} else {
497+
close(1);
498+
if (finish_command(&filter) != 0)
499+
die(_("'%s' filter reported error"), argv[0]);
500+
}
474501

475502
strbuf_release(&cmd);
476503
return r;

0 commit comments

Comments
 (0)