This revision of this series should address all of the problems brought up with
v3.

* indent output example in patch 5/6.
* fix ':' in submodule names and add a test to verify.
* cleanup some comments.
* fixed tests to test the case where a submodule isn't at the root of a
  repository.
* always pass --threads=%d in order to limit threads to child proccess.

Brandon Williams (6):
  submodules: add helper functions to determine presence of submodules
  submodules: load gitmodules file from commit sha1
  grep: add submodules as a grep source type
  grep: optionally recurse into submodules
  grep: enable recurse-submodules to work on <tree> objects
  grep: search history of moved submodules

 Documentation/git-grep.txt         |  14 ++
 builtin/grep.c                     | 393 ++++++++++++++++++++++++++++++++++---
 cache.h                            |   2 +
 config.c                           |   8 +-
 git.c                              |   2 +-
 grep.c                             |  16 +-
 grep.h                             |   1 +
 submodule-config.c                 |   6 +-
 submodule-config.h                 |   3 +
 submodule.c                        |  50 +++++
 submodule.h                        |   3 +
 t/t7814-grep-recurse-submodules.sh | 213 ++++++++++++++++++++
 12 files changed, 679 insertions(+), 32 deletions(-)
 create mode 100755 t/t7814-grep-recurse-submodules.sh

-- interdiff based on 'bw/grep-recurse-submodules'

