connect: split git:// setup into a separate function
[gitweb.git] / archive.c
index dde1ab4c79f87c00ffdd42c37073f459e76da315..1e41f4bbeb1d8730da83aad12bc8987abedcad8a 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "config.h"
 #include "refs.h"
 #include "commit.h"
 #include "tree-walk.h"
@@ -87,19 +88,6 @@ void *sha1_file_to_archive(const struct archiver_args *args,
        return buffer;
 }
 
-static void setup_archive_check(struct git_attr_check *check)
-{
-       static struct git_attr *attr_export_ignore;
-       static struct git_attr *attr_export_subst;
-
-       if (!attr_export_ignore) {
-               attr_export_ignore = git_attr("export-ignore");
-               attr_export_subst = git_attr("export-subst");
-       }
-       check[0].attr = attr_export_ignore;
-       check[1].attr = attr_export_subst;
-}
-
 struct directory {
        struct directory *up;
        struct object_id oid;
@@ -115,6 +103,24 @@ struct archiver_context {
        struct directory *bottom;
 };
 
+static const struct attr_check *get_archive_attrs(const char *path)
+{
+       static struct attr_check *check;
+       if (!check)
+               check = attr_check_initl("export-ignore", "export-subst", NULL);
+       return git_check_attr(path, check) ? NULL : check;
+}
+
+static int check_attr_export_ignore(const struct attr_check *check)
+{
+       return check && ATTR_TRUE(check->items[0].value);
+}
+
+static int check_attr_export_subst(const struct attr_check *check)
+{
+       return check && ATTR_TRUE(check->items[1].value);
+}
+
 static int write_archive_entry(const unsigned char *sha1, const char *base,
                int baselen, const char *filename, unsigned mode, int stage,
                void *context)
@@ -123,9 +129,8 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
        struct archiver_context *c = context;
        struct archiver_args *args = c->args;
        write_archive_entry_fn_t write_entry = c->write_entry;
-       struct git_attr_check check[2];
-       const char *path_without_prefix;
        int err;
+       const char *path_without_prefix;
 
        args->convert = 0;
        strbuf_reset(&path);
@@ -137,11 +142,12 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
                strbuf_addch(&path, '/');
        path_without_prefix = path.buf + args->baselen;
 
-       setup_archive_check(check);
-       if (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) {
-               if (ATTR_TRUE(check[0].value))
+       if (!S_ISDIR(mode)) {
+               const struct attr_check *check;
+               check = get_archive_attrs(path_without_prefix);
+               if (check_attr_export_ignore(check))
                        return 0;
-               args->convert = ATTR_TRUE(check[1].value);
+               args->convert = check_attr_export_subst(check);
        }
 
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
@@ -158,14 +164,6 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
        return write_entry(args, sha1, path.buf, path.len, mode);
 }
 
-static int write_archive_entry_buf(const unsigned char *sha1, struct strbuf *base,
-               const char *filename, unsigned mode, int stage,
-               void *context)
-{
-       return write_archive_entry(sha1, base->buf, base->len,
-                                    filename, mode, stage, context);
-}
-
 static void queue_directory(const unsigned char *sha1,
                struct strbuf *base, const char *filename,
                unsigned mode, int stage, struct archiver_context *c)
@@ -215,6 +213,17 @@ static int queue_or_write_archive_entry(const unsigned char *sha1,
        }
 
        if (S_ISDIR(mode)) {
+               size_t baselen = base->len;
+               const struct attr_check *check;
+
+               /* Borrow base, but restore its original value when done. */
+               strbuf_addstr(base, filename);
+               strbuf_addch(base, '/');
+               check = get_archive_attrs(base->buf);
+               strbuf_setlen(base, baselen);
+
+               if (check_attr_export_ignore(check))
+                       return 0;
                queue_directory(sha1, base, filename,
                                mode, stage, c);
                return READ_TREE_RECURSIVE;
@@ -268,9 +277,7 @@ int write_archive_entries(struct archiver_args *args,
        }
 
        err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec,
-                                 args->pathspec.has_wildcard ?
-                                 queue_or_write_archive_entry :
-                                 write_archive_entry_buf,
+                                 queue_or_write_archive_entry,
                                  &context);
        if (err == READ_TREE_RECURSIVE)
                err = 0;
@@ -369,10 +376,10 @@ static void parse_treeish_arg(const char **argv,
                free(ref);
        }
 
-       if (get_sha1(name, oid.hash))
+       if (get_oid(name, &oid))
                die("Not a valid object name");
 
-       commit = lookup_commit_reference_gently(oid.hash, 1);
+       commit = lookup_commit_reference_gently(&oid, 1);
        if (commit) {
                commit_sha1 = commit->object.oid.hash;
                archive_time = commit->date;
@@ -381,7 +388,7 @@ static void parse_treeish_arg(const char **argv,
                archive_time = time(NULL);
        }
 
-       tree = parse_tree_indirect(oid.hash);
+       tree = parse_tree_indirect(&oid);
        if (tree == NULL)
                die("not a tree object");
 
@@ -395,7 +402,7 @@ static void parse_treeish_arg(const char **argv,
                if (err || !S_ISDIR(mode))
                        die("current working directory is untracked");
 
-               tree = parse_tree_indirect(tree_oid.hash);
+               tree = parse_tree_indirect(&tree_oid);
        }
        ar_args->tree = tree;
        ar_args->commit_sha1 = commit_sha1;
@@ -504,15 +511,11 @@ static int parse_archive_args(int argc, const char **argv,
 }
 
 int write_archive(int argc, const char **argv, const char *prefix,
-                 int setup_prefix, const char *name_hint, int remote)
+                 const char *name_hint, int remote)
 {
-       int nongit = 0;
        const struct archiver *ar = NULL;
        struct archiver_args args;
 
-       if (setup_prefix && prefix == NULL)
-               prefix = setup_git_directory_gently(&nongit);
-
        git_config_get_bool("uploadarchive.allowunreachable", &remote_allow_unreachable);
        git_config(git_default_config, NULL);
 
@@ -520,7 +523,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
        init_zip_archiver();
 
        argc = parse_archive_args(argc, argv, &ar, &args, name_hint, remote);
-       if (nongit) {
+       if (!startup_info->have_repository) {
                /*
                 * We know this will die() with an error, so we could just
                 * die ourselves; but its error message will be more specific