grep: recurse in-process using 'struct repository'
Convert grep to use 'struct repository' which enables recursing into submodules to be handled in-process. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
2184d4ba0c
commit
f9ee2fcdfa
@ -95,13 +95,6 @@ OPTIONS
|
|||||||
<tree> option the prefix of all submodule output will be the name of
|
<tree> option the prefix of all submodule output will be the name of
|
||||||
the parent project's <tree> object.
|
the parent project's <tree> object.
|
||||||
|
|
||||||
--parent-basename <basename>::
|
|
||||||
For internal use only. In order to produce uniform output with the
|
|
||||||
--recurse-submodules option, this option can be used to provide the
|
|
||||||
basename of a parent's <tree> object to a submodule so the submodule
|
|
||||||
can prefix its output with the parent's name rather than the SHA1 of
|
|
||||||
the submodule.
|
|
||||||
|
|
||||||
-a::
|
-a::
|
||||||
--text::
|
--text::
|
||||||
Process binary files as if they were text.
|
Process binary files as if they were text.
|
||||||
|
416
builtin/grep.c
416
builtin/grep.c
@ -28,13 +28,7 @@ static char const * const grep_usage[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *super_prefix;
|
|
||||||
static int recurse_submodules;
|
static int recurse_submodules;
|
||||||
static struct argv_array submodule_options = ARGV_ARRAY_INIT;
|
|
||||||
static const char *parent_basename;
|
|
||||||
|
|
||||||
static int grep_submodule_launch(struct grep_opt *opt,
|
|
||||||
const struct grep_source *gs);
|
|
||||||
|
|
||||||
#define GREP_NUM_THREADS_DEFAULT 8
|
#define GREP_NUM_THREADS_DEFAULT 8
|
||||||
static int num_threads;
|
static int num_threads;
|
||||||
@ -186,10 +180,7 @@ static void *run(void *arg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
opt->output_priv = w;
|
opt->output_priv = w;
|
||||||
if (w->source.type == GREP_SOURCE_SUBMODULE)
|
hit |= grep_source(opt, &w->source);
|
||||||
hit |= grep_submodule_launch(opt, &w->source);
|
|
||||||
else
|
|
||||||
hit |= grep_source(opt, &w->source);
|
|
||||||
grep_source_clear_data(&w->source);
|
grep_source_clear_data(&w->source);
|
||||||
work_done(w);
|
work_done(w);
|
||||||
}
|
}
|
||||||
@ -327,21 +318,13 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
|
|||||||
{
|
{
|
||||||
struct strbuf pathbuf = STRBUF_INIT;
|
struct strbuf pathbuf = STRBUF_INIT;
|
||||||
|
|
||||||
if (super_prefix) {
|
if (opt->relative && opt->prefix_length) {
|
||||||
strbuf_add(&pathbuf, filename, tree_name_len);
|
quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf);
|
||||||
strbuf_addstr(&pathbuf, super_prefix);
|
strbuf_insert(&pathbuf, 0, filename, tree_name_len);
|
||||||
strbuf_addstr(&pathbuf, filename + tree_name_len);
|
|
||||||
} else {
|
} else {
|
||||||
strbuf_addstr(&pathbuf, filename);
|
strbuf_addstr(&pathbuf, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt->relative && opt->prefix_length) {
|
|
||||||
char *name = strbuf_detach(&pathbuf, NULL);
|
|
||||||
quote_path_relative(name + tree_name_len, opt->prefix, &pathbuf);
|
|
||||||
strbuf_insert(&pathbuf, 0, name, tree_name_len);
|
|
||||||
free(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NO_PTHREADS
|
#ifndef NO_PTHREADS
|
||||||
if (num_threads) {
|
if (num_threads) {
|
||||||
add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid);
|
add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid);
|
||||||
@ -366,15 +349,10 @@ static int grep_file(struct grep_opt *opt, const char *filename)
|
|||||||
{
|
{
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
if (super_prefix)
|
if (opt->relative && opt->prefix_length)
|
||||||
strbuf_addstr(&buf, super_prefix);
|
quote_path_relative(filename, opt->prefix, &buf);
|
||||||
strbuf_addstr(&buf, filename);
|
else
|
||||||
|
strbuf_addstr(&buf, filename);
|
||||||
if (opt->relative && opt->prefix_length) {
|
|
||||||
char *name = strbuf_detach(&buf, NULL);
|
|
||||||
quote_path_relative(name, opt->prefix, &buf);
|
|
||||||
free(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NO_PTHREADS
|
#ifndef NO_PTHREADS
|
||||||
if (num_threads) {
|
if (num_threads) {
|
||||||
@ -421,284 +399,89 @@ static void run_pager(struct grep_opt *opt, const char *prefix)
|
|||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void compile_submodule_options(const struct grep_opt *opt,
|
static int grep_cache(struct grep_opt *opt, struct repository *repo,
|
||||||
const char **argv,
|
const struct pathspec *pathspec, int cached);
|
||||||
int cached, int untracked,
|
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||||
int opt_exclude, int use_index,
|
struct tree_desc *tree, struct strbuf *base, int tn_len,
|
||||||
int pattern_type_arg)
|
int check_attr, struct repository *repo);
|
||||||
{
|
|
||||||
struct grep_pat *pattern;
|
|
||||||
|
|
||||||
if (recurse_submodules)
|
static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
|
||||||
argv_array_push(&submodule_options, "--recurse-submodules");
|
const struct pathspec *pathspec,
|
||||||
|
const struct object_id *oid,
|
||||||
if (cached)
|
|
||||||
argv_array_push(&submodule_options, "--cached");
|
|
||||||
if (!use_index)
|
|
||||||
argv_array_push(&submodule_options, "--no-index");
|
|
||||||
if (untracked)
|
|
||||||
argv_array_push(&submodule_options, "--untracked");
|
|
||||||
if (opt_exclude > 0)
|
|
||||||
argv_array_push(&submodule_options, "--exclude-standard");
|
|
||||||
|
|
||||||
if (opt->invert)
|
|
||||||
argv_array_push(&submodule_options, "-v");
|
|
||||||
if (opt->ignore_case)
|
|
||||||
argv_array_push(&submodule_options, "-i");
|
|
||||||
if (opt->word_regexp)
|
|
||||||
argv_array_push(&submodule_options, "-w");
|
|
||||||
switch (opt->binary) {
|
|
||||||
case GREP_BINARY_NOMATCH:
|
|
||||||
argv_array_push(&submodule_options, "-I");
|
|
||||||
break;
|
|
||||||
case GREP_BINARY_TEXT:
|
|
||||||
argv_array_push(&submodule_options, "-a");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (opt->allow_textconv)
|
|
||||||
argv_array_push(&submodule_options, "--textconv");
|
|
||||||
if (opt->max_depth != -1)
|
|
||||||
argv_array_pushf(&submodule_options, "--max-depth=%d",
|
|
||||||
opt->max_depth);
|
|
||||||
if (opt->linenum)
|
|
||||||
argv_array_push(&submodule_options, "-n");
|
|
||||||
if (!opt->pathname)
|
|
||||||
argv_array_push(&submodule_options, "-h");
|
|
||||||
if (!opt->relative)
|
|
||||||
argv_array_push(&submodule_options, "--full-name");
|
|
||||||
if (opt->name_only)
|
|
||||||
argv_array_push(&submodule_options, "-l");
|
|
||||||
if (opt->unmatch_name_only)
|
|
||||||
argv_array_push(&submodule_options, "-L");
|
|
||||||
if (opt->null_following_name)
|
|
||||||
argv_array_push(&submodule_options, "-z");
|
|
||||||
if (opt->count)
|
|
||||||
argv_array_push(&submodule_options, "-c");
|
|
||||||
if (opt->file_break)
|
|
||||||
argv_array_push(&submodule_options, "--break");
|
|
||||||
if (opt->heading)
|
|
||||||
argv_array_push(&submodule_options, "--heading");
|
|
||||||
if (opt->pre_context)
|
|
||||||
argv_array_pushf(&submodule_options, "--before-context=%d",
|
|
||||||
opt->pre_context);
|
|
||||||
if (opt->post_context)
|
|
||||||
argv_array_pushf(&submodule_options, "--after-context=%d",
|
|
||||||
opt->post_context);
|
|
||||||
if (opt->funcname)
|
|
||||||
argv_array_push(&submodule_options, "-p");
|
|
||||||
if (opt->funcbody)
|
|
||||||
argv_array_push(&submodule_options, "-W");
|
|
||||||
if (opt->all_match)
|
|
||||||
argv_array_push(&submodule_options, "--all-match");
|
|
||||||
if (opt->debug)
|
|
||||||
argv_array_push(&submodule_options, "--debug");
|
|
||||||
if (opt->status_only)
|
|
||||||
argv_array_push(&submodule_options, "-q");
|
|
||||||
|
|
||||||
switch (pattern_type_arg) {
|
|
||||||
case GREP_PATTERN_TYPE_BRE:
|
|
||||||
argv_array_push(&submodule_options, "-G");
|
|
||||||
break;
|
|
||||||
case GREP_PATTERN_TYPE_ERE:
|
|
||||||
argv_array_push(&submodule_options, "-E");
|
|
||||||
break;
|
|
||||||
case GREP_PATTERN_TYPE_FIXED:
|
|
||||||
argv_array_push(&submodule_options, "-F");
|
|
||||||
break;
|
|
||||||
case GREP_PATTERN_TYPE_PCRE:
|
|
||||||
argv_array_push(&submodule_options, "-P");
|
|
||||||
break;
|
|
||||||
case GREP_PATTERN_TYPE_UNSPECIFIED:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
die("BUG: Added a new grep pattern type without updating switch statement");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (pattern = opt->pattern_list; pattern != NULL;
|
|
||||||
pattern = pattern->next) {
|
|
||||||
switch (pattern->token) {
|
|
||||||
case GREP_PATTERN:
|
|
||||||
argv_array_pushf(&submodule_options, "-e%s",
|
|
||||||
pattern->pattern);
|
|
||||||
break;
|
|
||||||
case GREP_AND:
|
|
||||||
case GREP_OPEN_PAREN:
|
|
||||||
case GREP_CLOSE_PAREN:
|
|
||||||
case GREP_NOT:
|
|
||||||
case GREP_OR:
|
|
||||||
argv_array_push(&submodule_options, pattern->pattern);
|
|
||||||
break;
|
|
||||||
/* BODY and HEAD are not used by git-grep */
|
|
||||||
case GREP_PATTERN_BODY:
|
|
||||||
case GREP_PATTERN_HEAD:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Limit number of threads for child process to use.
|
|
||||||
* This is to prevent potential fork-bomb behavior of git-grep as each
|
|
||||||
* submodule process has its own thread pool.
|
|
||||||
*/
|
|
||||||
argv_array_pushf(&submodule_options, "--threads=%d",
|
|
||||||
DIV_ROUND_UP(num_threads, 2));
|
|
||||||
|
|
||||||
/* Add Pathspecs */
|
|
||||||
argv_array_push(&submodule_options, "--");
|
|
||||||
for (; *argv; argv++)
|
|
||||||
argv_array_push(&submodule_options, *argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Launch child process to grep contents of a submodule
|
|
||||||
*/
|
|
||||||
static int grep_submodule_launch(struct grep_opt *opt,
|
|
||||||
const struct grep_source *gs)
|
|
||||||
{
|
|
||||||
struct child_process cp = CHILD_PROCESS_INIT;
|
|
||||||
int status, i;
|
|
||||||
const char *end_of_base;
|
|
||||||
const char *name;
|
|
||||||
struct strbuf child_output = STRBUF_INIT;
|
|
||||||
|
|
||||||
end_of_base = strchr(gs->name, ':');
|
|
||||||
if (gs->identifier && end_of_base)
|
|
||||||
name = end_of_base + 1;
|
|
||||||
else
|
|
||||||
name = gs->name;
|
|
||||||
|
|
||||||
prepare_submodule_repo_env(&cp.env_array);
|
|
||||||
argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT);
|
|
||||||
|
|
||||||
if (opt->relative && opt->prefix_length)
|
|
||||||
argv_array_pushf(&cp.env_array, "%s=%s",
|
|
||||||
GIT_TOPLEVEL_PREFIX_ENVIRONMENT,
|
|
||||||
opt->prefix);
|
|
||||||
|
|
||||||
/* Add super prefix */
|
|
||||||
argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
|
|
||||||
super_prefix ? super_prefix : "",
|
|
||||||
name);
|
|
||||||
argv_array_push(&cp.args, "grep");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
* 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 OID.
|
|
||||||
*/
|
|
||||||
if (gs->identifier && end_of_base)
|
|
||||||
argv_array_pushf(&cp.args, "--parent-basename=%.*s",
|
|
||||||
(int) (end_of_base - gs->name),
|
|
||||||
gs->name);
|
|
||||||
|
|
||||||
/* Add options */
|
|
||||||
for (i = 0; i < submodule_options.argc; i++) {
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
* oid before pushing the '--' onto the child process argv
|
|
||||||
* array.
|
|
||||||
*/
|
|
||||||
if (gs->identifier &&
|
|
||||||
!strcmp("--", submodule_options.argv[i])) {
|
|
||||||
argv_array_push(&cp.args, oid_to_hex(gs->identifier));
|
|
||||||
}
|
|
||||||
|
|
||||||
argv_array_push(&cp.args, submodule_options.argv[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
cp.git_cmd = 1;
|
|
||||||
cp.dir = gs->path;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Capture output to output buffer and check the return code from the
|
|
||||||
* child process. A '0' indicates a hit, a '1' indicates no hit and
|
|
||||||
* anything else is an error.
|
|
||||||
*/
|
|
||||||
status = capture_command(&cp, &child_output, 0);
|
|
||||||
if (status && (status != 1)) {
|
|
||||||
/* flush the buffer */
|
|
||||||
write_or_die(1, child_output.buf, child_output.len);
|
|
||||||
die("process for submodule '%s' failed with exit code: %d",
|
|
||||||
gs->name, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
opt->output(opt, child_output.buf, child_output.len);
|
|
||||||
strbuf_release(&child_output);
|
|
||||||
/* invert the return code to make a hit equal to 1 */
|
|
||||||
return !status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Prep grep structures for a submodule grep
|
|
||||||
* oid: the oid of the submodule or NULL if using the working tree
|
|
||||||
* filename: name of the submodule including tree name of parent
|
|
||||||
* path: location of the submodule
|
|
||||||
*/
|
|
||||||
static int grep_submodule(struct grep_opt *opt, const struct object_id *oid,
|
|
||||||
const char *filename, const char *path)
|
const char *filename, const char *path)
|
||||||
{
|
{
|
||||||
if (!is_submodule_active(the_repository, path))
|
struct repository submodule;
|
||||||
return 0;
|
int hit;
|
||||||
if (!is_submodule_populated_gently(path, NULL)) {
|
|
||||||
/*
|
|
||||||
* If searching history, check for the presence of the
|
|
||||||
* submodule's gitdir before skipping the submodule.
|
|
||||||
*/
|
|
||||||
if (oid) {
|
|
||||||
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_submodule_active(superproject, path))
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
return 0;
|
if (repo_submodule_init(&submodule, superproject, path))
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
|
repo_read_gitmodules(&submodule);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NEEDSWORK: This adds the submodule's object directory to the list of
|
||||||
|
* alternates for the single in-memory object store. This has some bad
|
||||||
|
* consequences for memory (processed objects will never be freed) and
|
||||||
|
* performance (this increases the number of pack files git has to pay
|
||||||
|
* attention to, to the sum of the number of pack files in all the
|
||||||
|
* repositories processed so far). This can be removed once the object
|
||||||
|
* store is no longer global and instead is a member of the repository
|
||||||
|
* object.
|
||||||
|
*/
|
||||||
|
add_to_alternates_memory(submodule.objectdir);
|
||||||
|
|
||||||
|
if (oid) {
|
||||||
|
struct object *object;
|
||||||
|
struct tree_desc tree;
|
||||||
|
void *data;
|
||||||
|
unsigned long size;
|
||||||
|
struct strbuf base = STRBUF_INIT;
|
||||||
|
|
||||||
|
object = parse_object_or_die(oid, oid_to_hex(oid));
|
||||||
|
|
||||||
|
grep_read_lock();
|
||||||
|
data = read_object_with_reference(object->oid.hash, tree_type,
|
||||||
|
&size, NULL);
|
||||||
|
grep_read_unlock();
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
die(_("unable to read tree (%s)"), oid_to_hex(&object->oid));
|
||||||
|
|
||||||
|
strbuf_addstr(&base, filename);
|
||||||
|
strbuf_addch(&base, '/');
|
||||||
|
|
||||||
|
init_tree_desc(&tree, data, size);
|
||||||
|
hit = grep_tree(opt, pathspec, &tree, &base, base.len,
|
||||||
|
object->type == OBJ_COMMIT, &submodule);
|
||||||
|
strbuf_release(&base);
|
||||||
|
free(data);
|
||||||
|
} else {
|
||||||
|
hit = grep_cache(opt, &submodule, pathspec, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_PTHREADS
|
repo_clear(&submodule);
|
||||||
if (num_threads) {
|
return hit;
|
||||||
add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, oid);
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
struct grep_source gs;
|
|
||||||
int hit;
|
|
||||||
|
|
||||||
grep_source_init(&gs, GREP_SOURCE_SUBMODULE,
|
|
||||||
filename, path, oid);
|
|
||||||
hit = grep_submodule_launch(opt, &gs);
|
|
||||||
|
|
||||||
grep_source_clear(&gs);
|
|
||||||
return hit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
|
static int grep_cache(struct grep_opt *opt, struct repository *repo,
|
||||||
int cached)
|
const struct pathspec *pathspec, int cached)
|
||||||
{
|
{
|
||||||
int hit = 0;
|
int hit = 0;
|
||||||
int nr;
|
int nr;
|
||||||
struct strbuf name = STRBUF_INIT;
|
struct strbuf name = STRBUF_INIT;
|
||||||
int name_base_len = 0;
|
int name_base_len = 0;
|
||||||
if (super_prefix) {
|
if (repo->submodule_prefix) {
|
||||||
name_base_len = strlen(super_prefix);
|
name_base_len = strlen(repo->submodule_prefix);
|
||||||
strbuf_addstr(&name, super_prefix);
|
strbuf_addstr(&name, repo->submodule_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
read_cache();
|
repo_read_index(repo);
|
||||||
|
|
||||||
for (nr = 0; nr < active_nr; nr++) {
|
for (nr = 0; nr < repo->index->cache_nr; nr++) {
|
||||||
const struct cache_entry *ce = active_cache[nr];
|
const struct cache_entry *ce = repo->index->cache[nr];
|
||||||
strbuf_setlen(&name, name_base_len);
|
strbuf_setlen(&name, name_base_len);
|
||||||
strbuf_addstr(&name, ce->name);
|
strbuf_addstr(&name, ce->name);
|
||||||
|
|
||||||
@ -715,14 +498,14 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
ce_skip_worktree(ce)) {
|
ce_skip_worktree(ce)) {
|
||||||
if (ce_stage(ce) || ce_intent_to_add(ce))
|
if (ce_stage(ce) || ce_intent_to_add(ce))
|
||||||
continue;
|
continue;
|
||||||
hit |= grep_oid(opt, &ce->oid, ce->name,
|
hit |= grep_oid(opt, &ce->oid, name.buf,
|
||||||
0, ce->name);
|
0, name.buf);
|
||||||
} else {
|
} else {
|
||||||
hit |= grep_file(opt, ce->name);
|
hit |= grep_file(opt, name.buf);
|
||||||
}
|
}
|
||||||
} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
|
} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
|
||||||
submodule_path_match(pathspec, name.buf, NULL)) {
|
submodule_path_match(pathspec, name.buf, NULL)) {
|
||||||
hit |= grep_submodule(opt, NULL, ce->name, ce->name);
|
hit |= grep_submodule(opt, repo, pathspec, NULL, ce->name, ce->name);
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -730,8 +513,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
if (ce_stage(ce)) {
|
if (ce_stage(ce)) {
|
||||||
do {
|
do {
|
||||||
nr++;
|
nr++;
|
||||||
} while (nr < active_nr &&
|
} while (nr < repo->index->cache_nr &&
|
||||||
!strcmp(ce->name, active_cache[nr]->name));
|
!strcmp(ce->name, repo->index->cache[nr]->name));
|
||||||
nr--; /* compensate for loop control */
|
nr--; /* compensate for loop control */
|
||||||
}
|
}
|
||||||
if (hit && opt->status_only)
|
if (hit && opt->status_only)
|
||||||
@ -744,7 +527,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
|
|
||||||
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||||
struct tree_desc *tree, struct strbuf *base, int tn_len,
|
struct tree_desc *tree, struct strbuf *base, int tn_len,
|
||||||
int check_attr)
|
int check_attr, struct repository *repo)
|
||||||
{
|
{
|
||||||
int hit = 0;
|
int hit = 0;
|
||||||
enum interesting match = entry_not_interesting;
|
enum interesting match = entry_not_interesting;
|
||||||
@ -752,8 +535,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
int old_baselen = base->len;
|
int old_baselen = base->len;
|
||||||
struct strbuf name = STRBUF_INIT;
|
struct strbuf name = STRBUF_INIT;
|
||||||
int name_base_len = 0;
|
int name_base_len = 0;
|
||||||
if (super_prefix) {
|
if (repo->submodule_prefix) {
|
||||||
strbuf_addstr(&name, super_prefix);
|
strbuf_addstr(&name, repo->submodule_prefix);
|
||||||
name_base_len = name.len;
|
name_base_len = name.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,11 +574,11 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
strbuf_addch(base, '/');
|
strbuf_addch(base, '/');
|
||||||
init_tree_desc(&sub, data, size);
|
init_tree_desc(&sub, data, size);
|
||||||
hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
|
hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
|
||||||
check_attr);
|
check_attr, repo);
|
||||||
free(data);
|
free(data);
|
||||||
} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
|
} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
|
||||||
hit |= grep_submodule(opt, entry.oid, base->buf,
|
hit |= grep_submodule(opt, repo, pathspec, entry.oid,
|
||||||
base->buf + tn_len);
|
base->buf, base->buf + tn_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_setlen(base, old_baselen);
|
strbuf_setlen(base, old_baselen);
|
||||||
@ -809,7 +592,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
|
static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||||
struct object *obj, const char *name, const char *path)
|
struct object *obj, const char *name, const char *path,
|
||||||
|
struct repository *repo)
|
||||||
{
|
{
|
||||||
if (obj->type == OBJ_BLOB)
|
if (obj->type == OBJ_BLOB)
|
||||||
return grep_oid(opt, &obj->oid, name, 0, path);
|
return grep_oid(opt, &obj->oid, name, 0, path);
|
||||||
@ -828,10 +612,6 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
if (!data)
|
if (!data)
|
||||||
die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid));
|
die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid));
|
||||||
|
|
||||||
/* Use parent's name as base when recursing submodules */
|
|
||||||
if (recurse_submodules && parent_basename)
|
|
||||||
name = parent_basename;
|
|
||||||
|
|
||||||
len = name ? strlen(name) : 0;
|
len = name ? strlen(name) : 0;
|
||||||
strbuf_init(&base, PATH_MAX + len + 1);
|
strbuf_init(&base, PATH_MAX + len + 1);
|
||||||
if (len) {
|
if (len) {
|
||||||
@ -840,7 +620,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
}
|
}
|
||||||
init_tree_desc(&tree, data, size);
|
init_tree_desc(&tree, data, size);
|
||||||
hit = grep_tree(opt, pathspec, &tree, &base, base.len,
|
hit = grep_tree(opt, pathspec, &tree, &base, base.len,
|
||||||
obj->type == OBJ_COMMIT);
|
obj->type == OBJ_COMMIT, repo);
|
||||||
strbuf_release(&base);
|
strbuf_release(&base);
|
||||||
free(data);
|
free(data);
|
||||||
return hit;
|
return hit;
|
||||||
@ -849,6 +629,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
|
static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||||
|
struct repository *repo,
|
||||||
const struct object_array *list)
|
const struct object_array *list)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -864,7 +645,8 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
|
|||||||
submodule_free();
|
submodule_free();
|
||||||
gitmodules_config_sha1(real_obj->oid.hash);
|
gitmodules_config_sha1(real_obj->oid.hash);
|
||||||
}
|
}
|
||||||
if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path)) {
|
if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path,
|
||||||
|
repo)) {
|
||||||
hit = 1;
|
hit = 1;
|
||||||
if (opt->status_only)
|
if (opt->status_only)
|
||||||
break;
|
break;
|
||||||
@ -1005,9 +787,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||||||
N_("ignore files specified via '.gitignore'"), 1),
|
N_("ignore files specified via '.gitignore'"), 1),
|
||||||
OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
|
OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
|
||||||
N_("recursively search in each submodule")),
|
N_("recursively search in each submodule")),
|
||||||
OPT_STRING(0, "parent-basename", &parent_basename,
|
|
||||||
N_("basename"),
|
|
||||||
N_("prepend parent project's basename to output")),
|
|
||||||
OPT_GROUP(""),
|
OPT_GROUP(""),
|
||||||
OPT_BOOL('v', "invert-match", &opt.invert,
|
OPT_BOOL('v', "invert-match", &opt.invert,
|
||||||
N_("show non-matching lines")),
|
N_("show non-matching lines")),
|
||||||
@ -1112,7 +891,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||||||
init_grep_defaults();
|
init_grep_defaults();
|
||||||
git_config(grep_cmd_config, NULL);
|
git_config(grep_cmd_config, NULL);
|
||||||
grep_init(&opt, prefix);
|
grep_init(&opt, prefix);
|
||||||
super_prefix = get_super_prefix();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is no -- then the paths must exist in the working
|
* If there is no -- then the paths must exist in the working
|
||||||
@ -1272,9 +1050,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
if (recurse_submodules) {
|
if (recurse_submodules) {
|
||||||
gitmodules_config();
|
gitmodules_config();
|
||||||
compile_submodule_options(&opt, argv + i, cached, untracked,
|
|
||||||
opt_exclude, use_index,
|
|
||||||
pattern_type_arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_in_pager && (cached || list.nr))
|
if (show_in_pager && (cached || list.nr))
|
||||||
@ -1318,11 +1093,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||||||
if (!cached)
|
if (!cached)
|
||||||
setup_work_tree();
|
setup_work_tree();
|
||||||
|
|
||||||
hit = grep_cache(&opt, &pathspec, cached);
|
hit = grep_cache(&opt, the_repository, &pathspec, cached);
|
||||||
} else {
|
} else {
|
||||||
if (cached)
|
if (cached)
|
||||||
die(_("both --cached and trees are given."));
|
die(_("both --cached and trees are given."));
|
||||||
hit = grep_objects(&opt, &pathspec, &list);
|
|
||||||
|
hit = grep_objects(&opt, &pathspec, the_repository, &list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_threads)
|
if (num_threads)
|
||||||
|
1
cache.h
1
cache.h
@ -417,7 +417,6 @@ static inline enum object_type object_type(unsigned int mode)
|
|||||||
#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
|
#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
|
||||||
#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
|
#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
|
||||||
#define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX"
|
#define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX"
|
||||||
#define GIT_TOPLEVEL_PREFIX_ENVIRONMENT "GIT_INTERNAL_TOPLEVEL_PREFIX"
|
|
||||||
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
|
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
|
||||||
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
|
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
|
||||||
#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
|
#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
|
||||||
|
2
git.c
2
git.c
@ -392,7 +392,7 @@ static struct cmd_struct commands[] = {
|
|||||||
{ "fsck-objects", cmd_fsck, RUN_SETUP },
|
{ "fsck-objects", cmd_fsck, RUN_SETUP },
|
||||||
{ "gc", cmd_gc, RUN_SETUP },
|
{ "gc", cmd_gc, RUN_SETUP },
|
||||||
{ "get-tar-commit-id", cmd_get_tar_commit_id },
|
{ "get-tar-commit-id", cmd_get_tar_commit_id },
|
||||||
{ "grep", cmd_grep, RUN_SETUP_GENTLY | SUPPORT_SUPER_PREFIX },
|
{ "grep", cmd_grep, RUN_SETUP_GENTLY },
|
||||||
{ "hash-object", cmd_hash_object },
|
{ "hash-object", cmd_hash_object },
|
||||||
{ "help", cmd_help },
|
{ "help", cmd_help },
|
||||||
{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
|
{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
|
||||||
|
13
grep.c
13
grep.c
@ -1927,16 +1927,6 @@ void grep_source_init(struct grep_source *gs, enum grep_source_type type,
|
|||||||
case GREP_SOURCE_FILE:
|
case GREP_SOURCE_FILE:
|
||||||
gs->identifier = xstrdup(identifier);
|
gs->identifier = xstrdup(identifier);
|
||||||
break;
|
break;
|
||||||
case GREP_SOURCE_SUBMODULE:
|
|
||||||
if (!identifier) {
|
|
||||||
gs->identifier = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* FALL THROUGH
|
|
||||||
* If the identifier is non-NULL (in the submodule case) it
|
|
||||||
* will be a SHA1 that needs to be copied.
|
|
||||||
*/
|
|
||||||
case GREP_SOURCE_OID:
|
case GREP_SOURCE_OID:
|
||||||
gs->identifier = oiddup(identifier);
|
gs->identifier = oiddup(identifier);
|
||||||
break;
|
break;
|
||||||
@ -1959,7 +1949,6 @@ void grep_source_clear_data(struct grep_source *gs)
|
|||||||
switch (gs->type) {
|
switch (gs->type) {
|
||||||
case GREP_SOURCE_FILE:
|
case GREP_SOURCE_FILE:
|
||||||
case GREP_SOURCE_OID:
|
case GREP_SOURCE_OID:
|
||||||
case GREP_SOURCE_SUBMODULE:
|
|
||||||
FREE_AND_NULL(gs->buf);
|
FREE_AND_NULL(gs->buf);
|
||||||
gs->size = 0;
|
gs->size = 0;
|
||||||
break;
|
break;
|
||||||
@ -2030,8 +2019,6 @@ static int grep_source_load(struct grep_source *gs)
|
|||||||
return grep_source_load_oid(gs);
|
return grep_source_load_oid(gs);
|
||||||
case GREP_SOURCE_BUF:
|
case GREP_SOURCE_BUF:
|
||||||
return gs->buf ? 0 : -1;
|
return gs->buf ? 0 : -1;
|
||||||
case GREP_SOURCE_SUBMODULE:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
die("BUG: invalid grep_source type to load");
|
die("BUG: invalid grep_source type to load");
|
||||||
}
|
}
|
||||||
|
1
grep.h
1
grep.h
@ -193,7 +193,6 @@ struct grep_source {
|
|||||||
GREP_SOURCE_OID,
|
GREP_SOURCE_OID,
|
||||||
GREP_SOURCE_FILE,
|
GREP_SOURCE_FILE,
|
||||||
GREP_SOURCE_BUF,
|
GREP_SOURCE_BUF,
|
||||||
GREP_SOURCE_SUBMODULE,
|
|
||||||
} type;
|
} type;
|
||||||
void *identifier;
|
void *identifier;
|
||||||
|
|
||||||
|
12
setup.c
12
setup.c
@ -1027,7 +1027,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
|||||||
{
|
{
|
||||||
static struct strbuf cwd = STRBUF_INIT;
|
static struct strbuf cwd = STRBUF_INIT;
|
||||||
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
|
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
|
||||||
const char *prefix, *env_prefix;
|
const char *prefix;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We may have read an incomplete configuration before
|
* We may have read an incomplete configuration before
|
||||||
@ -1085,16 +1085,6 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
|||||||
die("BUG: unhandled setup_git_directory_1() result");
|
die("BUG: unhandled setup_git_directory_1() result");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* NEEDSWORK: This was a hack in order to get ls-files and grep to have
|
|
||||||
* properly formated output when recursing submodules. Once ls-files
|
|
||||||
* and grep have been changed to perform this recursing in-process this
|
|
||||||
* needs to be removed.
|
|
||||||
*/
|
|
||||||
env_prefix = getenv(GIT_TOPLEVEL_PREFIX_ENVIRONMENT);
|
|
||||||
if (env_prefix)
|
|
||||||
prefix = env_prefix;
|
|
||||||
|
|
||||||
if (prefix)
|
if (prefix)
|
||||||
setenv(GIT_PREFIX_ENVIRONMENT, prefix, 1);
|
setenv(GIT_PREFIX_ENVIRONMENT, prefix, 1);
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user