git-archive: convert archive entries like checkouts do
authorRené Scharfe <rene.scharfe@lsrfire.ath.cx>
Fri, 18 May 2007 22:09:41 +0000 (00:09 +0200)
committerJunio C Hamano <junkio@cox.net>
Fri, 18 May 2007 23:36:45 +0000 (16:36 -0700)
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>
Signed-off-by: Junio C Hamano <junkio@cox.net>
archive-tar.c
archive-zip.c
cache.h
convert.c

index 56ff356966c002a0d0a86b1b0d88a3ae60718172..33e76576f149d89922deda1de5548be7bc42d0eb 100644 (file)
@@ -82,12 +82,13 @@ 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;
+       if (total + 1 > sb->alloc) {
+               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';
 }
 
 /*
@@ -270,20 +271,21 @@ static int write_tar_entry(const unsigned char *sha1,
                path.alloc = PATH_MAX;
                path.len = path.eof = 0;
        }
-       if (path.alloc < baselen + filenamelen) {
+       if (path.alloc < baselen + filenamelen + 1) {
                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));
        }
index 1eaf262b7410e08f529ac48b9d56a131ba2a3ab3..3cbf6bb8ac4045803140ca5019126015e817155e 100644 (file)
@@ -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 aaeb04a1b9f756d946b06cad8561625ead9bb8a9..4204bc168c11fc7f8764e7d92e5935d2dc30c3bd 100644 (file)
--- 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);
index 12abdaf2a5ce6ffd1a186b8201fb0a8d3b8d11f1..c64880bdf589028af7ac67cd12e8aa55b41b1fc7 100644 (file)
--- 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;
+}