From: Chris Packham <judge.packham@gmail.com>
To: Jens Lehmann <Jens.Lehmann@web.de>
Cc: git@vger.kernel.org
Subject: Re: [RFC PATCH 3/3] grep: add support for grepping in submodules
Date: Wed, 29 Sep 2010 16:02:01 -0700 [thread overview]
Message-ID: <4CA3C569.4020309@gmail.com> (raw)
In-Reply-To: <4CA3BBD7.3090006@web.de>
On 29/09/10 15:21, Jens Lehmann wrote:
> Nice start!
>
>
> Am 29.09.2010 22:28, schrieb Chris Packham:
>> When the --recurse-submodules option is given git grep will search in
>> submodules as they are encountered.
>
> As "git clone" already introduced a "--recursive" option for
> submodule recursion IMO "--recursive" should be used here too for
> consistency. (Maybe you took the idea to use "--recurse-submodules"
> from my "git-checkout-recurse-submodules" branch on github? But that
> is only used there because I didn't get around to change it yet like
> I did in the "fetch-submodules-too" branch).
I actually started with --recursive and switched to
--recurse-submodules. One thing with this is the standard grep
--recursive option which may cause some confusion if people expect git
grep to behave like normal grep. I'll switch to using --recursive for
now until someone objects to the potential confusion.
One more thought on this that has been hanging around in my mind. I
sometimes want to do something on all but one submodule, in this case
with grep I'm fairly likely to want to skip a linux repository because I
already know the thing I'm looking for is in userland. Maybe in the
future we can make --recursive take an argument that allows us to
specify/restrict which submodules get included in the command invocation.
>
>> Signed-off-by: Chris Packham <judge.packham@gmail.com>
>> ---
>> builtin/grep.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> grep.h | 1 +
>> 2 files changed, 73 insertions(+), 0 deletions(-)
>>
>> diff --git a/builtin/grep.c b/builtin/grep.c
>> index 8315ff0..c9befdc 100644
>> --- a/builtin/grep.c
>> +++ b/builtin/grep.c
>> @@ -30,6 +30,9 @@ static char const * const grep_usage[] = {
>>
>> static int use_threads = 1;
>>
>> +static int saved_argc;
>> +static const char **saved_argv;
>> +
>> #ifndef NO_PTHREADS
>> #define THREADS 8
>> static pthread_t threads[THREADS];
>> @@ -585,6 +588,67 @@ static void run_pager(struct grep_opt *opt, const char *prefix)
>> free(argv);
>> }
>>
>> +static const char **create_sub_grep_argv(struct grep_opt *opt, const char *path)
>> +{
>> + #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";
>> + strbuf_addf(&buf, "--submodule-prefix=\\\"%s\\\"", path);
>> + //argv[i++] = buf.buf;
>
> As C++ comments are not portable they have to be avoided, but I
> assume this one here (and the unused "saved_argc" variable too) is
> a hint that this code is not working as intended yet? ;-)
Yeah this is due to my test problem I mentioned in the cover email. When
run_command gets called it ends up invoking the installed git executable
which doesn't understand my new option.
> It seems you want to use strbuf_detach() here so that this argv[]
> stays valid after the strbuf_release() at the end of this function.
> And if I'm not missing something this would not work correctly in
> the second recursion depth, as the new submodule prefix should
> be the one given to this grep command concatenated with the current
> submodule path.
I'll look into strbuf_detatch. The tricky thing will be keeping track of
what to free at the end of grep_submodule. I guess I can assume that it
will argv[1] is always going to be the dynamically allocated string.
>
>> + 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";
>> +
>> + argv[i++] = saved_argv[0];
>> + argv[i++] = NULL;
>
> Hm, at a quick glance it might be much easier to copy argc & argv
> in cmd_grep() before parse_options() starts manipulating it. Then
> you would only have to change/add the "--submodule-prefix" option
> as needed and would not have to deal with all possible grep option
> combinations (and for example you don't pass the recurse option
> yet, which would stop the recursion pretty soon).
Yeah this is the part I was struggling with a little. It would be easy
to save argv before any option processing but I wondered if that would
be frowned upon as an overhead for non-submodule usages.
I was thinking about doing something tricky with max-depth and
recursion. But maybe its better to keep it simple.
>> +
>> + strbuf_release(&buf);
>> + return argv;
>> +}
>> +
>> +static int grep_submodule(struct grep_opt *opt, const char *path)
>> +{
>> + struct strbuf buf = STRBUF_INIT;
>> + struct child_process cp;
>> + const char **argv = create_sub_grep_argv(opt, path);
>> + const char *git_dir;
>> + int hit = 0;
>> +
>> + 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)) {
>> + warning("submodule %s has not been initialized\n", path);
>
> Having a submodule which is not checked out is perfectly fine, so
> I don't think we want to issue a warning here.
>
OK I'll remove it.
>> + goto out_free;
>> + }
>> +
>> + memset(&cp, 0, sizeof(cp));
>> + cp.argv = argv;
>> + cp.env = local_repo_env;
>> + cp.git_cmd = 1;
>> + cp.no_stdin = 1;
>> + cp.dir = path;
>> + if (run_command(&cp) == 0)
>> + hit = 1;
>> +out_free:
>> + free(argv);
>> + strbuf_release(&buf);
>> + return hit;
>> +}
>> +
>> static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
>> {
>> int hit = 0;
>> @@ -593,6 +657,10 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
>>
>> for (nr = 0; nr < active_nr; nr++) {
>> struct cache_entry *ce = active_cache[nr];
>> + if (S_ISGITLINK(ce->ce_mode) && opt->recurse_submodules) {
>> + hit |= grep_submodule(opt, ce->name);
>> + continue;
>> + }
>> if (!S_ISREG(ce->ce_mode))
>> continue;
>> if (!pathspec_matches(paths, ce->name, opt->max_depth))
>> @@ -929,9 +997,13 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
>> PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
>> OPT_STRING(0, "submodule-prefix", &opt.submodule_prefix, "DIR",
>> "prepend this to submodule path output"),
>> + OPT_BOOLEAN(0, "recurse-submodules", &opt.recurse_submodules,
>> + "recurse into submodules"),
>> OPT_END()
>> };
>>
>> + saved_argc = argc;
>> + saved_argv = argv;
>> /*
>> * 'git grep -h', unlike 'git grep -h <pattern>', is a request
>> * to show usage information and exit.
>> diff --git a/grep.h b/grep.h
>> index d918da4..e3199c9 100644
>> --- a/grep.h
>> +++ b/grep.h
>> @@ -102,6 +102,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);
>
next prev parent reply other threads:[~2010-09-29 23:01 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-09-29 20:28 [RFC PATCH 0/3] grep: submodule support Chris Packham
2010-09-29 20:28 ` [RFC PATCH 1/3] add test for git grep --recursive Chris Packham
2010-09-29 20:35 ` Ævar Arnfjörð Bjarmason
2010-09-29 20:48 ` Chris Packham
2010-09-29 21:34 ` Kevin Ballard
2010-09-29 20:28 ` [RFC PATCH 2/3] grep: prepare grep for submodules Chris Packham
2010-09-30 1:10 ` Nguyen Thai Ngoc Duy
2010-09-30 18:34 ` Chris Packham
2010-10-01 14:37 ` Nguyen Thai Ngoc Duy
2010-10-01 16:26 ` Chris Packham
2010-09-29 20:28 ` [RFC PATCH 3/3] grep: add support for grepping in submodules Chris Packham
2010-09-29 22:21 ` Jens Lehmann
2010-09-29 22:59 ` Junio C Hamano
2010-09-29 23:47 ` Chris Packham
2010-09-30 11:09 ` Jens Lehmann
2010-09-30 11:28 ` Johannes Sixt
2010-09-30 15:07 ` Jens Lehmann
2010-09-29 23:02 ` Chris Packham [this message]
2010-09-30 11:24 ` Jens Lehmann
2010-09-30 16:48 ` Chris Packham
2010-09-30 18:59 ` Heiko Voigt
2010-09-30 19:48 ` Jens Lehmann
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=4CA3C569.4020309@gmail.com \
--to=judge.packham@gmail.com \
--cc=Jens.Lehmann@web.de \
--cc=git@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.