git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] GIT: Create tar archives of tree on the fly

From
Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Date
Apr 30, 2005, 01:22 UTC
Message-ID
<20050430012258.GA13930@lsrfire.ath.cx>
In-Reply-To
<Pine.LNX.4.58.0504291522250.18901@ppc970.osdl.org>
On Fri, Apr 29, 2005 at 03:26:14PM -0700, Linus Torvalds wrote:
Show 5 quoted lines
> 
> 
> Having just done the git-0.7.tar.gz file with git-tar-tree, I started 
> wondering if there is some nice way to encode the commit version that got 
> tarred up into the tar archive itself.

... and here is the patch that changes git-tar-tree to add the commit ID as a comment in a global pax header to the tar file. Archivers ignore this field. A little sample program is included to read the ID from a previously prepared archive.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>

Write commit ID to global extended pax header at the beginning of the tar file, if possible. get-tar-commit-id.c is an example program to get the ID back out of such a tar archive.

--- commit 716d21c45ba1c329fb88febf4704a4ab629a3933 tree 72f4d42eac2cd9099a663c16cb8201f90a8ff9c9 parent 0fc65a4572625405ff6dd9d8c16d835f2b1ebd49 author Rene Scharfe <rene.scharfe@lsrfire.ath.cx> 1114812895 +0200 committer Rene Scharfe <rene.scharfe@lsrfire.ath.cx> 1114812895 +0200

Index: get-tar-commit-id.c
===================================================================
--- /dev/null  (tree:c1546808797f6a3c4e6ae82069cee3dc316fbf24)
+++ 72f4d42eac2cd9099a663c16cb8201f90a8ff9c9/get-tar-commit-id.c  (mode:100644 sha1:a1a17e53d29136df431d2a128292d7aefefaea41)
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define HEADERSIZE	1024
+
+int main(int argc, char **argv)
+{
+	char buffer[HEADERSIZE];
+	ssize_t n;
+
+	n = read(0, buffer, HEADERSIZE);
+	if (n < HEADERSIZE) {
+		fprintf(stderr, "read error\n");
+		return 3;
+	}
+	if (buffer[156] != 'g')
+		return 1;
+	if (memcmp(&buffer[512], "52 comment=", 11))
+		return 1;
+	n = write(1, &buffer[523], 41);
+	if (n < 41) {
+		fprintf(stderr, "write error\n");
+		return 2;
+	}
+	return 0;
+}
Index: tar-tree.c
===================================================================
--- c1546808797f6a3c4e6ae82069cee3dc316fbf24/tar-tree.c  (mode:100644 sha1:5cc7cfef6db1269d81589b82255537fb64ba02fa)
+++ 72f4d42eac2cd9099a663c16cb8201f90a8ff9c9/tar-tree.c  (mode:100644 sha1:ea7ea91add54532c38dde9e343efe34d56805341)
@@ -160,7 +160,7 @@
 	return len;
 }
 
-static void write_header(const char *, const char *, struct path_prefix *,
+static void write_header(const char *, char, const char *, struct path_prefix *,
                          const char *, unsigned int, unsigned long);
 
 /* stores a pax extended header directly in the block buffer */
@@ -169,7 +169,7 @@
                                   struct path_prefix *prefix,
                                   const char *path, unsigned int namelen)
 {
-	char *records, *p;
+	char *p;
 	unsigned int size = 1 + 6 + namelen + 1;
 	if (size > 9)
 		size++;
@@ -177,12 +177,10 @@
 		size++;
 	if (size > RECORDSIZE)
 		die("tar-tree: extended header too big, wtf?");
-	write_header(NULL, NULL, NULL, headerfilename, 0100600, size);
-
-	records = block + offset;
-	memset(records, 0, RECORDSIZE);
+	write_header(NULL, 'x', NULL, NULL, headerfilename, 0100600, size);
+	p = block + offset;
+	memset(p, 0, RECORDSIZE);
 	offset += RECORDSIZE;
-	p = records;
 	append_long(&p, size);
 	append_string(&p, " path=");
 	append_path(&p, is_dir, basepath, prefix, path);
@@ -190,8 +188,22 @@
 	write_if_needed();
 }
 
+static void write_global_extended_header(const char *sha1)
+{
+	char *p;
+	write_header(NULL, 'g', NULL, NULL, "pax_global_header", 0, 52);
+	p = block + offset;
+	memset(p, 0, RECORDSIZE);
+	offset += RECORDSIZE;
+	append_long(&p, 52);	/* 2 + 9 + 40 + 1 */
+	append_string(&p, " comment=");
+	append_string(&p, sha1_to_hex(sha1));
+	append_char(&p, '\n');
+	write_if_needed();
+}
+
 /* stores a ustar header directly in the block buffer */
-static void write_header(const char *sha1, const char *basepath,
+static void write_header(const char *sha1, char typeflag, const char *basepath,
                          struct path_prefix *prefix, const char *path,
                          unsigned int mode, unsigned long size)
 {
@@ -236,11 +248,7 @@
 	sprintf(&header[124], "%011lo", S_ISDIR(mode) ? 0 : size);
 	sprintf(&header[136], "%011lo", archive_time);
 
-	/* typeflag */
-	if (!sha1)
-		header[156] = 'x';	/* extended header */
-	else
-		header[156] = S_ISDIR(mode) ? '5' : '0';
+	header[156] = typeflag;
 
 	memcpy(&header[257], "ustar", 6);
 	memcpy(&header[263], "00", 2);
@@ -279,7 +287,8 @@
 		eltbuf = read_sha1_file(sha1, elttype, &eltsize);
 		if (!eltbuf)
 			die("cannot read %s", sha1_to_hex(sha1));
-		write_header(sha1, basedir, prefix, path, mode, eltsize);
+		write_header(sha1, S_ISDIR(mode) ? '5' : '0', basedir,
+		             prefix, path, mode, eltsize);
 		if (!strcmp(elttype, "tree")) {
 			this_prefix.name = path;
 			traverse_tree(eltbuf, eltsize, &this_prefix);
@@ -320,6 +329,7 @@
 int main(int argc, char **argv)
 {
 	unsigned char sha1[20];
+	unsigned char commit_sha1[20];
 	void *buffer;
 	unsigned long size;
 
@@ -339,8 +349,9 @@
 	if (!sha1_file_directory)
 		sha1_file_directory = DEFAULT_DB_ENVIRONMENT;
 
-	buffer = read_object_with_reference(sha1, "commit", &size, NULL);
+	buffer = read_object_with_reference(sha1, "commit", &size, commit_sha1);
 	if (buffer) {
+		write_global_extended_header(commit_sha1);
 		archive_time = commit_time(buffer, size);
 		free(buffer);
 	}
@@ -351,7 +362,7 @@
 	if (!archive_time)
 		archive_time = time(NULL);
 	if (basedir)
-		write_header("0", NULL, NULL, basedir, 040755, 0);
+		write_header("0", '5', NULL, NULL, basedir, 040755, 0);
 	traverse_tree(buffer, size, NULL);
 	free(buffer);
 	write_trailer();
Previous: Rene Scharfe
Message 4 of 4 in “GIT: Create tar archives of tree on the fly”
  1. GIT: Create tar archives of tree on the flyRene Scharfe, Apr 26, 2005
  2. Linus TorvaldsApr 29, 2005
  3. Rene ScharfeApr 30, 2005
  4. Rene ScharfeApr 30, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.