apply: remove directory that becomes empty by renaming the last file away
[gitweb.git] / archive-tar.c
index ff0f6e29292cf716ac32e8ae63a58902fcccc120..33e76576f149d89922deda1de5548be7bc42d0eb 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * Copyright (c) 2005, 2006 Rene Scharfe
  */
-#include <time.h>
 #include "cache.h"
 #include "commit.h"
 #include "strbuf.h"
@@ -16,7 +15,7 @@ static char block[BLOCKSIZE];
 static unsigned long offset;
 
 static time_t archive_time;
-static int tar_umask;
+static int tar_umask = 002;
 static int verbose;
 
 /* writes out the whole block, but only if it is full */
@@ -83,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';
 }
 
 /*
@@ -167,7 +167,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
        } else {
                if (verbose)
                        fprintf(stderr, "%.*s\n", path->len, path->buf);
-               if (S_ISDIR(mode)) {
+               if (S_ISDIR(mode) || S_ISDIRLNK(mode)) {
                        *header.typeflag = TYPEFLAG_DIR;
                        mode = (mode | 0777) & ~tar_umask;
                } else if (S_ISLNK(mode)) {
@@ -211,11 +211,10 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
        sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0);
        sprintf(header.mtime, "%011lo", archive_time);
 
-       /* XXX: should we provide more meaningful info here? */
        sprintf(header.uid, "%07o", 0);
        sprintf(header.gid, "%07o", 0);
-       strlcpy(header.uname, "git", sizeof(header.uname));
-       strlcpy(header.gname, "git", sizeof(header.gname));
+       strlcpy(header.uname, "root", sizeof(header.uname));
+       strlcpy(header.gname, "root", sizeof(header.gname));
        sprintf(header.devmajor, "%07o", 0);
        sprintf(header.devminor, "%07o", 0);
 
@@ -264,7 +263,7 @@ static int write_tar_entry(const unsigned char *sha1,
        static struct strbuf path;
        int filenamelen = strlen(filename);
        void *buffer;
-       char type[20];
+       enum object_type type;
        unsigned long size;
 
        if (!path.alloc) {
@@ -272,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;
-       if (S_ISDIR(mode)) {
+       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));
        }