Code

grep: micro-optimize hit collection for AND nodes
[git.git] / archive.c
index 45d242b884c2796b67329aaabfea62cd1e7bbecb..c6aea8358f5b632ee11cb102c1ec1b6c2b317835 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -15,7 +15,7 @@ static char const * const archive_usage[] = {
 
 #define USES_ZLIB_COMPRESSION 1
 
-const struct archiver {
+static const struct archiver {
        const char *name;
        write_archive_fn_t write_archive;
        unsigned int flags;
@@ -29,11 +29,10 @@ static void format_subst(const struct commit *commit,
                          struct strbuf *buf)
 {
        char *to_free = NULL;
-       struct strbuf fmt;
+       struct strbuf fmt = STRBUF_INIT;
 
        if (src == buf->buf)
                to_free = strbuf_detach(buf, NULL);
-       strbuf_init(&fmt, 0);
        for (;;) {
                const char *b, *c;
 
@@ -65,10 +64,9 @@ static void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
 
        buffer = read_sha1_file(sha1, type, sizep);
        if (buffer && S_ISREG(mode)) {
-               struct strbuf buf;
+               struct strbuf buf = STRBUF_INIT;
                size_t size = 0;
 
-               strbuf_init(&buf, 0);
                strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
                convert_to_working_tree(path, buf.buf, buf.len, &buf);
                if (commit)
@@ -134,7 +132,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
                err = write_entry(args, sha1, path.buf, path.len, mode, NULL, 0);
                if (err)
                        return err;
-               return READ_TREE_RECURSIVE;
+               return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
        }
 
        buffer = sha1_file_to_archive(path_without_prefix, sha1, mode,
@@ -241,6 +239,19 @@ static void parse_treeish_arg(const char **argv,
        ar_args->time = archive_time;
 }
 
+static void create_output_file(const char *output_file)
+{
+       int output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
+       if (output_fd < 0)
+               die("could not create archive file: %s ", output_file);
+       if (output_fd != 1) {
+               if (dup2(output_fd, 1) < 0)
+                       die("could not redirect output");
+               else
+                       close(output_fd);
+       }
+}
+
 #define OPT__COMPR(s, v, h, p) \
        { OPTION_SET_INT, (s), NULL, (v), NULL, (h), \
          PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, (p) }
@@ -255,6 +266,7 @@ static int parse_archive_args(int argc, const char **argv,
        const char *base = NULL;
        const char *remote = NULL;
        const char *exec = NULL;
+       const char *output = NULL;
        int compression_level = -1;
        int verbose = 0;
        int i;
@@ -264,6 +276,8 @@ static int parse_archive_args(int argc, const char **argv,
                OPT_STRING(0, "format", &format, "fmt", "archive format"),
                OPT_STRING(0, "prefix", &base, "prefix",
                        "prepend prefix to each pathname in the archive"),
+               OPT_STRING(0, "output", &output, "file",
+                       "write the archive to this file"),
                OPT__VERBOSE(&verbose),
                OPT__COMPR('0', &compression_level, "store only", 0),
                OPT__COMPR('1', &compression_level, "compress faster", 1),
@@ -296,6 +310,9 @@ static int parse_archive_args(int argc, const char **argv,
        if (!base)
                base = "";
 
+       if (output)
+               create_output_file(output);
+
        if (list) {
                for (i = 0; i < ARRAY_SIZE(archivers); i++)
                        printf("%s\n", archivers[i].name);