{"thread":{"id":"14453","subject":"[PATCH 5/6] archive: unify file attribute handling","startedAt":"2008-07-14T19:22:05Z","lastAt":"2008-07-15T07:49:38Z","messageCount":6,"participants":["René Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"83294","messageId":"487BA75D.7080208@lsrfire.ath.cx","threadId":"14453","inReplyTo":"487B92FC.5030103@lsrfire.ath.cx","subject":"[PATCH 6/6] archive: remove extra arguments parsing code","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2008-07-14T19:22:05Z","receivedAt":"2008-07-14T19:22:05Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Replace the code that calls backend specific argument parsers by a\nsimple flag mechanism.  This reduces code size and complexity.\n\nWe can add back such a mechanism (based on incremental parse_opt(),\nperhaps) when we need it.  The compression level parameter, though,\nis going to be shared by future compressing backends like tgz.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n archive-zip.c     |   13 -------------\n archive.h         |    6 +-----\n builtin-archive.c |   29 ++++++++++++++++-------------\n 3 files changed, 17 insertions(+), 31 deletions(-)\n\ndiff --git a/archive-zip.c b/archive-zip.c\nindex 8131289..d56e5cf 100644\n--- a/archive-zip.c\n+++ b/archive-zip.c\n@@ -282,16 +282,3 @@ int write_zip_archive(struct archiver_args *args)\n \n \treturn err;\n }\n-\n-void *parse_extra_zip_args(int argc, const char **argv)\n-{\n-\tfor (; argc > 0; argc--, argv++) {\n-\t\tconst char *arg = argv[0];\n-\n-\t\tif (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\\0')\n-\t\t\tzlib_compression_level = arg[1] - '0';\n-\t\telse\n-\t\t\tdie(\"Unknown argument for zip format: %s\", arg);\n-\t}\n-\treturn NULL;\n-}\ndiff --git a/archive.h b/archive.h\nindex 88ee3be..96bb1cd 100644\n--- a/archive.h\n+++ b/archive.h\n@@ -13,19 +13,16 @@ struct archiver_args {\n \ttime_t time;\n \tconst char **pathspec;\n \tunsigned int verbose : 1;\n-\tvoid *extra;\n };\n \n typedef int (*write_archive_fn_t)(struct archiver_args *);\n \n-typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv);\n-\n typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, void *buffer, unsigned long size);\n \n struct archiver {\n \tconst char *name;\n \twrite_archive_fn_t write_archive;\n-\tparse_extra_args_fn_t parse_extra;\n+\tunsigned int flags;\n };\n \n extern int parse_archive_args(int argc, const char **argv, const struct archiver **ar, struct archiver_args *args);\n@@ -41,7 +38,6 @@ extern void parse_pathspec_arg(const char **pathspec,\n  */\n extern int write_tar_archive(struct archiver_args *);\n extern int write_zip_archive(struct archiver_args *);\n-extern void *parse_extra_zip_args(int argc, const char **argv);\n \n extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);\n \ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex e7f4ec6..88204bf 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -15,9 +15,11 @@\n static const char archive_usage[] = \\\n \"git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]\";\n \n+#define USES_ZLIB_COMPRESSION 1\n+\n const struct archiver archivers[] = {\n-\t{ \"tar\", write_tar_archive, NULL },\n-\t{ \"zip\", write_zip_archive, parse_extra_zip_args },\n+\t{ \"tar\", write_tar_archive },\n+\t{ \"zip\", write_zip_archive, USES_ZLIB_COMPRESSION },\n };\n \n static int run_remote_archiver(const char *remote, int argc,\n@@ -137,10 +139,9 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,\n int parse_archive_args(int argc, const char **argv, const struct archiver **ar,\n \t\tstruct archiver_args *args)\n {\n-\tconst char *extra_argv[MAX_EXTRA_ARGS];\n-\tint extra_argc = 0;\n \tconst char *format = \"tar\";\n \tconst char *base = \"\";\n+\tint compression_level = -1;\n \tint verbose = 0;\n \tint i;\n \n@@ -168,12 +169,12 @@ int parse_archive_args(int argc, const char **argv, const struct archiver **ar,\n \t\t\ti++;\n \t\t\tbreak;\n \t\t}\n-\t\tif (arg[0] == '-') {\n-\t\t\tif (extra_argc > MAX_EXTRA_ARGS - 1)\n-\t\t\t\tdie(\"Too many extra options\");\n-\t\t\textra_argv[extra_argc++] = arg;\n+\t\tif (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\\0') {\n+\t\t\tcompression_level = arg[1] - '0';\n \t\t\tcontinue;\n \t\t}\n+\t\tif (arg[0] == '-')\n+\t\t\tdie(\"Unknown argument: %s\", arg);\n \t\tbreak;\n \t}\n \n@@ -184,11 +185,13 @@ int parse_archive_args(int argc, const char **argv, const struct archiver **ar,\n \tif (!*ar)\n \t\tdie(\"Unknown archive format '%s'\", format);\n \n-\tif (extra_argc) {\n-\t\tif (!(*ar)->parse_extra)\n-\t\t\tdie(\"'%s' format does not handle %s\",\n-\t\t\t    (*ar)->name, extra_argv[0]);\n-\t\targs->extra = (*ar)->parse_extra(extra_argc, extra_argv);\n+\tif (compression_level != -1) {\n+\t\tif ((*ar)->flags & USES_ZLIB_COMPRESSION)\n+\t\t\tzlib_compression_level = compression_level;\n+\t\telse {\n+\t\t\tdie(\"Argument not supported for format '%s': -%d\",\n+\t\t\t\t\tformat, compression_level);\n+\t\t}\n \t}\n \targs->verbose = verbose;\n \targs->base = base;\n-- \n1.5.6.2.212.g08b51\n"},{"id":"83296","messageId":"487BA764.2060003@lsrfire.ath.cx","threadId":"14453","inReplyTo":"487B92FC.5030103@lsrfire.ath.cx","subject":"[PATCH 2/6] add context pointer to read_tree_recursive()","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2008-07-14T19:22:12Z","receivedAt":"2008-07-14T19:22:12Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add a pointer parameter to read_tree_recursive(), which is passed to the\ncallback function.  This allows callers of read_tree_recursive() to\nshare data with the callback without resorting to global variables.  All\ncurrent callers pass NULL.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n archive-tar.c             |   11 ++++++-----\n archive-zip.c             |   11 ++++++-----\n builtin-checkout.c        |    4 ++--\n builtin-log.c             |    4 ++--\n builtin-ls-tree.c         |    4 ++--\n builtin-merge-recursive.c |    4 ++--\n tree.c                    |   12 ++++++------\n tree.h                    |    4 ++--\n 8 files changed, 28 insertions(+), 26 deletions(-)\n\ndiff --git a/archive-tar.c b/archive-tar.c\nindex 99db58f..6eaf59e 100644\n--- a/archive-tar.c\n+++ b/archive-tar.c\n@@ -234,9 +234,9 @@ static int git_tar_config(const char *var, const char *value, void *cb)\n \treturn git_default_config(var, value, cb);\n }\n \n-static int write_tar_entry(const unsigned char *sha1,\n-                           const char *base, int baselen,\n-                           const char *filename, unsigned mode, int stage)\n+static int write_tar_entry(const unsigned char *sha1, const char *base,\n+\t\tint baselen, const char *filename, unsigned mode, int stage,\n+\t\tvoid *context)\n {\n \tstatic struct strbuf path = STRBUF_INIT;\n \tvoid *buffer;\n@@ -286,11 +286,12 @@ int write_tar_archive(struct archiver_args *args)\n \n \t\twhile (baselen > 0 && base[baselen - 1] == '/')\n \t\t\tbase[--baselen] = '\\0';\n-\t\twrite_tar_entry(args->tree->object.sha1, \"\", 0, base, 040777, 0);\n+\t\twrite_tar_entry(args->tree->object.sha1, \"\", 0, base, 040777,\n+\t\t\t\t0, NULL);\n \t\tfree(base);\n \t}\n \tread_tree_recursive(args->tree, args->base, plen, 0,\n-\t\t\t    args->pathspec, write_tar_entry);\n+\t\t\t    args->pathspec, write_tar_entry, NULL);\n \twrite_trailer();\n \n \treturn 0;\ndiff --git a/archive-zip.c b/archive-zip.c\nindex 5742762..0d24f3f 100644\n--- a/archive-zip.c\n+++ b/archive-zip.c\n@@ -152,9 +152,9 @@ static char *construct_path(const char *base, int baselen,\n \treturn path;\n }\n \n-static int write_zip_entry(const unsigned char *sha1,\n-                           const char *base, int baselen,\n-                           const char *filename, unsigned mode, int stage)\n+static int write_zip_entry(const unsigned char *sha1, const char *base,\n+\t\tint baselen, const char *filename, unsigned mode, int stage,\n+\t\tvoid *context)\n {\n \tstruct zip_local_header header;\n \tstruct zip_dir_header dirent;\n@@ -332,11 +332,12 @@ int write_zip_archive(struct archiver_args *args)\n \n \t\twhile (baselen > 0 && base[baselen - 1] == '/')\n \t\t\tbase[--baselen] = '\\0';\n-\t\twrite_zip_entry(args->tree->object.sha1, \"\", 0, base, 040777, 0);\n+\t\twrite_zip_entry(args->tree->object.sha1, \"\", 0, base, 040777,\n+\t\t\t\t0, NULL);\n \t\tfree(base);\n \t}\n \tread_tree_recursive(args->tree, args->base, plen, 0,\n-\t\t\t    args->pathspec, write_zip_entry);\n+\t\t\t    args->pathspec, write_zip_entry, NULL);\n \twrite_zip_trailer(args->commit_sha1);\n \n \tfree(zip_dir);\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex d6641c2..a542033 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -43,7 +43,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,\n }\n \n static int update_some(const unsigned char *sha1, const char *base, int baselen,\n-\t\t       const char *pathname, unsigned mode, int stage)\n+\t\tconst char *pathname, unsigned mode, int stage, void * context)\n {\n \tint len;\n \tstruct cache_entry *ce;\n@@ -67,7 +67,7 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,\n \n static int read_tree_some(struct tree *tree, const char **pathspec)\n {\n-\tread_tree_recursive(tree, \"\", 0, 0, pathspec, update_some);\n+\tread_tree_recursive(tree, \"\", 0, 0, pathspec, update_some, NULL);\n \n \t/* update the index with the given tree's info\n \t * for all args, expanding wildcards, and exit\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 430d876..617aa67 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -313,7 +313,7 @@ static int show_object(const unsigned char *sha1, int show_tag_object,\n \n static int show_tree_object(const unsigned char *sha1,\n \t\tconst char *base, int baselen,\n-\t\tconst char *pathname, unsigned mode, int stage)\n+\t\tconst char *pathname, unsigned mode, int stage, void *context)\n {\n \tprintf(\"%s%s\\n\", pathname, S_ISDIR(mode) ? \"/\" : \"\");\n \treturn 0;\n@@ -366,7 +366,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)\n \t\t\t\t\tname,\n \t\t\t\t\tdiff_get_color_opt(&rev.diffopt, DIFF_RESET));\n \t\t\tread_tree_recursive((struct tree *)o, \"\", 0, 0, NULL,\n-\t\t\t\t\tshow_tree_object);\n+\t\t\t\t\tshow_tree_object, NULL);\n \t\t\tbreak;\n \t\tcase OBJ_COMMIT:\n \t\t\trev.pending.nr = rev.pending.alloc = 0;\ndiff --git a/builtin-ls-tree.c b/builtin-ls-tree.c\nindex f4a75dd..0da047c 100644\n--- a/builtin-ls-tree.c\n+++ b/builtin-ls-tree.c\n@@ -56,7 +56,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)\n }\n \n static int show_tree(const unsigned char *sha1, const char *base, int baselen,\n-\t\t     const char *pathname, unsigned mode, int stage)\n+\t\tconst char *pathname, unsigned mode, int stage, void *context)\n {\n \tint retval = 0;\n \tconst char *type = blob_type;\n@@ -189,7 +189,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)\n \ttree = parse_tree_indirect(sha1);\n \tif (!tree)\n \t\tdie(\"not a tree object\");\n-\tread_tree_recursive(tree, \"\", 0, 0, pathspec, show_tree);\n+\tread_tree_recursive(tree, \"\", 0, 0, pathspec, show_tree, NULL);\n \n \treturn 0;\n }\ndiff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c\nindex 43bf6aa..385e742 100644\n--- a/builtin-merge-recursive.c\n+++ b/builtin-merge-recursive.c\n@@ -256,7 +256,7 @@ struct tree *write_tree_from_memory(void)\n \n static int save_files_dirs(const unsigned char *sha1,\n \t\tconst char *base, int baselen, const char *path,\n-\t\tunsigned int mode, int stage)\n+\t\tunsigned int mode, int stage, void *context)\n {\n \tint len = strlen(path);\n \tchar *newpath = xmalloc(baselen + len + 1);\n@@ -276,7 +276,7 @@ static int save_files_dirs(const unsigned char *sha1,\n static int get_files_dirs(struct tree *tree)\n {\n \tint n;\n-\tif (read_tree_recursive(tree, \"\", 0, 0, NULL, save_files_dirs) != 0)\n+\tif (read_tree_recursive(tree, \"\", 0, 0, NULL, save_files_dirs, NULL))\n \t\treturn 0;\n \tn = current_file_set.nr + current_directory_set.nr;\n \treturn n;\ndiff --git a/tree.c b/tree.c\nindex 4b1825c..03e782a 100644\n--- a/tree.c\n+++ b/tree.c\n@@ -29,7 +29,7 @@ static int read_one_entry_opt(const unsigned char *sha1, const char *base, int b\n \treturn add_cache_entry(ce, opt);\n }\n \n-static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)\n+static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)\n {\n \treturn read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,\n \t\t\t\t  ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);\n@@ -39,7 +39,7 @@ static int read_one_entry(const unsigned char *sha1, const char *base, int basel\n  * This is used when the caller knows there is no existing entries at\n  * the stage that will conflict with the entry being added.\n  */\n-static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)\n+static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)\n {\n \treturn read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,\n \t\t\t\t  ADD_CACHE_JUST_APPEND);\n@@ -92,7 +92,7 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns\n int read_tree_recursive(struct tree *tree,\n \t\t\tconst char *base, int baselen,\n \t\t\tint stage, const char **match,\n-\t\t\tread_tree_fn_t fn)\n+\t\t\tread_tree_fn_t fn, void *context)\n {\n \tstruct tree_desc desc;\n \tstruct name_entry entry;\n@@ -106,7 +106,7 @@ int read_tree_recursive(struct tree *tree,\n \t\tif (!match_tree_entry(base, baselen, entry.path, entry.mode, match))\n \t\t\tcontinue;\n \n-\t\tswitch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage)) {\n+\t\tswitch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) {\n \t\tcase 0:\n \t\t\tcontinue;\n \t\tcase READ_TREE_RECURSIVE:\n@@ -126,7 +126,7 @@ int read_tree_recursive(struct tree *tree,\n \t\t\tretval = read_tree_recursive(lookup_tree(entry.sha1),\n \t\t\t\t\t\t     newbase,\n \t\t\t\t\t\t     baselen + pathlen + 1,\n-\t\t\t\t\t\t     stage, match, fn);\n+\t\t\t\t\t\t     stage, match, fn, context);\n \t\t\tfree(newbase);\n \t\t\tif (retval)\n \t\t\t\treturn -1;\n@@ -174,7 +174,7 @@ int read_tree(struct tree *tree, int stage, const char **match)\n \n \tif (!fn)\n \t\tfn = read_one_entry_quick;\n-\terr = read_tree_recursive(tree, \"\", 0, stage, match, fn);\n+\terr = read_tree_recursive(tree, \"\", 0, stage, match, fn, NULL);\n \tif (fn == read_one_entry || err)\n \t\treturn err;\n \ndiff --git a/tree.h b/tree.h\nindex dd25c53..2ff01a4 100644\n--- a/tree.h\n+++ b/tree.h\n@@ -21,12 +21,12 @@ int parse_tree(struct tree *tree);\n struct tree *parse_tree_indirect(const unsigned char *sha1);\n \n #define READ_TREE_RECURSIVE 1\n-typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int);\n+typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int, void *);\n \n extern int read_tree_recursive(struct tree *tree,\n \t\t\t       const char *base, int baselen,\n \t\t\t       int stage, const char **match,\n-\t\t\t       read_tree_fn_t fn);\n+\t\t\t       read_tree_fn_t fn, void *context);\n \n extern int read_tree(struct tree *tree, int stage, const char **paths);\n \n-- \n1.5.6.2.212.g08b51\n"},{"id":"83298","messageId":"487BA770.2000703@lsrfire.ath.cx","threadId":"14453","inReplyTo":"487B92FC.5030103@lsrfire.ath.cx","subject":"[PATCH 4/6] archive: centralize archive entry writing","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2008-07-14T19:22:24Z","receivedAt":"2008-07-14T19:22:24Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add the exported function write_archive_entries() to archive.c, which uses\nthe new ability of read_tree_recursive() to pass a context pointer to its\ncallback in order to centralize previously duplicated code.\n\nThe new callback function write_archive_entry() does the work that every\narchiver backend needs to do: loading file contents, entering subdirectories,\nhandling file attributes, constructing the full path of the entry.  All that\ndone, it calls the backend specific write_archive_entry_fn_t function.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n archive.c     |   77 ++++++++++++++++++++++++++++++++++++++\n archive.h     |    4 ++\n archive-tar.c |  116 ++++++++++++++++++--------------------------------------\n archive-zip.c |   90 +++++++-------------------------------------\n 4 files changed, 133 insertions(+), 154 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 6502b76..58de55e 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"commit.h\"\n #include \"attr.h\"\n+#include \"archive.h\"\n \n static void format_subst(const struct commit *commit,\n                          const char *src, size_t len,\n@@ -95,3 +96,79 @@ int is_archive_path_ignored(const char *path)\n \t\treturn 0;\n \treturn ATTR_TRUE(check[0].value);\n }\n+\n+struct archiver_context {\n+\tstruct archiver_args *args;\n+\twrite_archive_entry_fn_t write_entry;\n+};\n+\n+static int write_archive_entry(const unsigned char *sha1, const char *base,\n+\t\tint baselen, const char *filename, unsigned mode, int stage,\n+\t\tvoid *context)\n+{\n+\tstatic struct strbuf path = STRBUF_INIT;\n+\tstruct archiver_context *c = context;\n+\tstruct archiver_args *args = c->args;\n+\twrite_archive_entry_fn_t write_entry = c->write_entry;\n+\tint err;\n+\tenum object_type type;\n+\tunsigned long size;\n+\tvoid *buffer;\n+\n+\tstrbuf_reset(&path);\n+\tstrbuf_grow(&path, PATH_MAX);\n+\tstrbuf_add(&path, base, baselen);\n+\tstrbuf_addstr(&path, filename);\n+\n+\tif (is_archive_path_ignored(path.buf + args->baselen))\n+\t\treturn 0;\n+\n+\tif (S_ISDIR(mode) || S_ISGITLINK(mode)) {\n+\t\tstrbuf_addch(&path, '/');\n+\t\tif (args->verbose)\n+\t\t\tfprintf(stderr, \"%.*s\\n\", (int)path.len, path.buf);\n+\t\terr = write_entry(args, sha1, path.buf, path.len, mode, NULL, 0);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t\treturn READ_TREE_RECURSIVE;\n+\t}\n+\n+\tbuffer = sha1_file_to_archive(path.buf + args->baselen, sha1, mode,\n+\t\t\t&type, &size, args->commit);\n+\tif (!buffer)\n+\t\treturn error(\"cannot read %s\", sha1_to_hex(sha1));\n+\tif (args->verbose)\n+\t\tfprintf(stderr, \"%.*s\\n\", (int)path.len, path.buf);\n+\terr = write_entry(args, sha1, path.buf, path.len, mode, buffer, size);\n+\tfree(buffer);\n+\treturn err;\n+}\n+\n+int write_archive_entries(struct archiver_args *args,\n+\t\twrite_archive_entry_fn_t write_entry)\n+{\n+\tstruct archiver_context context;\n+\tint err;\n+\n+\tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n+\t\tsize_t len = args->baselen;\n+\n+\t\twhile (len > 1 && args->base[len - 2] == '/')\n+\t\t\tlen--;\n+\t\tif (args->verbose)\n+\t\t\tfprintf(stderr, \"%.*s\\n\", (int)len, args->base);\n+\t\terr = write_entry(args, args->tree->object.sha1, args->base,\n+\t\t\t\tlen, 040777, NULL, 0);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n+\n+\tcontext.args = args;\n+\tcontext.write_entry = write_entry;\n+\n+\terr =  read_tree_recursive(args->tree, args->base, args->baselen, 0,\n+\t\t\targs->pathspec, write_archive_entry, &context);\n+\tif (err == READ_TREE_RECURSIVE)\n+\t\terr = 0;\n+\treturn err;\n+}\ndiff --git a/archive.h b/archive.h\nindex 34151f4..4e44549 100644\n--- a/archive.h\n+++ b/archive.h\n@@ -20,6 +20,8 @@ typedef int (*write_archive_fn_t)(struct archiver_args *);\n \n typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv);\n \n+typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, void *buffer, unsigned long size);\n+\n struct archiver {\n \tconst char *name;\n \twrite_archive_fn_t write_archive;\n@@ -44,4 +46,6 @@ extern void *parse_extra_zip_args(int argc, const char **argv);\n 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);\n extern int is_archive_path_ignored(const char *path);\n \n+extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);\n+\n #endif\t/* ARCHIVE_H */\ndiff --git a/archive-tar.c b/archive-tar.c\nindex 63cc2ec..f9eb726 100644\n--- a/archive-tar.c\n+++ b/archive-tar.c\n@@ -13,11 +13,7 @@\n static char block[BLOCKSIZE];\n static unsigned long offset;\n \n-static time_t archive_time;\n static int tar_umask = 002;\n-static int verbose;\n-static const struct commit *commit;\n-static size_t base_len;\n \n /* writes out the whole block, but only if it is full */\n static void write_if_needed(void)\n@@ -114,22 +110,24 @@ static unsigned int ustar_header_chksum(const struct ustar_header *header)\n \treturn chksum;\n }\n \n-static int get_path_prefix(const struct strbuf *path, int maxlen)\n+static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen)\n {\n-\tint i = path->len;\n+\tsize_t i = pathlen;\n \tif (i > maxlen)\n \t\ti = maxlen;\n \tdo {\n \t\ti--;\n-\t} while (i > 0 && path->buf[i] != '/');\n+\t} while (i > 0 && path[i] != '/');\n \treturn i;\n }\n \n-static void write_entry(const unsigned char *sha1, struct strbuf *path,\n-                        unsigned int mode, void *buffer, unsigned long size)\n+static int write_tar_entry(struct archiver_args *args,\n+\t\tconst unsigned char *sha1, const char *path, size_t pathlen,\n+\t\tunsigned int mode, void *buffer, unsigned long size)\n {\n \tstruct ustar_header header;\n \tstruct strbuf ext_header;\n+\tint err = 0;\n \n \tmemset(&header, 0, sizeof(header));\n \tstrbuf_init(&ext_header, 0);\n@@ -143,8 +141,6 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,\n \t\tmode = 0100666;\n \t\tsprintf(header.name, \"%s.paxheader\", sha1_to_hex(sha1));\n \t} else {\n-\t\tif (verbose)\n-\t\t\tfprintf(stderr, \"%.*s\\n\", (int)path->len, path->buf);\n \t\tif (S_ISDIR(mode) || S_ISGITLINK(mode)) {\n \t\t\t*header.typeflag = TYPEFLAG_DIR;\n \t\t\tmode = (mode | 0777) & ~tar_umask;\n@@ -155,24 +151,24 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,\n \t\t\t*header.typeflag = TYPEFLAG_REG;\n \t\t\tmode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask;\n \t\t} else {\n-\t\t\terror(\"unsupported file mode: 0%o (SHA1: %s)\",\n-\t\t\t      mode, sha1_to_hex(sha1));\n-\t\t\treturn;\n+\t\t\treturn error(\"unsupported file mode: 0%o (SHA1: %s)\",\n+\t\t\t\t\tmode, sha1_to_hex(sha1));\n \t\t}\n-\t\tif (path->len > sizeof(header.name)) {\n-\t\t\tint plen = get_path_prefix(path, sizeof(header.prefix));\n-\t\t\tint rest = path->len - plen - 1;\n+\t\tif (pathlen > sizeof(header.name)) {\n+\t\t\tsize_t plen = get_path_prefix(path, pathlen,\n+\t\t\t\t\tsizeof(header.prefix));\n+\t\t\tsize_t rest = pathlen - plen - 1;\n \t\t\tif (plen > 0 && rest <= sizeof(header.name)) {\n-\t\t\t\tmemcpy(header.prefix, path->buf, plen);\n-\t\t\t\tmemcpy(header.name, path->buf + plen + 1, rest);\n+\t\t\t\tmemcpy(header.prefix, path, plen);\n+\t\t\t\tmemcpy(header.name, path + plen + 1, rest);\n \t\t\t} else {\n \t\t\t\tsprintf(header.name, \"%s.data\",\n \t\t\t\t        sha1_to_hex(sha1));\n \t\t\t\tstrbuf_append_ext_header(&ext_header, \"path\",\n-\t\t\t\t                         path->buf, path->len);\n+\t\t\t\t\t\tpath, pathlen);\n \t\t\t}\n \t\t} else\n-\t\t\tmemcpy(header.name, path->buf, path->len);\n+\t\t\tmemcpy(header.name, path, pathlen);\n \t}\n \n \tif (S_ISLNK(mode) && buffer) {\n@@ -187,7 +183,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,\n \n \tsprintf(header.mode, \"%07o\", mode & 07777);\n \tsprintf(header.size, \"%011lo\", S_ISREG(mode) ? size : 0);\n-\tsprintf(header.mtime, \"%011lo\", archive_time);\n+\tsprintf(header.mtime, \"%011lo\", args->time);\n \n \tsprintf(header.uid, \"%07o\", 0);\n \tsprintf(header.gid, \"%07o\", 0);\n@@ -202,22 +198,30 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,\n \tsprintf(header.chksum, \"%07o\", ustar_header_chksum(&header));\n \n \tif (ext_header.len > 0) {\n-\t\twrite_entry(sha1, NULL, 0, ext_header.buf, ext_header.len);\n+\t\terr = write_tar_entry(args, sha1, NULL, 0, 0, ext_header.buf,\n+\t\t\t\text_header.len);\n+\t\tif (err)\n+\t\t\treturn err;\n \t}\n \tstrbuf_release(&ext_header);\n \twrite_blocked(&header, sizeof(header));\n \tif (S_ISREG(mode) && buffer && size > 0)\n \t\twrite_blocked(buffer, size);\n+\treturn err;\n }\n \n-static void write_global_extended_header(const unsigned char *sha1)\n+static int write_global_extended_header(struct archiver_args *args)\n {\n+\tconst unsigned char *sha1 = args->commit_sha1;\n \tstruct strbuf ext_header;\n+\tint err;\n \n \tstrbuf_init(&ext_header, 0);\n \tstrbuf_append_ext_header(&ext_header, \"comment\", sha1_to_hex(sha1), 40);\n-\twrite_entry(NULL, NULL, 0, ext_header.buf, ext_header.len);\n+\terr = write_tar_entry(args, NULL, NULL, 0, 0, ext_header.buf,\n+\t\t\text_header.len);\n \tstrbuf_release(&ext_header);\n+\treturn err;\n }\n \n static int git_tar_config(const char *var, const char *value, void *cb)\n@@ -234,63 +238,17 @@ static int git_tar_config(const char *var, const char *value, void *cb)\n \treturn git_default_config(var, value, cb);\n }\n \n-static int write_tar_entry(const unsigned char *sha1, const char *base,\n-\t\tint baselen, const char *filename, unsigned mode, int stage,\n-\t\tvoid *context)\n-{\n-\tstatic struct strbuf path = STRBUF_INIT;\n-\tvoid *buffer;\n-\tenum object_type type;\n-\tunsigned long size;\n-\n-\tstrbuf_reset(&path);\n-\tstrbuf_grow(&path, PATH_MAX);\n-\tstrbuf_add(&path, base, baselen);\n-\tstrbuf_addstr(&path, filename);\n-\tif (is_archive_path_ignored(path.buf + base_len))\n-\t\treturn 0;\n-\tif (S_ISDIR(mode) || S_ISGITLINK(mode)) {\n-\t\tstrbuf_addch(&path, '/');\n-\t\tbuffer = NULL;\n-\t\tsize = 0;\n-\t} else {\n-\t\tbuffer = sha1_file_to_archive(path.buf + base_len, sha1, mode,\n-\t\t\t\t&type, &size, commit);\n-\t\tif (!buffer)\n-\t\t\tdie(\"cannot read %s\", sha1_to_hex(sha1));\n-\t}\n-\n-\twrite_entry(sha1, &path, mode, buffer, size);\n-\tfree(buffer);\n-\n-\treturn READ_TREE_RECURSIVE;\n-}\n-\n int write_tar_archive(struct archiver_args *args)\n {\n-\tgit_config(git_tar_config, NULL);\n+\tint err = 0;\n \n-\tarchive_time = args->time;\n-\tverbose = args->verbose;\n-\tcommit = args->commit;\n-\tbase_len = args->baselen;\n+\tgit_config(git_tar_config, NULL);\n \n \tif (args->commit_sha1)\n-\t\twrite_global_extended_header(args->commit_sha1);\n-\n-\tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n-\t\tchar *base = xstrdup(args->base);\n-\t\tint baselen = strlen(base);\n-\n-\t\twhile (baselen > 0 && base[baselen - 1] == '/')\n-\t\t\tbase[--baselen] = '\\0';\n-\t\twrite_tar_entry(args->tree->object.sha1, \"\", 0, base, 040777,\n-\t\t\t\t0, NULL);\n-\t\tfree(base);\n-\t}\n-\tread_tree_recursive(args->tree, args->base, args->baselen, 0,\n-\t\t\t    args->pathspec, write_tar_entry, NULL);\n-\twrite_trailer();\n-\n-\treturn 0;\n+\t\terr = write_global_extended_header(args);\n+\tif (!err)\n+\t\terr = write_archive_entries(args, write_tar_entry);\n+\tif (!err)\n+\t\twrite_trailer();\n+\treturn err;\n }\ndiff --git a/archive-zip.c b/archive-zip.c\nindex d18254c..8131289 100644\n--- a/archive-zip.c\n+++ b/archive-zip.c\n@@ -9,11 +9,8 @@\n #include \"builtin.h\"\n #include \"archive.h\"\n \n-static int verbose;\n static int zip_date;\n static int zip_time;\n-static const struct commit *commit;\n-static size_t base_len;\n \n static unsigned char *zip_dir;\n static unsigned int zip_dir_size;\n@@ -128,33 +125,9 @@ static void *zlib_deflate(void *data, unsigned long size,\n \treturn buffer;\n }\n \n-static char *construct_path(const char *base, int baselen,\n-                            const char *filename, int isdir, int *pathlen)\n-{\n-\tint filenamelen = strlen(filename);\n-\tint len = baselen + filenamelen;\n-\tchar *path, *p;\n-\n-\tif (isdir)\n-\t\tlen++;\n-\tp = path = xmalloc(len + 1);\n-\n-\tmemcpy(p, base, baselen);\n-\tp += baselen;\n-\tmemcpy(p, filename, filenamelen);\n-\tp += filenamelen;\n-\tif (isdir)\n-\t\t*p++ = '/';\n-\t*p = '\\0';\n-\n-\t*pathlen = len;\n-\n-\treturn path;\n-}\n-\n-static int write_zip_entry(const unsigned char *sha1, const char *base,\n-\t\tint baselen, const char *filename, unsigned mode, int stage,\n-\t\tvoid *context)\n+static int write_zip_entry(struct archiver_args *args,\n+\t\tconst unsigned char *sha1, const char *path, size_t pathlen,\n+\t\tunsigned int mode, void *buffer, unsigned long size)\n {\n \tstruct zip_local_header header;\n \tstruct zip_dir_header dirent;\n@@ -163,33 +136,20 @@ static int write_zip_entry(const unsigned char *sha1, const char *base,\n \tunsigned long uncompressed_size;\n \tunsigned long crc;\n \tunsigned long direntsize;\n-\tunsigned long size;\n \tint method;\n-\tint result = -1;\n-\tint pathlen;\n \tunsigned char *out;\n-\tchar *path;\n-\tenum object_type type;\n-\tvoid *buffer = NULL;\n \tvoid *deflated = NULL;\n \n \tcrc = crc32(0, NULL, 0);\n \n-\tpath = construct_path(base, baselen, filename, S_ISDIR(mode), &pathlen);\n-\tif (is_archive_path_ignored(path + base_len))\n-\t\treturn 0;\n-\tif (verbose)\n-\t\tfprintf(stderr, \"%s\\n\", path);\n \tif (pathlen > 0xffff) {\n-\t\terror(\"path too long (%d chars, SHA1: %s): %s\", pathlen,\n-\t\t      sha1_to_hex(sha1), path);\n-\t\tgoto out;\n+\t\treturn error(\"path too long (%d chars, SHA1: %s): %s\",\n+\t\t\t\t(int)pathlen, sha1_to_hex(sha1), path);\n \t}\n \n \tif (S_ISDIR(mode) || S_ISGITLINK(mode)) {\n \t\tmethod = 0;\n \t\tattr2 = 16;\n-\t\tresult = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);\n \t\tout = NULL;\n \t\tuncompressed_size = 0;\n \t\tcompressed_size = 0;\n@@ -199,19 +159,13 @@ static int write_zip_entry(const unsigned char *sha1, const char *base,\n \t\t\t(mode & 0111) ? ((mode) << 16) : 0;\n \t\tif (S_ISREG(mode) && zlib_compression_level != 0)\n \t\t\tmethod = 8;\n-\t\tresult = 0;\n-\t\tbuffer = sha1_file_to_archive(path + base_len, sha1, mode,\n-\t\t\t\t&type, &size, commit);\n-\t\tif (!buffer)\n-\t\t\tdie(\"cannot read %s\", sha1_to_hex(sha1));\n \t\tcrc = crc32(crc, buffer, size);\n \t\tout = buffer;\n \t\tuncompressed_size = size;\n \t\tcompressed_size = size;\n \t} else {\n-\t\terror(\"unsupported file mode: 0%o (SHA1: %s)\", mode,\n-\t\t      sha1_to_hex(sha1));\n-\t\tgoto out;\n+\t\treturn error(\"unsupported file mode: 0%o (SHA1: %s)\", mode,\n+\t\t\t\tsha1_to_hex(sha1));\n \t}\n \n \tif (method == 8) {\n@@ -278,12 +232,9 @@ static int write_zip_entry(const unsigned char *sha1, const char *base,\n \t\tzip_offset += compressed_size;\n \t}\n \n-out:\n-\tfree(buffer);\n \tfree(deflated);\n-\tfree(path);\n \n-\treturn result;\n+\treturn 0;\n }\n \n static void write_zip_trailer(const unsigned char *sha1)\n@@ -316,31 +267,20 @@ static void dos_time(time_t *time, int *dos_date, int *dos_time)\n \n int write_zip_archive(struct archiver_args *args)\n {\n+\tint err;\n+\n \tdos_time(&args->time, &zip_date, &zip_time);\n \n \tzip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);\n \tzip_dir_size = ZIP_DIRECTORY_MIN_SIZE;\n-\tverbose = args->verbose;\n-\tcommit = args->commit;\n-\tbase_len = args->baselen;\n-\n-\tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n-\t\tchar *base = xstrdup(args->base);\n-\t\tint baselen = strlen(base);\n-\n-\t\twhile (baselen > 0 && base[baselen - 1] == '/')\n-\t\t\tbase[--baselen] = '\\0';\n-\t\twrite_zip_entry(args->tree->object.sha1, \"\", 0, base, 040777,\n-\t\t\t\t0, NULL);\n-\t\tfree(base);\n-\t}\n-\tread_tree_recursive(args->tree, args->base, args->baselen, 0,\n-\t\t\t    args->pathspec, write_zip_entry, NULL);\n-\twrite_zip_trailer(args->commit_sha1);\n+\n+\terr = write_archive_entries(args, write_zip_entry);\n+\tif (!err)\n+\t\twrite_zip_trailer(args->commit_sha1);\n \n \tfree(zip_dir);\n \n-\treturn 0;\n+\treturn err;\n }\n \n void *parse_extra_zip_args(int argc, const char **argv)\n-- \n1.5.6.2.212.g08b51\n"},{"id":"83293","messageId":"487BA775.5090700@lsrfire.ath.cx","threadId":"14453","inReplyTo":"487B92FC.5030103@lsrfire.ath.cx","subject":"[PATCH 5/6] archive: unify file attribute handling","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2008-07-14T19:22:29Z","receivedAt":"2008-07-14T19:22:29Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Now that all file attribute handling for git archive has moved to archive.c,\nwe can unexport sha1_file_to_archive() and is_archive_path_ignored() even\ndisappears.\n\nAdd setup_archive_check(), modelled after similar functions used in the code\nof other commands that support multiple file attributes.\n\nAlso remove convert_to_archive(), as it's only remaining function with\nattribute handling gone was to call format_subst() if commit was not NULL,\nwhich is now checked in sha1_file_to_archive().\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n archive.c |   63 ++++++++++++++++++++++--------------------------------------\n archive.h |    3 --\n 2 files changed, 23 insertions(+), 43 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 58de55e..b8b45ba 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -36,34 +36,9 @@ static void format_subst(const struct commit *commit,\n \tfree(to_free);\n }\n \n-static int convert_to_archive(const char *path,\n-                              const void *src, size_t len,\n-                              struct strbuf *buf,\n-                              const struct commit *commit)\n-{\n-\tstatic struct git_attr *attr_export_subst;\n-\tstruct git_attr_check check[1];\n-\n-\tif (!commit)\n-\t\treturn 0;\n-\n-\tif (!attr_export_subst)\n-\t\tattr_export_subst = git_attr(\"export-subst\", 12);\n-\n-\tcheck[0].attr = attr_export_subst;\n-\tif (git_checkattr(path, ARRAY_SIZE(check), check))\n-\t\treturn 0;\n-\tif (!ATTR_TRUE(check[0].value))\n-\t\treturn 0;\n-\n-\tformat_subst(commit, src, len, buf);\n-\treturn 1;\n-}\n-\n-void *sha1_file_to_archive(const char *path, const unsigned char *sha1,\n-                           unsigned int mode, enum object_type *type,\n-                           unsigned long *sizep,\n-                           const struct commit *commit)\n+static void *sha1_file_to_archive(const char *path, const unsigned char *sha1,\n+\t\tunsigned int mode, enum object_type *type,\n+\t\tunsigned long *sizep, const struct commit *commit)\n {\n \tvoid *buffer;\n \n@@ -75,7 +50,8 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,\n \t\tstrbuf_init(&buf, 0);\n \t\tstrbuf_attach(&buf, buffer, *sizep, *sizep + 1);\n \t\tconvert_to_working_tree(path, buf.buf, buf.len, &buf);\n-\t\tconvert_to_archive(path, buf.buf, buf.len, &buf, commit);\n+\t\tif (commit)\n+\t\t\tformat_subst(commit, buf.buf, buf.len, &buf);\n \t\tbuffer = strbuf_detach(&buf, &size);\n \t\t*sizep = size;\n \t}\n@@ -83,18 +59,17 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,\n \treturn buffer;\n }\n \n-int is_archive_path_ignored(const char *path)\n+static void setup_archive_check(struct git_attr_check *check)\n {\n \tstatic struct git_attr *attr_export_ignore;\n-\tstruct git_attr_check check[1];\n+\tstatic struct git_attr *attr_export_subst;\n \n-\tif (!attr_export_ignore)\n+\tif (!attr_export_ignore) {\n \t\tattr_export_ignore = git_attr(\"export-ignore\", 13);\n-\n+\t\tattr_export_subst = git_attr(\"export-subst\", 12);\n+\t}\n \tcheck[0].attr = attr_export_ignore;\n-\tif (git_checkattr(path, ARRAY_SIZE(check), check))\n-\t\treturn 0;\n-\treturn ATTR_TRUE(check[0].value);\n+\tcheck[1].attr = attr_export_subst;\n }\n \n struct archiver_context {\n@@ -110,6 +85,9 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,\n \tstruct archiver_context *c = context;\n \tstruct archiver_args *args = c->args;\n \twrite_archive_entry_fn_t write_entry = c->write_entry;\n+\tstruct git_attr_check check[2];\n+\tconst char *path_without_prefix;\n+\tint convert = 0;\n \tint err;\n \tenum object_type type;\n \tunsigned long size;\n@@ -119,9 +97,14 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,\n \tstrbuf_grow(&path, PATH_MAX);\n \tstrbuf_add(&path, base, baselen);\n \tstrbuf_addstr(&path, filename);\n+\tpath_without_prefix = path.buf + args->baselen;\n \n-\tif (is_archive_path_ignored(path.buf + args->baselen))\n-\t\treturn 0;\n+\tsetup_archive_check(check);\n+\tif (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) {\n+\t\tif (ATTR_TRUE(check[0].value))\n+\t\t\treturn 0;\n+\t\tconvert = ATTR_TRUE(check[1].value);\n+\t}\n \n \tif (S_ISDIR(mode) || S_ISGITLINK(mode)) {\n \t\tstrbuf_addch(&path, '/');\n@@ -133,8 +116,8 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,\n \t\treturn READ_TREE_RECURSIVE;\n \t}\n \n-\tbuffer = sha1_file_to_archive(path.buf + args->baselen, sha1, mode,\n-\t\t\t&type, &size, args->commit);\n+\tbuffer = sha1_file_to_archive(path_without_prefix, sha1, mode,\n+\t\t\t&type, &size, convert ? args->commit : NULL);\n \tif (!buffer)\n \t\treturn error(\"cannot read %s\", sha1_to_hex(sha1));\n \tif (args->verbose)\ndiff --git a/archive.h b/archive.h\nindex 4e44549..88ee3be 100644\n--- a/archive.h\n+++ b/archive.h\n@@ -43,9 +43,6 @@ extern int write_tar_archive(struct archiver_args *);\n extern int write_zip_archive(struct archiver_args *);\n extern void *parse_extra_zip_args(int argc, const char **argv);\n \n-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);\n-extern int is_archive_path_ignored(const char *path);\n-\n extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);\n \n #endif\t/* ARCHIVE_H */\n-- \n1.5.6.2.212.g08b51\n"},{"id":"83297","messageId":"487BA7C9.6090908@lsrfire.ath.cx","threadId":"14453","inReplyTo":"487B92FC.5030103@lsrfire.ath.cx","subject":"[PATCH 3/6] archive: add baselen member to struct archiver_args","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2008-07-14T19:23:53Z","receivedAt":"2008-07-14T19:23:53Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Calculate the length of base and save it in a new member of struct\narchiver_args.  This way we don't have to compute it in each of the\nformat backends.\n\nNote: parse_archive_args() guarantees that ->base won't ever be NULL.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n archive-tar.c     |    8 +++-----\n archive-zip.c     |    8 +++-----\n archive.h         |    1 +\n builtin-archive.c |    1 +\n 4 files changed, 8 insertions(+), 10 deletions(-)\n\ndiff --git a/archive-tar.c b/archive-tar.c\nindex 6eaf59e..63cc2ec 100644\n--- a/archive-tar.c\n+++ b/archive-tar.c\n@@ -268,19 +268,17 @@ static int write_tar_entry(const unsigned char\n*sha1, const char *base,\n\n int write_tar_archive(struct archiver_args *args)\n {\n-\tint plen = args->base ? strlen(args->base) : 0;\n-\n \tgit_config(git_tar_config, NULL);\n\n \tarchive_time = args->time;\n \tverbose = args->verbose;\n \tcommit = args->commit;\n-\tbase_len = args->base ? strlen(args->base) : 0;\n+\tbase_len = args->baselen;\n\n \tif (args->commit_sha1)\n \t\twrite_global_extended_header(args->commit_sha1);\n\n-\tif (args->base && plen > 0 && args->base[plen - 1] == '/') {\n+\tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n \t\tchar *base = xstrdup(args->base);\n \t\tint baselen = strlen(base);\n\n@@ -290,7 +288,7 @@ int write_tar_archive(struct archiver_args *args)\n \t\t\t\t0, NULL);\n \t\tfree(base);\n \t}\n-\tread_tree_recursive(args->tree, args->base, plen, 0,\n+\tread_tree_recursive(args->tree, args->base, args->baselen, 0,\n \t\t\t    args->pathspec, write_tar_entry, NULL);\n \twrite_trailer();\n\ndiff --git a/archive-zip.c b/archive-zip.c\nindex 0d24f3f..d18254c 100644\n--- a/archive-zip.c\n+++ b/archive-zip.c\n@@ -316,17 +316,15 @@ static void dos_time(time_t *time, int *dos_date,\nint *dos_time)\n\n int write_zip_archive(struct archiver_args *args)\n {\n-\tint plen = strlen(args->base);\n-\n \tdos_time(&args->time, &zip_date, &zip_time);\n\n \tzip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);\n \tzip_dir_size = ZIP_DIRECTORY_MIN_SIZE;\n \tverbose = args->verbose;\n \tcommit = args->commit;\n-\tbase_len = args->base ? strlen(args->base) : 0;\n+\tbase_len = args->baselen;\n\n-\tif (args->base && plen > 0 && args->base[plen - 1] == '/') {\n+\tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n \t\tchar *base = xstrdup(args->base);\n \t\tint baselen = strlen(base);\n\n@@ -336,7 +334,7 @@ int write_zip_archive(struct archiver_args *args)\n \t\t\t\t0, NULL);\n \t\tfree(base);\n \t}\n-\tread_tree_recursive(args->tree, args->base, plen, 0,\n+\tread_tree_recursive(args->tree, args->base, args->baselen, 0,\n \t\t\t    args->pathspec, write_zip_entry, NULL);\n \twrite_zip_trailer(args->commit_sha1);\n\ndiff --git a/archive.h b/archive.h\nindex 1b24ae3..34151f4 100644\n--- a/archive.h\n+++ b/archive.h\n@@ -6,6 +6,7 @@\n\n struct archiver_args {\n \tconst char *base;\n+\tsize_t baselen;\n \tstruct tree *tree;\n \tconst unsigned char *commit_sha1;\n \tconst struct commit *commit;\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex 6ee3677..e7f4ec6 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -192,6 +192,7 @@ int parse_archive_args(int argc, const char **argv,\nconst struct archiver **ar,\n \t}\n \targs->verbose = verbose;\n \targs->base = base;\n+\targs->baselen = strlen(base);\n\n \treturn i;\n }\n-- \n1.5.6.2.212.g08b51\n"},{"id":"83372","messageId":"487C5692.3020405@lsrfire.ath.cx","threadId":"14453","inReplyTo":"487BA7C9.6090908@lsrfire.ath.cx","subject":"Re: [PATCH 3/6] archive: add baselen member to struct archiver_args","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2008-07-15T07:49:38Z","receivedAt":"2008-07-15T07:49:38Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"[Resent with fixed line wrap.]\nCalculate the length of base and save it in a new member of struct\narchiver_args.  This way we don't have to compute it in each of the\nformat backends.\n\nNote: parse_archive_args() guarantees that ->base won't ever be NULL.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n archive-tar.c     |    8 +++-----\n archive-zip.c     |    8 +++-----\n archive.h         |    1 +\n builtin-archive.c |    1 +\n 4 files changed, 8 insertions(+), 10 deletions(-)\n\ndiff --git a/archive-tar.c b/archive-tar.c\nindex 6eaf59e..63cc2ec 100644\n--- a/archive-tar.c\n+++ b/archive-tar.c\n@@ -268,19 +268,17 @@ static int write_tar_entry(const unsigned char *sha1, const char *base,\n \n int write_tar_archive(struct archiver_args *args)\n {\n-\tint plen = args->base ? strlen(args->base) : 0;\n-\n \tgit_config(git_tar_config, NULL);\n \n \tarchive_time = args->time;\n \tverbose = args->verbose;\n \tcommit = args->commit;\n-\tbase_len = args->base ? strlen(args->base) : 0;\n+\tbase_len = args->baselen;\n \n \tif (args->commit_sha1)\n \t\twrite_global_extended_header(args->commit_sha1);\n \n-\tif (args->base && plen > 0 && args->base[plen - 1] == '/') {\n+\tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n \t\tchar *base = xstrdup(args->base);\n \t\tint baselen = strlen(base);\n \n@@ -290,7 +288,7 @@ int write_tar_archive(struct archiver_args *args)\n \t\t\t\t0, NULL);\n \t\tfree(base);\n \t}\n-\tread_tree_recursive(args->tree, args->base, plen, 0,\n+\tread_tree_recursive(args->tree, args->base, args->baselen, 0,\n \t\t\t    args->pathspec, write_tar_entry, NULL);\n \twrite_trailer();\n \ndiff --git a/archive-zip.c b/archive-zip.c\nindex 0d24f3f..d18254c 100644\n--- a/archive-zip.c\n+++ b/archive-zip.c\n@@ -316,17 +316,15 @@ static void dos_time(time_t *time, int *dos_date, int *dos_time)\n \n int write_zip_archive(struct archiver_args *args)\n {\n-\tint plen = strlen(args->base);\n-\n \tdos_time(&args->time, &zip_date, &zip_time);\n \n \tzip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);\n \tzip_dir_size = ZIP_DIRECTORY_MIN_SIZE;\n \tverbose = args->verbose;\n \tcommit = args->commit;\n-\tbase_len = args->base ? strlen(args->base) : 0;\n+\tbase_len = args->baselen;\n \n-\tif (args->base && plen > 0 && args->base[plen - 1] == '/') {\n+\tif (args->baselen > 0 && args->base[args->baselen - 1] == '/') {\n \t\tchar *base = xstrdup(args->base);\n \t\tint baselen = strlen(base);\n \n@@ -336,7 +334,7 @@ int write_zip_archive(struct archiver_args *args)\n \t\t\t\t0, NULL);\n \t\tfree(base);\n \t}\n-\tread_tree_recursive(args->tree, args->base, plen, 0,\n+\tread_tree_recursive(args->tree, args->base, args->baselen, 0,\n \t\t\t    args->pathspec, write_zip_entry, NULL);\n \twrite_zip_trailer(args->commit_sha1);\n \ndiff --git a/archive.h b/archive.h\nindex 1b24ae3..34151f4 100644\n--- a/archive.h\n+++ b/archive.h\n@@ -6,6 +6,7 @@\n \n struct archiver_args {\n \tconst char *base;\n+\tsize_t baselen;\n \tstruct tree *tree;\n \tconst unsigned char *commit_sha1;\n \tconst struct commit *commit;\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex 6ee3677..e7f4ec6 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -192,6 +192,7 @@ int parse_archive_args(int argc, const char **argv, const struct archiver **ar,\n \t}\n \targs->verbose = verbose;\n \targs->base = base;\n+\targs->baselen = strlen(base);\n \n \treturn i;\n }\n-- \n1.5.6.2.212.g08b51\n"}]}