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

[PATCH] git-archive: convert archive entries like checkouts do

From
René Scharfe <rene.scharfe@lsrfire.ath.cx>
Date
May 18, 2007, 22:09 UTC
Message-ID
<464E2425.2030904@lsrfire.ath.cx>
In-Reply-To
<200705171928.34927.johan@herland.net>

As noted by Johan Herland, git-archive is a kind of checkout and needs to apply any checkout filters that might be configured.

This patch adds the convenience function convert_sha1_file which returns a buffer containing the object's contents, after converting, if necessary (i.e. it's a combination of read_sha1_file and convert_to_working_tree). Direct calls to read_sha1_file in git-archive are then replaced by calls to convert_sha1_file.

Since convert_sha1_file expects its path argument to be NUL-terminated -- a convention it inherits from convert_to_working_tree -- the patch also changes the path handling in archive-tar.c to always NUL-terminate the string. It used to solely rely on the len field of struct strbuf before.

archive-zip.c already NUL-terminates the path and thus needs no such change.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
 archive-tar.c |   12 +++++++-----
 archive-zip.c |    2 +-
 cache.h       |    1 +
 convert.c     |   15 +++++++++++++++
 4 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/archive-tar.c b/archive-tar.c
index 56ff356..eb0abc7 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -83,11 +83,12 @@ static void strbuf_append_string(struct strbuf *sb, const char *s)
 	int slen = strlen(s);
 	int total = sb->len + slen;
 	if (total > sb->alloc) {
-		sb->buf = xrealloc(sb->buf, total);
-		sb->alloc = total;
+		sb->buf = xrealloc(sb->buf, total + 1);
+		sb->alloc = total + 1;
 	}
 	memcpy(sb->buf + sb->len, s, slen);
 	sb->len = total;
+	sb->buf[total] = '\0';
 }
 
 /*
@@ -272,18 +273,19 @@ static int write_tar_entry(const unsigned char *sha1,
 	}
 	if (path.alloc < baselen + filenamelen) {
 		free(path.buf);
-		path.buf = xmalloc(baselen + filenamelen);
-		path.alloc = baselen + filenamelen;
+		path.buf = xmalloc(baselen + filenamelen + 1);
+		path.alloc = baselen + filenamelen + 1;
 	}
 	memcpy(path.buf, base, baselen);
 	memcpy(path.buf + baselen, filename, filenamelen);
 	path.len = baselen + filenamelen;
+	path.buf[path.len] = '\0';
 	if (S_ISDIR(mode) || S_ISDIRLNK(mode)) {
 		strbuf_append_string(&path, "/");
 		buffer = NULL;
 		size = 0;
 	} else {
-		buffer = read_sha1_file(sha1, &type, &size);
+		buffer = convert_sha1_file(path.buf, sha1, mode, &type, &size);
 		if (!buffer)
 			die("cannot read %s", sha1_to_hex(sha1));
 	}
diff --git a/archive-zip.c b/archive-zip.c
index 1eaf262..3cbf6bb 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -195,7 +195,7 @@ static int write_zip_entry(const unsigned char *sha1,
 		if (S_ISREG(mode) && zlib_compression_level != 0)
 			method = 8;
 		result = 0;
-		buffer = read_sha1_file(sha1, &type, &size);
+		buffer = convert_sha1_file(path, sha1, mode, &type, &size);
 		if (!buffer)
 			die("cannot read %s", sha1_to_hex(sha1));
 		crc = crc32(crc, buffer, size);
diff --git a/cache.h b/cache.h
index aaeb04a..4204bc1 100644
--- a/cache.h
+++ b/cache.h
@@ -548,6 +548,7 @@ extern void trace_argv_printf(const char **argv, int count, const char *format,
 /* convert.c */
 extern char *convert_to_git(const char *path, const char *src, unsigned long *sizep);
 extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep);
+extern void *convert_sha1_file(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size);
 
 /* match-trees.c */
 void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int);
diff --git a/convert.c b/convert.c
index 12abdaf..c64880b 100644
--- a/convert.c
+++ b/convert.c
@@ -652,3 +652,18 @@ char *convert_to_working_tree(const char *path, const char *src, unsigned long *
 
 	return buf;
 }
+
+void *convert_sha1_file(const char *path, const unsigned char *sha1,
+                        unsigned int mode, enum object_type *type,
+                        unsigned long *size)
+{
+	void *buffer = read_sha1_file(sha1, type, size);
+	if (S_ISREG(mode) && buffer) {
+		void *converted = convert_to_working_tree(path, buffer, size);
+		if (converted) {
+			free(buffer);
+			buffer = converted;
+		}
+	}
+	return buffer;
+}
Previous: Johan HerlandNext: Daniel Barkalow
Message 6 of 38 in “Commit ID in exported Tar Ball”
  1. Thomas GlanzmannMay 17, 2007
  2. Johan HerlandMay 17, 2007
  3. Frank LichtenheldMay 17, 2007
  4. Thomas GlanzmannMay 17, 2007
  5. Johan HerlandMay 17, 2007
  6. git-archive: convert archive entries like checkouts doRené Scharfe, May 18, 2007
  7. Daniel BarkalowMay 18, 2007
  8. René ScharfeMay 18, 2007
  9. René ScharfeMay 19, 2007
  10. Junio C HamanoMay 19, 2007
  11. A Large Angry SCMMay 19, 2007
  12. René ScharfeMay 20, 2007
  13. René ScharfeMay 20, 2007
  14. Shawn O. PearceMay 20, 2007
  15. René ScharfeMay 20, 2007
  16. Shawn O. PearceMay 21, 2007
  17. Petr BaudisMay 21, 2007
  18. René ScharfeMay 21, 2007
  19. René ScharfeMay 22, 2007
  20. Junio C HamanoMay 22, 2007
  21. René ScharfeMay 22, 2007
  22. Shawn O. PearceMay 23, 2007
  23. René ScharfeMay 20, 2007
  24. Thomas GlanzmannMay 20, 2007
  25. Brian GernhardtMay 20, 2007
  26. Thomas GlanzmannMay 20, 2007
  27. Peter BaumannMay 21, 2007
  28. Thomas GlanzmannMay 21, 2007
  29. Shawn O. PearceMay 21, 2007
  30. Thomas GlanzmannMay 21, 2007
  31. Shawn O. PearceMay 21, 2007
  32. Thomas GlanzmannMay 21, 2007
  33. Brian GernhardtMay 21, 2007
  34. Thomas GlanzmannMay 21, 2007
  35. Frank LichtenheldMay 17, 2007
  36. Johan HerlandMay 17, 2007
  37. Kristian HøgsbergMay 17, 2007
  38. Thomas GlanzmannMay 17, 2007

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.