git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
To: Git Mailing List <git@vger.kernel.org>
Cc: Junio C Hamano <junkio@cox.net>, Franck Bui-Huu <vagabon.xyz@gmail.com>
Subject: [PATCH] Add support for tgz archive format
Date: Sat, 02 Sep 2006 14:37:56 +0200	[thread overview]
Message-ID: <44F97B24.7090305@lsrfire.ath.cx> (raw)
In-Reply-To: <44F977C0.4060901@lsrfire.ath.cx>

 Documentation/git-archive-tree.txt |    9 ++---
 archive.h                          |    2 +
 builtin-archive-tree.c             |    4 +-
 builtin-tar-tree.c                 |   63 ++++++++++++++++++++++++++++++++-----
 4 files changed, 65 insertions(+), 13 deletions(-)

diff --git a/Documentation/git-archive-tree.txt b/Documentation/git-archive-tree.txt
index 122c482..25136d9 100644
--- a/Documentation/git-archive-tree.txt
+++ b/Documentation/git-archive-tree.txt
@@ -8,7 +8,7 @@ git-archive-tree - Creates a archive of the f
 
 SYNOPSIS
 --------
-'git-archive-tree' -f {tar|zip} [--prefix=<prefix>/] [-0|...|-9]
+'git-archive-tree' -f {tar|tgz|zip} [--prefix=<prefix>/] [-0|...|-9]
 	    <tree-ish> [path...]
 
 DESCRIPTION
@@ -29,7 +29,8 @@ OPTIONS
 -------
 
 -f::
-	Format of the resulting archive, can be either 'tar' or 'zip'.
+	Format of the resulting archive, can be either 'tar', 'tgz'
+	or 'zip'.
 
 <tree-ish>::
 	The tree or commit to produce an archive for.
@@ -71,11 +72,11 @@ git archive -f tar --prefix=junk/ HEAD |
 	latest commit on the current branch, and extracts it in
 	`/var/tmp/junk` directory.
 
-git archive -f tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz::
+git archive -f tgz --prefix=git-1.4.0/ v1.4.0 >git-1.4.0.tar.gz::
 
 	Create a compressed tarball for v1.4.0 release.
 
-git archive -f tar --prefix=git-1.4.0/ v1.4.0{caret}\{tree\} | gzip >git-1.4.0.tar.gz::
+git archive -f tgz --prefix=git-1.4.0/ v1.4.0{caret}\{tree\} >git-1.4.0.tar.gz::
 
 	Create a compressed tarball for v1.4.0 release, but without a
 	global extended pax header.
diff --git a/archive.h b/archive.h
index 7813962..6a03864 100644
--- a/archive.h
+++ b/archive.h
@@ -3,4 +3,6 @@ #include "tree.h"
 typedef int (*write_archive_fn_t)(struct tree *tree, const unsigned char *commit_sha1, const char *prefix, time_t time, const char **pathspec);
 
 int write_tar_archive(struct tree *tree, const unsigned char *commit_sha1, const char *prefix, time_t time, const char **pathspec);
+int write_tgz_archive(struct tree *tree, const unsigned char *commit_sha1,
+                      const char *prefix, time_t time, const char **pathspec);
 int write_zip_archive(struct tree *tree, const unsigned char *commit_sha1, const char *prefix, time_t time, const char **pathspec);
diff --git a/builtin-archive-tree.c b/builtin-archive-tree.c
index 2c6ee60..f61e26d 100644
--- a/builtin-archive-tree.c
+++ b/builtin-archive-tree.c
@@ -9,12 +9,14 @@ #include "tree-walk.h"
 #include "archive.h"
 
 static const char archive_usage[] =
