From: Chris Packham <judge.packham@gmail.com>
To: git@vger.kernel.org
Cc: Jens.Lehmann@web.de, pclouds@gmail.com, gitster@pobox.com,
Chris Packham <judge.packham@gmail.com>
Subject: [RFC/PATCHv2 5/5] grep: add support for grepping in submodules
Date: Fri, 15 Oct 2010 16:26:44 -0700 [thread overview]
Message-ID: <1287185204-843-6-git-send-email-judge.packham@gmail.com> (raw)
In-Reply-To: <1287185204-843-1-git-send-email-judge.packham@gmail.com>
When the --recurse-submodules option is given git grep will search in
submodules as they are encountered.
Signed-off-by: Chris Packham <judge.packham@gmail.com>
---
The refspec from the super project is passed as an environment variable
along with the GIT_DIR and GIT_WORK_TREE. We re-build a command line for
the sub-process grep which works for the basic cases but I need to add
some more complex tests to ensure everything gets passed through
correctly.
At the moment I don't alter the pathspec or max-depth option but I'll do
so in a future re-roll.
builtin/grep.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
grep.h | 1 +
2 files changed, 102 insertions(+), 2 deletions(-)
diff --git a/builtin/grep.c b/builtin/grep.c
index 251c4e7..7bcdf05 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -587,6 +587,91 @@ static void run_pager(struct grep_opt *opt, const char *prefix)
free(argv);
}
+static int pattern_list_to_argv(struct grep_opt *opt, const char **argv, int len)
+{
+ int i = 0;
+ struct grep_pat *p = opt->pattern_list;
+ while(p) {
+ if (i > len)
+ die("grep: not enough space for subprocess args");
+ if (p->token == GREP_PATTERN)
+ argv[i++] = "-e";
+ argv[i++] = p->pattern;
+ p = p->next;
+ }
+ return i;
+}
+
+static const char **create_sub_grep_argv(struct grep_opt *opt,
+ const char *path, const char *sha1, const char *tree_name)
+{
+ #define NUM_ARGS 10
+ struct strbuf buf = STRBUF_INIT;
+ const char **argv;
+ int i = 0;
+
+ argv = xcalloc(NUM_ARGS, sizeof(const char *));
+ argv[i++] = "grep";
+
+ if (opt->linenum)
+ argv[i++] = "-n";
+ if (opt->invert)
+ argv[i++] = "-v";
+ if (opt->ignore_case)
+ argv[i++] = "-i";
+ if (opt->count)
+ argv[i++] = "-c";
+ if (opt->name_only)
+ argv[i++] = "-l";
+ if (opt->recurse_submodules)
+ argv[i++] = "--recursive";
+
+ i += pattern_list_to_argv(opt, &argv[i], NUM_ARGS-(i+1));
+ if (sha1) {
+ argv[i++] = sha1;
+ }
+ argv[i++] = NULL;
+
+ strbuf_release(&buf);
+ return argv;
+}
+
+static int grep_submodule(struct grep_opt *opt, const char *path,
+ const char *sha1, const char *tree_name)
+{
+ struct strbuf buf = STRBUF_INIT;
+ struct strbuf pre_buf = STRBUF_INIT;
+ struct child_process cp;
+ const char **argv = create_sub_grep_argv(opt, path, sha1, tree_name);
+ const char *git_dir;
+ int hit = 0;
+ memset(&cp, 0, sizeof(cp));
+
+ strbuf_addf(&buf, "%s/.git", path);
+ git_dir = read_gitfile_gently(buf.buf);
+ if (!git_dir)
+ git_dir = buf.buf;
+ if (!is_directory(git_dir))
+ goto out_free;
+
+ setenv("GIT_SUPER_REFNAME", tree_name, 1);
+ setenv(GIT_DIR_ENVIRONMENT, git_dir, 1);
+ setenv(GIT_WORK_TREE_ENVIRONMENT, path, 1);
+ cp.argv = argv;
+ cp.git_cmd = 1;
+ cp.no_stdin = 1;
+ if (run_command(&cp) == 0)
+ hit = 1;
+out_free:
+ unsetenv("GIT_SUPER_REFNAME");
+ unsetenv(GIT_DIR_ENVIRONMENT);
+ unsetenv(GIT_WORK_TREE_ENVIRONMENT);
+ free(argv);
+ strbuf_release(&buf);
+ strbuf_release(&pre_buf);
+ return hit;
+}
+
static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
{
int hit = 0;
@@ -597,6 +682,10 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
struct cache_entry *ce = active_cache[nr];
if (!pathspec_matches(paths, ce->name, opt->max_depth))
continue;
+ if (S_ISGITLINK(ce->ce_mode) && opt->recurse_submodules) {
+ hit |= grep_submodule(opt, ce->name, NULL, NULL);
+ continue;
+ }
if (!S_ISREG(ce->ce_mode))
continue;
/*
@@ -634,11 +723,16 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
char *down;
int tn_len = strlen(tree_name);
struct strbuf pathbuf;
+ const char *refname = getenv("GIT_SUPER_REFNAME");
+ int rn_len = refname ? strlen(refname) : 0;
- strbuf_init(&pathbuf, PATH_MAX + tn_len);
+ strbuf_init(&pathbuf, PATH_MAX + MAX(tn_len, rn_len));
if (tn_len) {
- strbuf_add(&pathbuf, tree_name, tn_len);
+ if (refname)
+ strbuf_add(&pathbuf, refname, rn_len);
+ else
+ strbuf_add(&pathbuf, tree_name, tn_len);
strbuf_addch(&pathbuf, ':');
tn_len = pathbuf.len;
}
@@ -664,6 +758,9 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
;
else if (S_ISREG(entry.mode))
hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
+ else if (S_ISGITLINK(entry.mode) && opt->recurse_submodules)
+ hit |= grep_submodule(opt, entry.path,
+ sha1_to_hex(entry.sha1), tree_name);
else if (S_ISDIR(entry.mode)) {
enum object_type type;
struct tree_desc sub;
@@ -931,6 +1028,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
"allow calling of grep(1) (ignored by this build)"),
{ OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage",
PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
+ OPT_BOOLEAN(0, "recursive", &opt.recurse_submodules,
+ "recurse into submodules"),
OPT_END()
};
diff --git a/grep.h b/grep.h
index 06621fe..d5e2e11 100644
--- a/grep.h
+++ b/grep.h
@@ -101,6 +101,7 @@ struct grep_opt {
unsigned post_context;
unsigned last_shown;
int show_hunk_mark;
+ int recurse_submodules;
void *priv;
void (*output)(struct grep_opt *opt, const void *data, size_t size);
--
1.7.3.1
next prev parent reply other threads:[~2010-10-15 23:27 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-15 23:26 [RGC/PATCHv2] grep: submodule support Chris Packham
2010-10-15 23:26 ` [RFC/PATCHv2 1/5] worktree: provide better prefix to go back to original cwd Chris Packham
2010-10-16 18:42 ` Jonathan Nieder
2010-10-17 2:48 ` Chris Packham
2010-10-17 10:01 ` Nguyen Thai Ngoc Duy
2010-10-18 2:05 ` Chris Packham
2010-10-15 23:26 ` [RFC/PATCHv2 2/5] grep: output the path from cwd to worktree Chris Packham
2010-10-15 23:26 ` [RFC/PATCHv2 3/5] grep_cache: check pathspec first Chris Packham
2010-10-15 23:26 ` [RFC/PATCHv2 4/5] add test for git grep --recursive Chris Packham
2010-10-15 23:26 ` Chris Packham [this message]
2010-10-17 10:28 ` [RFC/PATCHv2 5/5] grep: add support for grepping in submodules Nguyen Thai Ngoc Duy
2010-10-18 2:01 ` Chris Packham
2010-10-18 3:37 ` Nguyen Thai Ngoc Duy
2010-10-16 15:54 ` [RGC/PATCHv2] grep: submodule support Jens Lehmann
2010-10-17 2:13 ` Chris Packham
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1287185204-843-6-git-send-email-judge.packham@gmail.com \
--to=judge.packham@gmail.com \
--cc=Jens.Lehmann@web.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=pclouds@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).