Merge branch 'master' (early part) into pd/bash-4-completion
[gitweb.git] / archive.c
index 0cc79d2a240ac260fec66e6c30e28b438bcb5948..f59afda6ffda02920a50cabe1eb3e764221199ba 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -7,9 +7,9 @@
 #include "unpack-trees.h"
 
 static char const * const archive_usage[] = {
-       "git archive [options] <tree-ish> [path...]",
+       "git archive [options] <tree-ish> [<path>...]",
        "git archive --list",
-       "git archive --remote <repo> [--exec <cmd>] [options] <tree-ish> [path...]",
+       "git archive --remote <repo> [--exec <cmd>] [options] <tree-ish> [<path>...]",
        "git archive --remote <repo> [--exec <cmd>] --list",
        NULL
 };
@@ -31,6 +31,9 @@ static void format_subst(const struct commit *commit,
 {
        char *to_free = NULL;
        struct strbuf fmt = STRBUF_INIT;
+       struct pretty_print_context ctx = {0};
+       ctx.date_mode = DATE_NORMAL;
+       ctx.abbrev = DEFAULT_ABBREV;
 
        if (src == buf->buf)
                to_free = strbuf_detach(buf, NULL);
@@ -48,7 +51,7 @@ static void format_subst(const struct commit *commit,
                strbuf_add(&fmt, b + 8, c - b - 8);
 
                strbuf_add(buf, src, b - src);
-               format_commit_message(commit, fmt.buf, buf, DATE_NORMAL);
+               format_commit_message(commit, fmt.buf, buf, &ctx);
                len -= c + 1 - src;
                src  = c + 1;
        }
@@ -85,8 +88,8 @@ static void setup_archive_check(struct git_attr_check *check)
        static struct git_attr *attr_export_subst;
 
        if (!attr_export_ignore) {
-               attr_export_ignore = git_attr("export-ignore", 13);
-               attr_export_subst = git_attr("export-subst", 12);
+               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;
@@ -209,10 +212,33 @@ static const struct archiver *lookup_archiver(const char *name)
        return NULL;
 }
 
+static int reject_entry(const unsigned char *sha1, const char *base,
+                       int baselen, const char *filename, unsigned mode,
+                       int stage, void *context)
+{
+       return -1;
+}
+
+static int path_exists(struct tree *tree, const char *path)
+{
+       const char *pathspec[] = { path, NULL };
+
+       if (read_tree_recursive(tree, "", 0, 0, pathspec, reject_entry, NULL))
+               return 1;
+       return 0;
+}
+
 static void parse_pathspec_arg(const char **pathspec,
                struct archiver_args *ar_args)
 {
-       ar_args->pathspec = get_pathspec("", pathspec);
+       ar_args->pathspec = pathspec = get_pathspec("", pathspec);
+       if (pathspec) {
+               while (*pathspec) {
+                       if (!path_exists(ar_args->tree, *pathspec))
+                               die("path not found: %s", *pathspec);
+                       pathspec++;
+               }
+       }
 }
 
 static void parse_treeish_arg(const char **argv,