Thread (1 message) 1 message, 1 author, 2019-05-02

Re: [PATCH v2 3/4] archive: optionally use zlib directly for gzip compression

From: René Scharfe <hidden>
Date: 2019-05-02 20:29:57

Am 27.04.19 um 01:27 schrieb Rohit Ashiwal via GitGitGadget:
From: Rohit Ashiwal <redacted>

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.
Technically the patch emits the gzip format using the gz* functions.
Raw zlib output with deflate* would be slightly different.  So I'd
rather use "gzip" instead of "zlib" in the magic string.

And I'm not sure about the colon as the only magic marker.  Perhaps
throw in a "git " or "git-" instead or in addition?
quoted hunk
@@ -459,18 +464,40 @@ static int write_tar_filter_archive(const struct archiver *ar,
 	filter.use_shell = 1;
 	filter.in = -1;

-	if (start_command(&filter) < 0)
-		die_errno(_("unable to start '%s' filter"), argv[0]);
-	close(1);
-	if (dup2(filter.in, 1) < 0)
-		die_errno(_("unable to redirect descriptor"));
-	close(filter.in);
+	if (!strcmp(":zlib", ar->data)) {
+		struct strbuf mode = STRBUF_INIT;
+
+		strbuf_addstr(&mode, "wb");
+
+		if (args->compression_level >= 0 && args->compression_level <= 9)
+			strbuf_addf(&mode, "%d", args->compression_level);
Using gzsetparams() to set the compression level numerically after gzdopen()
instead of baking it into the mode string feels cleaner.
+
+		gzip = gzdopen(fileno(stdout), mode.buf);
+		if (!gzip)
+			die(_("Could not gzdopen stdout"));
+		strbuf_release(&mode);
+	} else {
+		if (start_command(&filter) < 0)
+			die_errno(_("unable to start '%s' filter"), argv[0]);
+		close(1);
+		if (dup2(filter.in, 1) < 0)
+			die_errno(_("unable to redirect descriptor"));
+		close(filter.in);
+	}

 	r = write_tar_archive(ar, args);

-	close(1);
-	if (finish_command(&filter) != 0)
-		die(_("'%s' filter reported error"), argv[0]);
+	if (gzip) {
+		int ret = gzclose(gzip);
+		if (ret == Z_ERRNO)
+			die_errno(_("gzclose failed"));
+		else if (ret != Z_OK)
+			die(_("gzclose failed (%d)"), ret);
+	} else {
+		close(1);
+		if (finish_command(&filter) != 0)
+			die(_("'%s' filter reported error"), argv[0]);
+	}

 	strbuf_release(&cmd);
 	return r;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help