Convert read_tree{,_recursive} to support struct pathspec
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Fri, 25 Mar 2011 09:34:19 +0000 (16:34 +0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 25 Mar 2011 16:20:33 +0000 (09:20 -0700)
This patch changes behavior of the two functions. Previously it does
prefix matching only. Now it can also do wildcard matching.

All callers are updated. Some gain wildcard matching (archive,
checkout), others reset pathspec_item.has_wildcard to retain old
behavior (ls-files, ls-tree as they are plumbing).

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
archive.c
builtin/checkout.c
builtin/log.c
builtin/ls-files.c
builtin/ls-tree.c
merge-recursive.c
t/t3102-ls-tree-wildcards.sh [new file with mode: 0755]
tree.c
tree.h

index 1944ed4e4dc36addaf6a8b408703a7ff418bd26c..42f2d2fdc81a7c656e3ec006227b092addd13044 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -157,6 +157,7 @@ int write_archive_entries(struct archiver_args *args,
        struct archiver_context context;
        struct unpack_trees_options opts;
        struct tree_desc t;
+       struct pathspec pathspec;
        int err;
 
        if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
@@ -191,8 +192,10 @@ int write_archive_entries(struct archiver_args *args,
                git_attr_set_direction(GIT_ATTR_INDEX, &the_index);
        }
 
-       err = read_tree_recursive(args->tree, "", 0, 0, args->pathspec,
+       init_pathspec(&pathspec, args->pathspec);
+       err = read_tree_recursive(args->tree, "", 0, 0, &pathspec,
                                  write_archive_entry, &context);
+       free_pathspec(&pathspec);
        if (err == READ_TREE_RECURSIVE)
                err = 0;
        return err;
@@ -221,11 +224,14 @@ static int reject_entry(const unsigned char *sha1, const char *base,
 
 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;
+       const char *paths[] = { path, NULL };
+       struct pathspec pathspec;
+       int ret;
+
+       init_pathspec(&pathspec, paths);
+       ret = read_tree_recursive(tree, "", 0, 0, &pathspec, reject_entry, NULL);
+       free_pathspec(&pathspec);
+       return ret != 0;
 }
 
 static void parse_pathspec_arg(const char **pathspec,
index 757f9a08ddbaf102726a781b06d7294a4638984e..f4d4db1ee2136c5a700a12e2489a54e70bd8e615 100644 (file)
@@ -78,7 +78,10 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
 
 static int read_tree_some(struct tree *tree, const char **pathspec)
 {
-       read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL);
+       struct pathspec ps;
+       init_pathspec(&ps, pathspec);
+       read_tree_recursive(tree, "", 0, 0, &ps, update_some, NULL);
+       free_pathspec(&ps);
 
        /* update the index with the given tree's info
         * for all args, expanding wildcards, and exit
index f5ed690c435423662808fe0ff7f1e256374586db..e6bbcecda2b25b0f06f01bf2ec5d83479225353c 100644 (file)
@@ -390,6 +390,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
        struct rev_info rev;
        struct object_array_entry *objects;
        struct setup_revision_opt opt;
+       struct pathspec match_all;
        int i, count, ret = 0;
 
        git_config(git_log_config, NULL);
@@ -397,6 +398,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
        if (diff_use_color_default == -1)
                diff_use_color_default = git_use_color_default;
 
+       init_pathspec(&match_all, NULL);
        init_revisions(&rev, prefix);
        rev.diff = 1;
        rev.always_show_header = 1;
@@ -443,7 +445,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                                        diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
                                        name,
                                        diff_get_color_opt(&rev.diffopt, DIFF_RESET));
-                       read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
+                       read_tree_recursive((struct tree *)o, "", 0, 0, &match_all,
                                        show_tree_object, NULL);
                        rev.shown_one = 1;
                        break;
index fb2d5f4b1fb0ce9ef2fb0c4099b5fea6d07b6838..199af46360b4d8cefc448a2384bacd083311d76c 100644 (file)
@@ -338,7 +338,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
 {
        struct tree *tree;
        unsigned char sha1[20];
-       const char **match;
+       struct pathspec pathspec;
        struct cache_entry *last_stage0 = NULL;
        int i;
 
@@ -360,10 +360,11 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
                static const char *(matchbuf[2]);
                matchbuf[0] = prefix;
                matchbuf[1] = NULL;
-               match = matchbuf;
+               init_pathspec(&pathspec, matchbuf);
+               pathspec.items[0].has_wildcard = 0;
        } else
-               match = NULL;
-       if (read_tree(tree, 1, match))
+               init_pathspec(&pathspec, NULL);
+       if (read_tree(tree, 1, &pathspec))
                die("unable to read tree entries %s", tree_name);
 
        for (i = 0; i < active_nr; i++) {
index f73e6bd9626a0e929a513fed1fd1227c28732ec7..4290723392141938c7099eaa870bd05754f41ec4 100644 (file)
@@ -19,7 +19,7 @@ static int line_termination = '\n';
 #define LS_SHOW_SIZE 16
 static int abbrev;
 static int ls_options;
-static const char **pathspec;
+static struct pathspec pathspec;
 static int chomp_prefix;
 static const char *ls_tree_prefix;
 
@@ -35,7 +35,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
        if (ls_options & LS_RECURSIVE)
                return 1;
 
-       s = pathspec;
+       s = pathspec.raw;
        if (!s)
                return 0;
 
@@ -120,7 +120,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 {
        unsigned char sha1[20];
        struct tree *tree;
-       int full_tree = 0;
+       int i, full_tree = 0;
        const struct option ls_tree_options[] = {
                OPT_BIT('d', NULL, &ls_options, "only show trees",
                        LS_TREE_ONLY),
@@ -166,11 +166,13 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
        if (get_sha1(argv[0], sha1))
                die("Not a valid object name %s", argv[0]);
 
-       pathspec = get_pathspec(prefix, argv + 1);
+       init_pathspec(&pathspec, get_pathspec(prefix, argv + 1));
+       for (i = 0; i < pathspec.nr; i++)
+               pathspec.items[i].has_wildcard = 0;
        tree = parse_tree_indirect(sha1);
        if (!tree)
                die("not a tree object");
-       read_tree_recursive(tree, "", 0, 0, pathspec, show_tree, NULL);
+       read_tree_recursive(tree, "", 0, 0, &pathspec, show_tree, NULL);
 
        return 0;
 }
index 16c2dbeab95a0f4099e3de8badf688bb4dee8189..0645138ae5424ff2652f464c0f6fb9a6965d80e5 100644 (file)
@@ -288,7 +288,9 @@ static int save_files_dirs(const unsigned char *sha1,
 static int get_files_dirs(struct merge_options *o, struct tree *tree)
 {
        int n;
-       if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, o))
+       struct pathspec match_all;
+       init_pathspec(&match_all, NULL);
+       if (read_tree_recursive(tree, "", 0, 0, &match_all, save_files_dirs, o))
                return 0;
        n = o->current_file_set.nr + o->current_directory_set.nr;
        return n;
diff --git a/t/t3102-ls-tree-wildcards.sh b/t/t3102-ls-tree-wildcards.sh
new file mode 100755 (executable)
index 0000000..f2b2a52
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='ls-tree with(out) wildcards'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       mkdir a aa "a*" &&
+       touch a/one aa/two "a*/three" &&
+       git add a/one aa/two "a*/three" &&
+       git commit -m test
+'
+
+test_expect_success 'ls-tree a* matches literally' '
+       cat >expected <<EOF &&
+100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391   a*/three
+EOF
+       git ls-tree -r HEAD "a*" >actual &&
+       test_cmp expected actual
+'
+
+test_done
diff --git a/tree.c b/tree.c
index db3a5c3319c81a7eb94cd267a671776d46742dc0..698ecf7af13871cf9639e969f368ba5d7b2e940a 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -114,20 +114,15 @@ static int read_tree_1(struct tree *tree, struct strbuf *base,
 
 int read_tree_recursive(struct tree *tree,
                        const char *base, int baselen,
-                       int stage, const char **match,
+                       int stage, struct pathspec *pathspec,
                        read_tree_fn_t fn, void *context)
 {
        struct strbuf sb = STRBUF_INIT;
-       struct pathspec pathspec;
-       int i, ret;
+       int ret;
 
-       init_pathspec(&pathspec, match);
-       for (i = 0; i < pathspec.nr; i++)
-               pathspec.items[i].has_wildcard = 0;
        strbuf_add(&sb, base, baselen);
-       ret = read_tree_1(tree, &sb, stage, &pathspec, fn, context);
+       ret = read_tree_1(tree, &sb, stage, pathspec, fn, context);
        strbuf_release(&sb);
-       free_pathspec(&pathspec);
        return ret;
 }
 
@@ -141,7 +136,7 @@ static int cmp_cache_name_compare(const void *a_, const void *b_)
                                  ce2->name, ce2->ce_flags);
 }
 
-int read_tree(struct tree *tree, int stage, const char **match)
+int read_tree(struct tree *tree, int stage, struct pathspec *match)
 {
        read_tree_fn_t fn = NULL;
        int i, err;
diff --git a/tree.h b/tree.h
index 2ff01a4f839ecc2206fcc1c13fee9d5d202b1128..69bcb5e0ec27de6699e349b8dcec26f1cbc4e741 100644 (file)
--- a/tree.h
+++ b/tree.h
@@ -25,9 +25,9 @@ typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const ch
 
 extern int read_tree_recursive(struct tree *tree,
                               const char *base, int baselen,
-                              int stage, const char **match,
+                              int stage, struct pathspec *pathspec,
                               read_tree_fn_t fn, void *context);
 
-extern int read_tree(struct tree *tree, int stage, const char **paths);
+extern int read_tree(struct tree *tree, int stage, struct pathspec *pathspec);
 
 #endif /* TREE_H */