diff --git a/archive.c b/archive.c index 58de55e15ce8f0..b8b45bad77230b 100644 --- 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) diff --git a/archive.h b/archive.h index 4e44549fdd702c..88ee3be5420421 100644 --- a/archive.h +++ b/archive.h @@ -43,9 +43,6 @@ extern int write_tar_archive(struct archiver_args *); extern int write_zip_archive(struct archiver_args *); extern void *parse_extra_zip_args(int argc, const char **argv); -extern void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size, const struct commit *commit); -extern int is_archive_path_ignored(const char *path); - extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry); #endif /* ARCHIVE_H */