diff --git a/builtin/grep.c b/builtin/grep.c
index 1cd2be9..747b0c3 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -518,9 +518,8 @@ static void compile_submodule_options(const struct grep_opt 
*opt,
         * This is to prevent potential fork-bomb behavior of git-grep as each
         * submodule process has its own thread pool.
         */
-       if (num_threads)
-               argv_array_pushf(&submodule_options, "--threads=%d",
-                                (num_threads + 1) / 2);
+       argv_array_pushf(&submodule_options, "--threads=%d",
+                        (num_threads + 1) / 2);
 
        /* Add Pathspecs */
        argv_array_push(&submodule_options, "--");
@@ -542,7 +541,7 @@ static int grep_submodule_launch(struct grep_opt *opt,
        struct work_item *w = opt->output_priv;
 
        end_of_base = strchr(gs->name, ':');
-       if (end_of_base)
+       if (gs->identifier && end_of_base)
                name = end_of_base + 1;
        else
                name = gs->name;
@@ -558,13 +557,13 @@ static int grep_submodule_launch(struct grep_opt *opt,
 
        /*
         * Add basename of parent project
-        * When performing grep on a <tree> object the filename is prefixed
-        * with the object's name: '<tree-name>:filename'.  In order to
+        * When performing grep on a tree object the filename is prefixed
+        * with the object's name: 'tree-name:filename'.  In order to
         * provide uniformity of output we want to pass the name of the
         * parent project's object name to the submodule so the submodule can
         * prefix its output with the parent's name and not its own SHA1.
         */
-       if (end_of_base)
+       if (gs->identifier && end_of_base)
                argv_array_pushf(&cp.args, "--parent-basename=%.*s",
                                 (int) (end_of_base - gs->name),
                                 gs->name);
@@ -572,7 +571,7 @@ static int grep_submodule_launch(struct grep_opt *opt,
        /* Add options */
        for (i = 0; i < submodule_options.argc; i++) {
                /*
-                * If there is a <tree> identifier for the submodule, add the
+                * If there is a tree identifier for the submodule, add the
                 * rev after adding the submodule options but before the
                 * pathspecs.  To do this we listen for the '--' and insert the
                 * sha1 before pushing the '--' onto the child process argv
@@ -615,17 +614,20 @@ static int grep_submodule_launch(struct grep_opt *opt,
 static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
                          const char *filename, const char *path)
 {
-       if (!(is_submodule_initialized(path) &&
-             is_submodule_populated(path))) {
+       if (!is_submodule_initialized(path))
+               return 0;
+       if (!is_submodule_populated(path)) {
                /*
                 * If searching history, check for the presense of the
                 * submodule's gitdir before skipping the submodule.
                 */
                if (sha1) {
-                       path = git_path("modules/%s",
-                                       submodule_from_path(null_sha1, 
path)->name);
+                       const struct submodule *sub =
+                                       submodule_from_path(null_sha1, path);
+                       if (sub)
+                               path = git_path("modules/%s", sub->name);
 
-                       if (!(is_directory(path) && is_git_directory(path)))
+                       if(!(is_directory(path) && is_git_directory(path)))
                                return 0;
                } else {
                        return 0;
diff --git a/t/t7814-grep-recurse-submodules.sh 
b/t/t7814-grep-recurse-submodules.sh
index ee173ad..7d66716 100755
--- a/t/t7814-grep-recurse-submodules.sh
+++ b/t/t7814-grep-recurse-submodules.sh
@@ -60,7 +60,7 @@ test_expect_success 'grep and nested submodules' '
        submodule/sub/a:foobar
        EOF
 
-       git grep -e "bar" --recurse-submodules > actual &&
+       git grep -e "bar" --recurse-submodules >actual &&
        test_cmp expect actual
 '
 
@@ -71,7 +71,7 @@ test_expect_success 'grep and multiple patterns' '
        submodule/sub/a:foobar
        EOF
 
-       git grep -e "bar" --and -e "foo" --recurse-submodules > actual &&
+       git grep -e "bar" --and -e "foo" --recurse-submodules >actual &&
        test_cmp expect actual
 '
 
@@ -80,7 +80,7 @@ test_expect_success 'grep and multiple patterns' '
        b/b:bar
        EOF
 
-       git grep -e "bar" --and --not -e "foo" --recurse-submodules > actual &&
+       git grep -e "bar" --and --not -e "foo" --recurse-submodules >actual &&
        test_cmp expect actual
 '
 
@@ -92,7 +92,7 @@ test_expect_success 'basic grep tree' '
        HEAD:submodule/sub/a:foobar
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD > actual &&
+       git grep -e "bar" --recurse-submodules HEAD >actual &&
        test_cmp expect actual
 '
 
@@ -103,7 +103,7 @@ test_expect_success 'grep tree HEAD^' '
        HEAD^:submodule/a:foobar
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD^ > actual &&
+       git grep -e "bar" --recurse-submodules HEAD^ >actual &&
        test_cmp expect actual
 '
 
@@ -113,7 +113,7 @@ test_expect_success 'grep tree HEAD^^' '
        HEAD^^:b/b:bar
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD^^ > actual &&
+       git grep -e "bar" --recurse-submodules HEAD^^ >actual &&
        test_cmp expect actual
 '
 
@@ -123,49 +123,80 @@ test_expect_success 'grep tree and pathspecs' '
        HEAD:submodule/sub/a:foobar
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD -- submodule > actual &&
+       git grep -e "bar" --recurse-submodules HEAD -- submodule >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'grep recurse submodule colon in name' '
+       git init parent &&
+       test_when_finished "rm -rf parent" &&
+       echo "foobar" >"parent/fi:le" &&
+       git -C parent add "fi:le" &&
+       git -C parent commit -m "add fi:le" &&
+
+       git init "su:b" &&
+       test_when_finished "rm -rf su:b" &&
+       echo "foobar" >"su:b/fi:le" &&
+       git -C "su:b" add "fi:le" &&
+       git -C "su:b" commit -m "add fi:le" &&
+
+       git -C parent submodule add "../su:b" "su:b" &&
+       git -C parent commit -m "add submodule" &&
+
+       cat >expect <<-\EOF &&
+       fi:le:foobar
+       su:b/fi:le:foobar
+       EOF
+       git -C parent grep -e "foobar" --recurse-submodules >actual &&
+       test_cmp expect actual &&
+
+       cat >expect <<-\EOF &&
+       HEAD:fi:le:foobar
+       HEAD:su:b/fi:le:foobar
+       EOF
+       git -C parent grep -e "foobar" --recurse-submodules HEAD >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep history with moved submoules' '
        git init parent &&
+       test_when_finished "rm -rf parent" &&
        echo "foobar" >parent/file &&
        git -C parent add file &&
        git -C parent commit -m "add file" &&
 
        git init sub &&
+       test_when_finished "rm -rf sub" &&
        echo "foobar" >sub/file &&
        git -C sub add file &&
        git -C sub commit -m "add file" &&
 
-       git -C parent submodule add ../sub &&
+       git -C parent submodule add ../sub dir/sub &&
        git -C parent commit -m "add submodule" &&
 
        cat >expect <<-\EOF &&
+       dir/sub/file:foobar
        file:foobar
-       sub/file:foobar
        EOF
-       git -C parent grep -e "foobar" --recurse-submodules > actual &&
+       git -C parent grep -e "foobar" --recurse-submodules >actual &&
        test_cmp expect actual &&
 
-       git -C parent mv sub sub-moved &&
+       git -C parent mv dir/sub sub-moved &&
        git -C parent commit -m "moved submodule" &&
 
        cat >expect <<-\EOF &&
        file:foobar
        sub-moved/file:foobar
        EOF
-       git -C parent grep -e "foobar" --recurse-submodules > actual &&
+       git -C parent grep -e "foobar" --recurse-submodules >actual &&
        test_cmp expect actual &&
 
        cat >expect <<-\EOF &&
+       HEAD^:dir/sub/file:foobar
        HEAD^:file:foobar
-       HEAD^:sub/file:foobar
        EOF
-       git -C parent grep -e "foobar" --recurse-submodules HEAD^ > actual &&
-       test_cmp expect actual &&
-
-       rm -rf parent sub
+       git -C parent grep -e "foobar" --recurse-submodules HEAD^ >actual &&
+       test_cmp expect actual
 '
 
 test_incompatible_with_recurse_submodules ()

-- 
2.8.0.rc3.226.g39d4020

Reply via email to