Merge branch 'bw/grep-recurse-submodules'
"git grep --recurse-submodules" has been reworked to give a more consistent output across submodule boundary (and do its thing without having to fork a separate process). * bw/grep-recurse-submodules: grep: recurse in-process using 'struct repository' submodule: merge repo_read_gitmodules and gitmodules_config submodule: check for unmerged .gitmodules outside of config parsing submodule: check for unstaged .gitmodules outside of config parsing submodule: remove fetch.recursesubmodules from submodule-config parsing submodule: remove submodule.fetchjobs from submodule-config parsing config: add config_from_gitmodules cache.h: add GITMODULES_FILE macro repository: have the_repository use the_index repo_read_index: don't discard the index
This commit is contained in:
commit
5aa0b6c506
@ -95,13 +95,6 @@ OPTIONS
|
||||
<tree> option the prefix of all submodule output will be the name of
|
||||
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::
|
||||
--text::
|
||||
Process binary files as if they were text.
|
||||
|
@ -39,7 +39,7 @@ static int prune = -1; /* unspecified */
|
||||
static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative;
|
||||
static int progress = -1;
|
||||
static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
|
||||
static int max_children = -1;
|
||||
static int max_children = 1;
|
||||
static enum transport_family family;
|
||||
static const char *depth;
|
||||
static const char *deepen_since;
|
||||
@ -68,9 +68,30 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
|
||||
recurse_submodules = r;
|
||||
}
|
||||
|
||||
if (!strcmp(k, "submodule.fetchjobs")) {
|
||||
max_children = parse_submodule_fetchjobs(k, v);
|
||||
return 0;
|
||||
} else if (!strcmp(k, "fetch.recursesubmodules")) {
|
||||
recurse_submodules = parse_fetch_recurse_submodules_arg(k, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_default_config(k, v, cb);
|
||||
}
|
||||
|
||||
static int gitmodules_fetch_config(const char *var, const char *value, void *cb)
|
||||
{
|
||||
if (!strcmp(var, "submodule.fetchjobs")) {
|
||||
max_children = parse_submodule_fetchjobs(var, value);
|
||||
return 0;
|
||||
} else if (!strcmp(var, "fetch.recursesubmodules")) {
|
||||
recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
ALLOC_GROW(refmap_array, refmap_nr + 1, refmap_alloc);
|
||||
@ -1311,6 +1332,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
|
||||
for (i = 1; i < argc; i++)
|
||||
strbuf_addf(&default_rla, " %s", argv[i]);
|
||||
|
||||
config_from_gitmodules(gitmodules_fetch_config, NULL);
|
||||
git_config(git_fetch_config, NULL);
|
||||
|
||||
argc = parse_options(argc, argv, prefix,
|
||||
@ -1339,7 +1361,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
|
||||
deepen = 1;
|
||||
|
||||
if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
|
||||
set_config_fetch_recurse_submodules(recurse_submodules_default);
|
||||
gitmodules_config();
|
||||
git_config(submodule_config, NULL);
|
||||
}
|
||||
@ -1383,6 +1404,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
|
||||
result = fetch_populated_submodules(&options,
|
||||
submodule_prefix,
|
||||
recurse_submodules,
|
||||
recurse_submodules_default,
|
||||
verbosity < 0,
|
||||
max_children);
|
||||
argv_array_clear(&options);
|
||||
|
410
builtin/grep.c
410
builtin/grep.c
@ -28,13 +28,7 @@ static char const * const grep_usage[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *super_prefix;
|
||||
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
|
||||
static int num_threads;
|
||||
@ -186,9 +180,6 @@ static void *run(void *arg)
|
||||
break;
|
||||
|
||||
opt->output_priv = w;
|
||||
if (w->source.type == GREP_SOURCE_SUBMODULE)
|
||||
hit |= grep_submodule_launch(opt, &w->source);
|
||||
else
|
||||
hit |= grep_source(opt, &w->source);
|
||||
grep_source_clear_data(&w->source);
|
||||
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;
|
||||
|
||||
if (super_prefix) {
|
||||
strbuf_add(&pathbuf, filename, tree_name_len);
|
||||
strbuf_addstr(&pathbuf, super_prefix);
|
||||
strbuf_addstr(&pathbuf, filename + tree_name_len);
|
||||
if (opt->relative && opt->prefix_length) {
|
||||
quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf);
|
||||
strbuf_insert(&pathbuf, 0, filename, tree_name_len);
|
||||
} else {
|
||||
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
|
||||
if (num_threads) {
|
||||
add_work(opt, GREP_SOURCE_OID, pathbuf.buf, path, oid);
|
||||
@ -366,16 +349,11 @@ static int grep_file(struct grep_opt *opt, const char *filename)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (super_prefix)
|
||||
strbuf_addstr(&buf, super_prefix);
|
||||
if (opt->relative && opt->prefix_length)
|
||||
quote_path_relative(filename, opt->prefix, &buf);
|
||||
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
|
||||
if (num_threads) {
|
||||
add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename);
|
||||
@ -421,284 +399,89 @@ static void run_pager(struct grep_opt *opt, const char *prefix)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static void compile_submodule_options(const struct grep_opt *opt,
|
||||
const char **argv,
|
||||
int cached, int untracked,
|
||||
int opt_exclude, int use_index,
|
||||
int pattern_type_arg)
|
||||
{
|
||||
struct grep_pat *pattern;
|
||||
static int grep_cache(struct grep_opt *opt, struct repository *repo,
|
||||
const struct pathspec *pathspec, int cached);
|
||||
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||
struct tree_desc *tree, struct strbuf *base, int tn_len,
|
||||
int check_attr, struct repository *repo);
|
||||
|
||||
if (recurse_submodules)
|
||||
argv_array_push(&submodule_options, "--recurse-submodules");
|
||||
|
||||
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,
|
||||
static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
|
||||
const struct pathspec *pathspec,
|
||||
const struct object_id *oid,
|
||||
const char *filename, const char *path)
|
||||
{
|
||||
if (!is_submodule_active(the_repository, path))
|
||||
return 0;
|
||||
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_oid, path);
|
||||
if (sub)
|
||||
path = git_path("modules/%s", sub->name);
|
||||
|
||||
if (!(is_directory(path) && is_git_directory(path)))
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_PTHREADS
|
||||
if (num_threads) {
|
||||
add_work(opt, GREP_SOURCE_SUBMODULE, filename, path, oid);
|
||||
return 0;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
struct grep_source gs;
|
||||
struct repository submodule;
|
||||
int hit;
|
||||
|
||||
grep_source_init(&gs, GREP_SOURCE_SUBMODULE,
|
||||
filename, path, oid);
|
||||
hit = grep_submodule_launch(opt, &gs);
|
||||
if (!is_submodule_active(superproject, path))
|
||||
return 0;
|
||||
|
||||
grep_source_clear(&gs);
|
||||
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);
|
||||
}
|
||||
|
||||
repo_clear(&submodule);
|
||||
return hit;
|
||||
}
|
||||
}
|
||||
|
||||
static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||
int cached)
|
||||
static int grep_cache(struct grep_opt *opt, struct repository *repo,
|
||||
const struct pathspec *pathspec, int cached)
|
||||
{
|
||||
int hit = 0;
|
||||
int nr;
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
int name_base_len = 0;
|
||||
if (super_prefix) {
|
||||
name_base_len = strlen(super_prefix);
|
||||
strbuf_addstr(&name, super_prefix);
|
||||
if (repo->submodule_prefix) {
|
||||
name_base_len = strlen(repo->submodule_prefix);
|
||||
strbuf_addstr(&name, repo->submodule_prefix);
|
||||
}
|
||||
|
||||
read_cache();
|
||||
repo_read_index(repo);
|
||||
|
||||
for (nr = 0; nr < active_nr; nr++) {
|
||||
const struct cache_entry *ce = active_cache[nr];
|
||||
for (nr = 0; nr < repo->index->cache_nr; nr++) {
|
||||
const struct cache_entry *ce = repo->index->cache[nr];
|
||||
strbuf_setlen(&name, name_base_len);
|
||||
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)) {
|
||||
if (ce_stage(ce) || ce_intent_to_add(ce))
|
||||
continue;
|
||||
hit |= grep_oid(opt, &ce->oid, ce->name,
|
||||
0, ce->name);
|
||||
hit |= grep_oid(opt, &ce->oid, name.buf,
|
||||
0, name.buf);
|
||||
} else {
|
||||
hit |= grep_file(opt, ce->name);
|
||||
hit |= grep_file(opt, name.buf);
|
||||
}
|
||||
} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
|
||||
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 {
|
||||
continue;
|
||||
}
|
||||
@ -730,8 +513,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||
if (ce_stage(ce)) {
|
||||
do {
|
||||
nr++;
|
||||
} while (nr < active_nr &&
|
||||
!strcmp(ce->name, active_cache[nr]->name));
|
||||
} while (nr < repo->index->cache_nr &&
|
||||
!strcmp(ce->name, repo->index->cache[nr]->name));
|
||||
nr--; /* compensate for loop control */
|
||||
}
|
||||
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,
|
||||
struct tree_desc *tree, struct strbuf *base, int tn_len,
|
||||
int check_attr)
|
||||
int check_attr, struct repository *repo)
|
||||
{
|
||||
int hit = 0;
|
||||
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;
|
||||
struct strbuf name = STRBUF_INIT;
|
||||
int name_base_len = 0;
|
||||
if (super_prefix) {
|
||||
strbuf_addstr(&name, super_prefix);
|
||||
if (repo->submodule_prefix) {
|
||||
strbuf_addstr(&name, repo->submodule_prefix);
|
||||
name_base_len = name.len;
|
||||
}
|
||||
|
||||
@ -791,11 +574,11 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||
strbuf_addch(base, '/');
|
||||
init_tree_desc(&sub, data, size);
|
||||
hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
|
||||
check_attr);
|
||||
check_attr, repo);
|
||||
free(data);
|
||||
} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
|
||||
hit |= grep_submodule(opt, entry.oid, base->buf,
|
||||
base->buf + tn_len);
|
||||
hit |= grep_submodule(opt, repo, pathspec, entry.oid,
|
||||
base->buf, base->buf + tn_len);
|
||||
}
|
||||
|
||||
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,
|
||||
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)
|
||||
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)
|
||||
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;
|
||||
strbuf_init(&base, PATH_MAX + len + 1);
|
||||
if (len) {
|
||||
@ -840,7 +620,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||
}
|
||||
init_tree_desc(&tree, data, size);
|
||||
hit = grep_tree(opt, pathspec, &tree, &base, base.len,
|
||||
obj->type == OBJ_COMMIT);
|
||||
obj->type == OBJ_COMMIT, repo);
|
||||
strbuf_release(&base);
|
||||
free(data);
|
||||
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,
|
||||
struct repository *repo,
|
||||
const struct object_array *list)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -864,7 +645,8 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
|
||||
submodule_free();
|
||||
gitmodules_config_oid(&real_obj->oid);
|
||||
}
|
||||
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;
|
||||
if (opt->status_only)
|
||||
break;
|
||||
@ -1005,9 +787,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
N_("ignore files specified via '.gitignore'"), 1),
|
||||
OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
|
||||
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_BOOL('v', "invert-match", &opt.invert,
|
||||
N_("show non-matching lines")),
|
||||
@ -1112,7 +891,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
init_grep_defaults();
|
||||
git_config(grep_cmd_config, NULL);
|
||||
grep_init(&opt, prefix);
|
||||
super_prefix = get_super_prefix();
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
gitmodules_config();
|
||||
compile_submodule_options(&opt, argv + i, cached, untracked,
|
||||
opt_exclude, use_index,
|
||||
pattern_type_arg);
|
||||
}
|
||||
|
||||
if (show_in_pager && (cached || list.nr))
|
||||
@ -1318,11 +1093,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
if (!cached)
|
||||
setup_work_tree();
|
||||
|
||||
hit = grep_cache(&opt, &pathspec, cached);
|
||||
hit = grep_cache(&opt, the_repository, &pathspec, cached);
|
||||
} else {
|
||||
if (cached)
|
||||
die(_("both --cached and trees are given."));
|
||||
hit = grep_objects(&opt, &pathspec, &list);
|
||||
|
||||
hit = grep_objects(&opt, &pathspec, the_repository, &list);
|
||||
}
|
||||
|
||||
if (num_threads)
|
||||
|
@ -81,7 +81,7 @@ static void prepare_move_submodule(const char *src, int first,
|
||||
struct strbuf submodule_dotgit = STRBUF_INIT;
|
||||
if (!S_ISGITLINK(active_cache[first]->ce_mode))
|
||||
die(_("Directory %s is in index and no submodule?"), src);
|
||||
if (!is_staging_gitmodules_ok())
|
||||
if (!is_staging_gitmodules_ok(&the_index))
|
||||
die(_("Please stage your changes to .gitmodules or stash them to proceed"));
|
||||
strbuf_addf(&submodule_dotgit, "%s/.git", src);
|
||||
*submodule_gitfile = read_gitfile(submodule_dotgit.buf);
|
||||
|
@ -286,7 +286,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||
list.entry[list.nr].name = xstrdup(ce->name);
|
||||
list.entry[list.nr].is_submodule = S_ISGITLINK(ce->ce_mode);
|
||||
if (list.entry[list.nr++].is_submodule &&
|
||||
!is_staging_gitmodules_ok())
|
||||
!is_staging_gitmodules_ok(&the_index))
|
||||
die (_("Please stage your changes to .gitmodules or stash them to proceed"));
|
||||
}
|
||||
|
||||
|
@ -960,10 +960,19 @@ static int update_clone_task_finished(int result,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gitmodules_update_clone_config(const char *var, const char *value,
|
||||
void *cb)
|
||||
{
|
||||
int *max_jobs = cb;
|
||||
if (!strcmp(var, "submodule.fetchjobs"))
|
||||
*max_jobs = parse_submodule_fetchjobs(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update_clone(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
const char *update = NULL;
|
||||
int max_jobs = -1;
|
||||
int max_jobs = 1;
|
||||
struct string_list_item *item;
|
||||
struct pathspec pathspec;
|
||||
struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
|
||||
@ -1000,6 +1009,9 @@ static int update_clone(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
suc.prefix = prefix;
|
||||
|
||||
config_from_gitmodules(gitmodules_update_clone_config, &max_jobs);
|
||||
git_config(gitmodules_update_clone_config, &max_jobs);
|
||||
|
||||
argc = parse_options(argc, argv, prefix, module_update_clone_options,
|
||||
git_submodule_helper_usage, 0);
|
||||
|
||||
@ -1017,9 +1029,6 @@ static int update_clone(int argc, const char **argv, const char *prefix)
|
||||
gitmodules_config();
|
||||
git_config(submodule_config, NULL);
|
||||
|
||||
if (max_jobs < 0)
|
||||
max_jobs = parallel_submodules();
|
||||
|
||||
run_processes_parallel(max_jobs,
|
||||
update_clone_get_next_task,
|
||||
update_clone_start_failure,
|
||||
|
2
cache.h
2
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_PREFIX_ENVIRONMENT "GIT_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 DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
|
||||
#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
|
||||
@ -433,6 +432,7 @@ static inline enum object_type object_type(unsigned int mode)
|
||||
#define GITATTRIBUTES_FILE ".gitattributes"
|
||||
#define INFOATTRIBUTES_FILE "info/attributes"
|
||||
#define ATTRIBUTE_MACRO_PREFIX "[attr]"
|
||||
#define GITMODULES_FILE ".gitmodules"
|
||||
#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
|
||||
#define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
|
||||
#define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
|
||||
|
17
config.c
17
config.c
@ -2059,6 +2059,23 @@ int git_config_get_pathname(const char *key, const char **dest)
|
||||
return repo_config_get_pathname(the_repository, key, dest);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: This function exists solely to maintain backward compatibility with
|
||||
* 'fetch' and 'update_clone' storing configuration in '.gitmodules' and should
|
||||
* NOT be used anywhere else.
|
||||
*
|
||||
* Runs the provided config function on the '.gitmodules' file found in the
|
||||
* working directory.
|
||||
*/
|
||||
void config_from_gitmodules(config_fn_t fn, void *data)
|
||||
{
|
||||
if (the_repository->worktree) {
|
||||
char *file = repo_worktree_path(the_repository, GITMODULES_FILE);
|
||||
git_config_from_file(fn, file, data);
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
|
||||
int git_config_get_expiry(const char *key, const char **output)
|
||||
{
|
||||
int ret = git_config_get_string_const(key, output);
|
||||
|
10
config.h
10
config.h
@ -187,6 +187,16 @@ extern int repo_config_get_maybe_bool(struct repository *repo,
|
||||
extern int repo_config_get_pathname(struct repository *repo,
|
||||
const char *key, const char **dest);
|
||||
|
||||
/*
|
||||
* Note: This function exists solely to maintain backward compatibility with
|
||||
* 'fetch' and 'update_clone' storing configuration in '.gitmodules' and should
|
||||
* NOT be used anywhere else.
|
||||
*
|
||||
* Runs the provided config function on the '.gitmodules' file found in the
|
||||
* working directory.
|
||||
*/
|
||||
extern void config_from_gitmodules(config_fn_t fn, void *data);
|
||||
|
||||
extern int git_config_get_value(const char *key, const char **value);
|
||||
extern const struct string_list *git_config_get_value_multi(const char *key);
|
||||
extern void git_config_clear(void);
|
||||
|
2
git.c
2
git.c
@ -404,7 +404,7 @@ static struct cmd_struct commands[] = {
|
||||
{ "fsck-objects", cmd_fsck, RUN_SETUP },
|
||||
{ "gc", cmd_gc, RUN_SETUP },
|
||||
{ "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 },
|
||||
{ "help", cmd_help },
|
||||
{ "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:
|
||||
gs->identifier = xstrdup(identifier);
|
||||
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:
|
||||
gs->identifier = oiddup(identifier);
|
||||
break;
|
||||
@ -1959,7 +1949,6 @@ void grep_source_clear_data(struct grep_source *gs)
|
||||
switch (gs->type) {
|
||||
case GREP_SOURCE_FILE:
|
||||
case GREP_SOURCE_OID:
|
||||
case GREP_SOURCE_SUBMODULE:
|
||||
FREE_AND_NULL(gs->buf);
|
||||
gs->size = 0;
|
||||
break;
|
||||
@ -2030,8 +2019,6 @@ static int grep_source_load(struct grep_source *gs)
|
||||
return grep_source_load_oid(gs);
|
||||
case GREP_SOURCE_BUF:
|
||||
return gs->buf ? 0 : -1;
|
||||
case GREP_SOURCE_SUBMODULE:
|
||||
break;
|
||||
}
|
||||
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_FILE,
|
||||
GREP_SOURCE_BUF,
|
||||
GREP_SOURCE_SUBMODULE,
|
||||
} type;
|
||||
void *identifier;
|
||||
|
||||
|
@ -4,7 +4,9 @@
|
||||
#include "submodule-config.h"
|
||||
|
||||
/* The main repository */
|
||||
static struct repository the_repo;
|
||||
static struct repository the_repo = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, 0, 0
|
||||
};
|
||||
struct repository *the_repository = &the_repo;
|
||||
|
||||
static char *git_path_from_env(const char *envvar, const char *git_dir,
|
||||
@ -235,8 +237,6 @@ int repo_read_index(struct repository *repo)
|
||||
{
|
||||
if (!repo->index)
|
||||
repo->index = xcalloc(1, sizeof(*repo->index));
|
||||
else
|
||||
discard_index(repo->index);
|
||||
|
||||
return read_index_from(repo->index, repo->index_file);
|
||||
}
|
||||
|
@ -92,6 +92,14 @@ extern int repo_submodule_init(struct repository *submodule,
|
||||
const char *path);
|
||||
extern void repo_clear(struct repository *repo);
|
||||
|
||||
/*
|
||||
* Populates the repository's index from its index_file, an index struct will
|
||||
* be allocated if needed.
|
||||
*
|
||||
* Return the number of index entries in the populated index or a value less
|
||||
* than zero if an error occured. If the repository's index has already been
|
||||
* populated then the number of entries will simply be returned.
|
||||
*/
|
||||
extern int repo_read_index(struct repository *repo);
|
||||
|
||||
#endif /* REPOSITORY_H */
|
||||
|
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;
|
||||
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
|
||||
const char *prefix, *env_prefix;
|
||||
const char *prefix;
|
||||
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
setenv(GIT_PREFIX_ENVIRONMENT, prefix, 1);
|
||||
else
|
||||
|
@ -254,6 +254,14 @@ static int parse_fetch_recurse(const char *opt, const char *arg,
|
||||
}
|
||||
}
|
||||
|
||||
int parse_submodule_fetchjobs(const char *var, const char *value)
|
||||
{
|
||||
int fetchjobs = git_config_int(var, value);
|
||||
if (fetchjobs < 0)
|
||||
die(_("negative values not allowed for submodule.fetchjobs"));
|
||||
return fetchjobs;
|
||||
}
|
||||
|
||||
int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg)
|
||||
{
|
||||
return parse_fetch_recurse(opt, arg, 1);
|
||||
|
@ -27,6 +27,7 @@ struct repository;
|
||||
|
||||
extern void submodule_cache_free(struct submodule_cache *cache);
|
||||
|
||||
extern int parse_submodule_fetchjobs(const char *var, const char *value);
|
||||
extern int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg);
|
||||
struct option;
|
||||
extern int option_fetch_parse_recurse_submodules(const struct option *opt,
|
||||
|
157
submodule.c
157
submodule.c
@ -20,37 +20,53 @@
|
||||
#include "worktree.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
|
||||
static int config_update_recurse_submodules = RECURSE_SUBMODULES_OFF;
|
||||
static int parallel_jobs = 1;
|
||||
static struct string_list changed_submodule_paths = STRING_LIST_INIT_DUP;
|
||||
static int initialized_fetch_ref_tips;
|
||||
static struct oid_array ref_tips_before_fetch;
|
||||
static struct oid_array ref_tips_after_fetch;
|
||||
|
||||
/*
|
||||
* The following flag is set if the .gitmodules file is unmerged. We then
|
||||
* disable recursion for all submodules where .git/config doesn't have a
|
||||
* matching config entry because we can't guess what might be configured in
|
||||
* .gitmodules unless the user resolves the conflict. When a command line
|
||||
* option is given (which always overrides configuration) this flag will be
|
||||
* ignored.
|
||||
* Check if the .gitmodules file is unmerged. Parsing of the .gitmodules file
|
||||
* will be disabled because we can't guess what might be configured in
|
||||
* .gitmodules unless the user resolves the conflict.
|
||||
*/
|
||||
static int gitmodules_is_unmerged;
|
||||
int is_gitmodules_unmerged(const struct index_state *istate)
|
||||
{
|
||||
int pos = index_name_pos(istate, GITMODULES_FILE, strlen(GITMODULES_FILE));
|
||||
if (pos < 0) { /* .gitmodules not found or isn't merged */
|
||||
pos = -1 - pos;
|
||||
if (istate->cache_nr > pos) { /* there is a .gitmodules */
|
||||
const struct cache_entry *ce = istate->cache[pos];
|
||||
if (ce_namelen(ce) == strlen(GITMODULES_FILE) &&
|
||||
!strcmp(ce->name, GITMODULES_FILE))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This flag is set if the .gitmodules file had unstaged modifications on
|
||||
* startup. This must be checked before allowing modifications to the
|
||||
* .gitmodules file with the intention to stage them later, because when
|
||||
* continuing we would stage the modifications the user didn't stage herself
|
||||
* too. That might change in a future version when we learn to stage the
|
||||
* changes we do ourselves without staging any previous modifications.
|
||||
* Check if the .gitmodules file has unstaged modifications. This must be
|
||||
* checked before allowing modifications to the .gitmodules file with the
|
||||
* intention to stage them later, because when continuing we would stage the
|
||||
* modifications the user didn't stage herself too. That might change in a
|
||||
* future version when we learn to stage the changes we do ourselves without
|
||||
* staging any previous modifications.
|
||||
*/
|
||||
static int gitmodules_is_modified;
|
||||
|
||||
int is_staging_gitmodules_ok(void)
|
||||
int is_staging_gitmodules_ok(const struct index_state *istate)
|
||||
{
|
||||
return !gitmodules_is_modified;
|
||||
int pos = index_name_pos(istate, GITMODULES_FILE, strlen(GITMODULES_FILE));
|
||||
|
||||
if ((pos >= 0) && (pos < istate->cache_nr)) {
|
||||
struct stat st;
|
||||
if (lstat(GITMODULES_FILE, &st) == 0 &&
|
||||
ce_match_stat(istate->cache[pos], &st, 0) & DATA_CHANGED)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -63,10 +79,10 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
|
||||
struct strbuf entry = STRBUF_INIT;
|
||||
const struct submodule *submodule;
|
||||
|
||||
if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */
|
||||
if (!file_exists(GITMODULES_FILE)) /* Do nothing without .gitmodules */
|
||||
return -1;
|
||||
|
||||
if (gitmodules_is_unmerged)
|
||||
if (is_gitmodules_unmerged(&the_index))
|
||||
die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
|
||||
|
||||
submodule = submodule_from_path(&null_oid, oldpath);
|
||||
@ -77,7 +93,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath)
|
||||
strbuf_addstr(&entry, "submodule.");
|
||||
strbuf_addstr(&entry, submodule->name);
|
||||
strbuf_addstr(&entry, ".path");
|
||||
if (git_config_set_in_file_gently(".gitmodules", entry.buf, newpath) < 0) {
|
||||
if (git_config_set_in_file_gently(GITMODULES_FILE, entry.buf, newpath) < 0) {
|
||||
/* Maybe the user already did that, don't error out here */
|
||||
warning(_("Could not update .gitmodules entry %s"), entry.buf);
|
||||
strbuf_release(&entry);
|
||||
@ -97,10 +113,10 @@ int remove_path_from_gitmodules(const char *path)
|
||||
struct strbuf sect = STRBUF_INIT;
|
||||
const struct submodule *submodule;
|
||||
|
||||
if (!file_exists(".gitmodules")) /* Do nothing without .gitmodules */
|
||||
if (!file_exists(GITMODULES_FILE)) /* Do nothing without .gitmodules */
|
||||
return -1;
|
||||
|
||||
if (gitmodules_is_unmerged)
|
||||
if (is_gitmodules_unmerged(&the_index))
|
||||
die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first"));
|
||||
|
||||
submodule = submodule_from_path(&null_oid, path);
|
||||
@ -110,7 +126,7 @@ int remove_path_from_gitmodules(const char *path)
|
||||
}
|
||||
strbuf_addstr(§, "submodule.");
|
||||
strbuf_addstr(§, submodule->name);
|
||||
if (git_config_rename_section_in_file(".gitmodules", sect.buf, NULL) < 0) {
|
||||
if (git_config_rename_section_in_file(GITMODULES_FILE, sect.buf, NULL) < 0) {
|
||||
/* Maybe the user already did that, don't error out here */
|
||||
warning(_("Could not remove .gitmodules entry for %s"), path);
|
||||
strbuf_release(§);
|
||||
@ -122,7 +138,7 @@ int remove_path_from_gitmodules(const char *path)
|
||||
|
||||
void stage_updated_gitmodules(void)
|
||||
{
|
||||
if (add_file_to_cache(".gitmodules", 0))
|
||||
if (add_file_to_cache(GITMODULES_FILE, 0))
|
||||
die(_("staging updated .gitmodules failed"));
|
||||
}
|
||||
|
||||
@ -151,7 +167,7 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
|
||||
if (submodule) {
|
||||
if (submodule->ignore)
|
||||
handle_ignore_submodules_arg(diffopt, submodule->ignore);
|
||||
else if (gitmodules_is_unmerged)
|
||||
else if (is_gitmodules_unmerged(&the_index))
|
||||
DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
|
||||
}
|
||||
}
|
||||
@ -159,17 +175,8 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
|
||||
/* For loading from the .gitmodules file. */
|
||||
static int git_modules_config(const char *var, const char *value, void *cb)
|
||||
{
|
||||
if (!strcmp(var, "submodule.fetchjobs")) {
|
||||
parallel_jobs = git_config_int(var, value);
|
||||
if (parallel_jobs < 0)
|
||||
die(_("negative values not allowed for submodule.fetchJobs"));
|
||||
return 0;
|
||||
} else if (starts_with(var, "submodule."))
|
||||
if (starts_with(var, "submodule."))
|
||||
return parse_submodule_config_option(var, value);
|
||||
else if (!strcmp(var, "fetch.recursesubmodules")) {
|
||||
config_fetch_recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -223,39 +230,6 @@ void load_submodule_cache(void)
|
||||
git_config(submodule_config, NULL);
|
||||
}
|
||||
|
||||
void gitmodules_config(void)
|
||||
{
|
||||
const char *work_tree = get_git_work_tree();
|
||||
if (work_tree) {
|
||||
struct strbuf gitmodules_path = STRBUF_INIT;
|
||||
int pos;
|
||||
strbuf_addstr(&gitmodules_path, work_tree);
|
||||
strbuf_addstr(&gitmodules_path, "/.gitmodules");
|
||||
if (read_cache() < 0)
|
||||
die("index file corrupt");
|
||||
pos = cache_name_pos(".gitmodules", 11);
|
||||
if (pos < 0) { /* .gitmodules not found or isn't merged */
|
||||
pos = -1 - pos;
|
||||
if (active_nr > pos) { /* there is a .gitmodules */
|
||||
const struct cache_entry *ce = active_cache[pos];
|
||||
if (ce_namelen(ce) == 11 &&
|
||||
!memcmp(ce->name, ".gitmodules", 11))
|
||||
gitmodules_is_unmerged = 1;
|
||||
}
|
||||
} else if (pos < active_nr) {
|
||||
struct stat st;
|
||||
if (lstat(".gitmodules", &st) == 0 &&
|
||||
ce_match_stat(active_cache[pos], &st, 0) & DATA_CHANGED)
|
||||
gitmodules_is_modified = 1;
|
||||
}
|
||||
|
||||
if (!gitmodules_is_unmerged)
|
||||
git_config_from_file(git_modules_config,
|
||||
gitmodules_path.buf, NULL);
|
||||
strbuf_release(&gitmodules_path);
|
||||
}
|
||||
}
|
||||
|
||||
static int gitmodules_cb(const char *var, const char *value, void *data)
|
||||
{
|
||||
struct repository *repo = data;
|
||||
@ -264,10 +238,24 @@ static int gitmodules_cb(const char *var, const char *value, void *data)
|
||||
|
||||
void repo_read_gitmodules(struct repository *repo)
|
||||
{
|
||||
char *gitmodules_path = repo_worktree_path(repo, ".gitmodules");
|
||||
if (repo->worktree) {
|
||||
char *gitmodules;
|
||||
|
||||
git_config_from_file(gitmodules_cb, gitmodules_path, repo);
|
||||
free(gitmodules_path);
|
||||
if (repo_read_index(repo) < 0)
|
||||
return;
|
||||
|
||||
gitmodules = repo_worktree_path(repo, GITMODULES_FILE);
|
||||
|
||||
if (!is_gitmodules_unmerged(repo->index))
|
||||
git_config_from_file(gitmodules_cb, gitmodules, repo);
|
||||
|
||||
free(gitmodules);
|
||||
}
|
||||
}
|
||||
|
||||
void gitmodules_config(void)
|
||||
{
|
||||
repo_read_gitmodules(the_repository);
|
||||
}
|
||||
|
||||
void gitmodules_config_oid(const struct object_id *commit_oid)
|
||||
@ -720,11 +708,6 @@ done:
|
||||
clear_commit_marks(right, ~0);
|
||||
}
|
||||
|
||||
void set_config_fetch_recurse_submodules(int value)
|
||||
{
|
||||
config_fetch_recurse_submodules = value;
|
||||
}
|
||||
|
||||
int should_update_submodules(void)
|
||||
{
|
||||
return config_update_recurse_submodules == RECURSE_SUBMODULES_ON;
|
||||
@ -1182,10 +1165,11 @@ struct submodule_parallel_fetch {
|
||||
const char *work_tree;
|
||||
const char *prefix;
|
||||
int command_line_option;
|
||||
int default_option;
|
||||
int quiet;
|
||||
int result;
|
||||
};
|
||||
#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0}
|
||||
#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0, 0}
|
||||
|
||||
static int get_next_submodule(struct child_process *cp,
|
||||
struct strbuf *err, void *data, void **task_cb)
|
||||
@ -1223,10 +1207,9 @@ static int get_next_submodule(struct child_process *cp,
|
||||
default_argv = "on-demand";
|
||||
}
|
||||
} else {
|
||||
if ((config_fetch_recurse_submodules == RECURSE_SUBMODULES_OFF) ||
|
||||
gitmodules_is_unmerged)
|
||||
if (spf->default_option == RECURSE_SUBMODULES_OFF)
|
||||
continue;
|
||||
if (config_fetch_recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) {
|
||||
if (spf->default_option == RECURSE_SUBMODULES_ON_DEMAND) {
|
||||
if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
|
||||
continue;
|
||||
default_argv = "on-demand";
|
||||
@ -1293,6 +1276,7 @@ static int fetch_finish(int retvalue, struct strbuf *err,
|
||||
|
||||
int fetch_populated_submodules(const struct argv_array *options,
|
||||
const char *prefix, int command_line_option,
|
||||
int default_option,
|
||||
int quiet, int max_parallel_jobs)
|
||||
{
|
||||
int i;
|
||||
@ -1300,6 +1284,7 @@ int fetch_populated_submodules(const struct argv_array *options,
|
||||
|
||||
spf.work_tree = get_git_work_tree();
|
||||
spf.command_line_option = command_line_option;
|
||||
spf.default_option = default_option;
|
||||
spf.quiet = quiet;
|
||||
spf.prefix = prefix;
|
||||
|
||||
@ -1315,9 +1300,6 @@ int fetch_populated_submodules(const struct argv_array *options,
|
||||
argv_array_push(&spf.args, "--recurse-submodules-default");
|
||||
/* default value, "--submodule-prefix" and its value are added later */
|
||||
|
||||
if (max_parallel_jobs < 0)
|
||||
max_parallel_jobs = parallel_jobs;
|
||||
|
||||
calculate_changed_submodule_paths();
|
||||
run_processes_parallel(max_parallel_jobs,
|
||||
get_next_submodule,
|
||||
@ -1837,11 +1819,6 @@ int merge_submodule(struct object_id *result, const char *path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parallel_submodules(void)
|
||||
{
|
||||
return parallel_jobs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Embeds a single submodules git directory into the superprojects git dir,
|
||||
* non recursively.
|
||||
|
@ -33,7 +33,8 @@ struct submodule_update_strategy {
|
||||
};
|
||||
#define SUBMODULE_UPDATE_STRATEGY_INIT {SM_UPDATE_UNSPECIFIED, NULL}
|
||||
|
||||
extern int is_staging_gitmodules_ok(void);
|
||||
extern int is_gitmodules_unmerged(const struct index_state *istate);
|
||||
extern int is_staging_gitmodules_ok(const struct index_state *istate);
|
||||
extern int update_path_in_gitmodules(const char *oldpath, const char *newpath);
|
||||
extern int remove_path_from_gitmodules(const char *path);
|
||||
extern void stage_updated_gitmodules(void);
|
||||
@ -76,7 +77,6 @@ extern void show_submodule_inline_diff(FILE *f, const char *path,
|
||||
unsigned dirty_submodule, const char *meta,
|
||||
const char *del, const char *add, const char *reset,
|
||||
const struct diff_options *opt);
|
||||
extern void set_config_fetch_recurse_submodules(int value);
|
||||
/* Check if we want to update any submodule.*/
|
||||
extern int should_update_submodules(void);
|
||||
/*
|
||||
@ -87,6 +87,7 @@ extern const struct submodule *submodule_from_ce(const struct cache_entry *ce);
|
||||
extern void check_for_new_submodule_commits(struct object_id *oid);
|
||||
extern int fetch_populated_submodules(const struct argv_array *options,
|
||||
const char *prefix, int command_line_option,
|
||||
int default_option,
|
||||
int quiet, int max_parallel_jobs);
|
||||
extern unsigned is_submodule_modified(const char *path, int ignore_untracked);
|
||||
extern int submodule_uses_gitfile(const char *path);
|
||||
@ -112,7 +113,6 @@ extern int push_unpushed_submodules(struct oid_array *commits,
|
||||
const struct string_list *push_options,
|
||||
int dry_run);
|
||||
extern void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
|
||||
extern int parallel_submodules(void);
|
||||
/*
|
||||
* Given a submodule path (as in the index), return the repository
|
||||
* path of that submodule in 'buf'. Return -1 on error or when the
|
||||
|
@ -286,7 +286,7 @@ static void reload_gitmodules_file(struct index_state *index,
|
||||
for (i = 0; i < index->cache_nr; i++) {
|
||||
struct cache_entry *ce = index->cache[i];
|
||||
if (ce->ce_flags & CE_UPDATE) {
|
||||
int r = strcmp(ce->name, ".gitmodules");
|
||||
int r = strcmp(ce->name, GITMODULES_FILE);
|
||||
if (r < 0)
|
||||
continue;
|
||||
else if (r == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user