Merge branch 'ph/checkout'
[gitweb.git] / archive.c
index 58de55e15ce8f00d65de440191285c32f9fc79e1..b8b45bad77230b0258622e993dbbac3a20e3716c 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -36,34 +36,9 @@ static void format_subst(const struct commit *commit,
        free(to_free);
 }
 
-static int convert_to_archive(const char *path,
-                              const void *src, size_t len,
-                              struct strbuf *buf,
-                              const struct commit *commit)
-{
-       static struct git_attr *attr_export_subst;
-       struct git_attr_check check[1];
-
-       if (!commit)
-               return 0;
-
-       if (!attr_export_subst)
-               attr_export_subst = git_attr("export-subst", 12);
-
-       check[0].attr = attr_export_subst;
-       if (git_checkattr(path, ARRAY_SIZE(check), check))
-               return 0;
-       if (!ATTR_TRUE(check[0].value))
-               return 0;
-
-       format_subst(commit, src, len, buf);
-       return 1;
-}
-
-void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
-                           unsigned int mode, enum object_type *type,
-                           unsigned long *sizep,
-                           const struct commit *commit)
+static void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
+               unsigned int mode, enum object_type *type,
+               unsigned long *sizep, const struct commit *commit)
 {
        void *buffer;
 
@@ -75,7 +50,8 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
                strbuf_init(&buf, 0);
                strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
                convert_to_working_tree(path, buf.buf, buf.len, &buf);
-               convert_to_archive(path, buf.buf, buf.len, &buf, commit);
+               if (commit)
+                       format_subst(commit, buf.buf, buf.len, &buf);
                buffer = strbuf_detach(&buf, &size);
                *sizep = size;
        }
@@ -83,18 +59,17 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
        return buffer;
 }
 
-int is_archive_path_ignored(const char *path)
+static void setup_archive_check(struct git_attr_check *check)
 {
        static struct git_attr *attr_export_ignore;
-       struct git_attr_check check[1];
+       static struct git_attr *attr_export_subst;
 
-       if (!attr_export_ignore)
+       if (!attr_export_ignore) {
                attr_export_ignore = git_attr("export-ignore", 13);
-
+               attr_export_subst = git_attr("export-subst", 12);
+       }
        check[0].attr = attr_export_ignore;
-       if (git_checkattr(path, ARRAY_SIZE(check), check))
-               return 0;
-       return ATTR_TRUE(check[0].value);
+       check[1].attr = attr_export_subst;
 }
 
 struct archiver_context {
@@ -110,6 +85,9 @@ 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 convert = 0;
        int err;
        enum object_type type;
        unsigned long size;
@@ -119,9 +97,14 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
        strbuf_grow(&path, PATH_MAX);
        strbuf_add(&path, base, baselen);
        strbuf_addstr(&path, filename);
+       path_without_prefix = path.buf + args->baselen;
 
-       if (is_archive_path_ignored(path.buf + args->baselen))
-               return 0;
+       setup_archive_check(check);
+       if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) {
+               if (ATTR_TRUE(check[0].value))
+                       return 0;
+               convert = ATTR_TRUE(check[1].value);
+       }
 
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
                strbuf_addch(&path, '/');
@@ -133,8 +116,8 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
                return READ_TREE_RECURSIVE;
        }
 
-       buffer = sha1_file_to_archive(path.buf + args->baselen, sha1, mode,
-                       &type, &size, args->commit);
+       buffer = sha1_file_to_archive(path_without_prefix, sha1, mode,
+                       &type, &size, convert ? args->commit : NULL);
        if (!buffer)
                return error("cannot read %s", sha1_to_hex(sha1));
        if (args->verbose)