-"git-archive-tree -f {tar|zip} [--prefix=<prefix>/] [-0|...|-9] <tree-ish> [path...]";
+"git-archive-tree -f {tar|tgz|zip} [--prefix=<prefix>/] [-0|...|-9] <tree-ish> [path...]";
 
 static write_archive_fn_t parse_archive_format(const char *format)
 {
 	if (!strcmp(format, "tar"))
 		return write_tar_archive;
+	if (!strcmp(format, "tgz"))
+		return write_tgz_archive;
 	if (!strcmp(format, "zip"))
 		return write_zip_archive;
 	return NULL;
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index e0da01e..743d53a 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -23,6 +23,10 @@ static unsigned long offset;
 static time_t archive_time;
 static int tar_umask;
 
+static gzFile gzstdout;
+
+typedef void (*blocked_write_fn)(const void *data, unsigned long size);
+
 /* writes out the whole block, but only if it is full */
 static void write_if_needed(void)
 {
@@ -36,7 +40,7 @@ static void write_if_needed(void)
  * queues up writes, so that all our write(2) calls write exactly one
  * full block; pads writes to RECORDSIZE
  */
-static void write_blocked(const void *data, unsigned long size)
+static void do_write_blocked(const void *data, unsigned long size)
 {
 	const char *buf = data;
 	unsigned long tail;
@@ -68,19 +72,20 @@ static void write_blocked(const void *da
 	write_if_needed();
 }
 
+static blocked_write_fn write_blocked = do_write_blocked;
+
 /*
  * The end of tar archives is marked by 2*512 nul bytes and after that
  * follows the rest of the block (if any).
  */
 static void write_trailer(void)
 {
-	int tail = BLOCKSIZE - offset;
-	memset(block + offset, 0, tail);
-	write_or_die(1, block, BLOCKSIZE);
-	if (tail < 2 * RECORDSIZE) {
-		memset(block, 0, offset);
-		write_or_die(1, block, BLOCKSIZE);
-	}
+	char zeroes[RECORDSIZE];
+	memset(zeroes, 0, RECORDSIZE);
+	write_blocked(zeroes, RECORDSIZE);
+	write_blocked(zeroes, RECORDSIZE);
+	while (offset)
+		write_blocked(zeroes, RECORDSIZE);
 }
 
 static void strbuf_append_string(struct strbuf *sb, const char *s)
@@ -404,6 +409,48 @@ int write_tar_archive(struct tree *tree,
 	return 0;
 }
 
+static void write_blocked_gzip(const void *data, unsigned long size)
+{
+	const char *p = data;
+	int written;
+	unsigned long tail = size % RECORDSIZE;
+
+	while (size > 0) {
+		written = gzwrite(gzstdout, p, size);
+		if (written == 0) {
+			if (errno == EPIPE)
+				exit(0);
+			die("gzwrite error (%s)", strerror(errno));
+		}
+		size -= written;
+		p += written;
+	}
+
+	if (tail) {
+		z_off_t result = gzseek(gzstdout, RECORDSIZE - tail, SEEK_CUR);
+		if (result == -1)
+			die("gzseek error (%s)", strerror(errno));
+	}
+}
+
+int write_tgz_archive(struct tree *tree, const unsigned char *commit_sha1,
+                      const char *prefix, time_t time, const char **pathspec)
+{
+	int result;
+
+	gzstdout = gzdopen(1, "wb");
+	if (!gzstdout)
+		die("zlib is unable to open stdout");
+
+	write_blocked = write_blocked_gzip;
+	result = write_tar_archive(tree, commit_sha1, prefix, time, pathspec); 
+
+	if (gzclose(gzstdout) != Z_OK)
+		result = 1;
+
+	return result;
+}
+
 static const char *exec = "git-upload-tar";
 
 static int remote_tar(int argc, const char **argv)

-- 
VGER BF report: U 0.497484

  reply	other threads:[~2006-09-02 12:38 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-09-02 12:23 [PATCH][RFC] Add git-archive-tree Rene Scharfe
2006-09-02 12:37 ` Rene Scharfe [this message]
2006-09-02 13:10 ` Rene Scharfe
2006-09-02 20:13   ` Franck Bui-Huu
2006-09-04 18:22     ` Rene Scharfe
2006-09-04 20:09       ` Junio C Hamano
2006-09-04 22:02         ` Rene Scharfe
2006-09-04 22:20           ` Junio C Hamano
2006-09-05 11:43             ` Franck Bui-Huu
2006-09-02 21:19   ` Junio C Hamano
2006-09-02 14:17 ` Rene Scharfe
2006-09-02 15:24 ` Franck Bui-Huu
2006-09-02 16:08   ` Rene Scharfe
2006-09-02 21:27 ` Junio C Hamano
2006-09-06 18:05   ` Rene Scharfe
2006-09-06 21:47     ` Junio C Hamano
2006-09-17 11:54       ` Rene 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=44F97B24.7090305@lsrfire.ath.cx \
    --to=rene.scharfe@lsrfire.ath.cx \
    --cc=git@vger.kernel.org \
    --cc=junkio@cox.net \
    --cc=vagabon.xyz@gmail.com \
    /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).