Merge branch 'bw/submodule-config-cleanup'

Code clean-up to avoid mixing values read from the .gitmodules file
and values read from the .git/config file.

* bw/submodule-config-cleanup:
  submodule: remove gitmodules_config
  unpack-trees: improve loading of .gitmodules
  submodule-config: lazy-load a repository's .gitmodules file
  submodule-config: move submodule-config functions to submodule-config.c
  submodule-config: remove support for overlaying repository config
  diff: stop allowing diff to have submodules configured in .git/config
  submodule: remove submodule_config callback routine
  unpack-trees: don't respect submodule.update
  submodule: don't rely on overlayed config when setting diffopts
  fetch: don't overlay config with submodule-config
  submodule--helper: don't overlay config in update-clone
  submodule--helper: don't overlay config in remote_submodule_branch
  add, reset: ensure submodules can be added or reset
  submodule: don't use submodule_from_name
  t7411: check configuration parsing errors
This commit is contained in:
Junio C Hamano 2017-08-26 22:55:07 -07:00
Родитель 2adb614902 557a5998df
Коммит 614ea03a71
25 изменённых файлов: 192 добавлений и 373 удалений

Просмотреть файл

@ -116,6 +116,7 @@ int add_files_to_cache(const char *prefix,
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = update_callback;
rev.diffopt.format_callback_data = &data;
rev.diffopt.flags |= DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
return !!data.add_errors;

Просмотреть файл

@ -861,7 +861,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb)
}
if (starts_with(var, "submodule."))
return submodule_config(var, value, NULL);
return git_default_submodule_config(var, value, NULL);
return git_xmerge_config(var, value, NULL);
}
@ -1182,7 +1182,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
opts.prefix = prefix;
opts.show_progress = -1;
gitmodules_config();
git_config(git_checkout_config, &opts);
opts.track = BRANCH_TRACK_UNSPECIFIED;

Просмотреть файл

@ -195,7 +195,6 @@ static void determine_whence(struct wt_status *s)
static void status_init_config(struct wt_status *s, config_fn_t fn)
{
wt_status_prepare(s);
gitmodules_config();
git_config(fn, s);
determine_whence(s);
init_diff_ui_defaults();

Просмотреть файл

@ -26,7 +26,6 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
init_revisions(&rev, prefix);
gitmodules_config();
rev.abbrev = 0;
precompose_argv(argc, argv);

Просмотреть файл

@ -23,7 +23,6 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
init_revisions(&rev, prefix);
gitmodules_config();
rev.abbrev = 0;
precompose_argv(argc, argv);

Просмотреть файл

@ -110,7 +110,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
init_revisions(opt, prefix);
gitmodules_config();
opt->abbrev = 0;
opt->diff = 1;
opt->disable_stdin = 1;

Просмотреть файл

@ -315,8 +315,6 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
no_index = DIFF_NO_INDEX_IMPLICIT;
}
if (!no_index)
gitmodules_config();
init_diff_ui_defaults();
git_config(git_diff_ui_config, NULL);
precompose_argv(argc, argv);

Просмотреть файл

@ -1360,11 +1360,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
if (depth || deepen_since || deepen_not.nr)
deepen = 1;
if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
gitmodules_config();
git_config(submodule_config, NULL);
}
if (all) {
if (argc == 1)
die(_("fetch --all does not take a repository argument"));

Просмотреть файл

@ -1048,10 +1048,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
#endif
if (recurse_submodules) {
gitmodules_config();
}
if (show_in_pager && (cached || list.nr))
die(_("--open-files-in-pager only works on the worktree"));

Просмотреть файл

@ -19,6 +19,7 @@
#include "pathspec.h"
#include "run-command.h"
#include "submodule.h"
#include "submodule-config.h"
static int abbrev;
static int show_deleted;
@ -210,8 +211,6 @@ static void show_submodule(struct repository *superproject,
if (repo_read_index(&submodule) < 0)
die("index file corrupt");
repo_read_gitmodules(&submodule);
show_files(&submodule, dir);
repo_clear(&submodule);
@ -609,9 +608,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
if (require_work_tree && !is_inside_work_tree())
setup_work_tree();
if (recurse_submodules)
repo_read_gitmodules(the_repository);
if (recurse_submodules &&
(show_stage || show_deleted || show_others || show_unmerged ||
show_killed || show_modified || show_resolve_undo || with_tree))

Просмотреть файл

@ -131,7 +131,6 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
struct stat st;
struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
gitmodules_config();
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, builtin_mv_options,

Просмотреть файл

@ -164,8 +164,6 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
argc = parse_options(argc, argv, unused_prefix, read_tree_options,
read_tree_usage, 0);
load_submodule_cache();
hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
prefix_set = opts.prefix ? 1 : 0;

Просмотреть файл

@ -156,6 +156,7 @@ static int read_from_tree(const struct pathspec *pathspec,
opt.output_format = DIFF_FORMAT_CALLBACK;
opt.format_callback = update_index_from_diff;
opt.format_callback_data = &intent_to_add;
opt.flags |= DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
if (do_diff_cache(tree_oid, &opt))
return 1;
@ -308,8 +309,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_DASHDASH);
parse_args(&pathspec, argv, prefix, patch_mode, &rev);
load_submodule_cache();
unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
if (unborn) {
/* reset on unborn branch: treat as reset to empty tree */

Просмотреть файл

@ -255,7 +255,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
struct pathspec pathspec;
char *seen;
gitmodules_config();
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, builtin_rm_options,

Просмотреть файл

@ -275,8 +275,6 @@ static void module_list_active(struct module_list *list)
int i;
struct module_list active_modules = MODULE_LIST_INIT;
gitmodules_config();
for (i = 0; i < list->nr; i++) {
const struct cache_entry *ce = list->entries[i];
@ -337,9 +335,6 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
struct strbuf sb = STRBUF_INIT;
char *upd = NULL, *url = NULL, *displaypath;
/* Only loads from .gitmodules, no overlay with .git/config */
gitmodules_config();
if (prefix && get_super_prefix())
die("BUG: cannot have prefix and superprefix");
else if (prefix)
@ -475,7 +470,6 @@ static int module_name(int argc, const char **argv, const char *prefix)
if (argc != 2)
usage(_("git submodule--helper name <path>"));
gitmodules_config();
sub = submodule_from_path(&null_oid, argv[1]);
if (!sub)
@ -780,6 +774,10 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
struct strbuf *out)
{
const struct submodule *sub = NULL;
const char *url = NULL;
const char *update_string;
enum submodule_update_type update_type;
char *key;
struct strbuf displaypath_sb = STRBUF_INIT;
struct strbuf sb = STRBUF_INIT;
const char *displaypath = NULL;
@ -808,9 +806,17 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
goto cleanup;
}
key = xstrfmt("submodule.%s.update", sub->name);
if (!repo_config_get_string_const(the_repository, key, &update_string)) {
update_type = parse_submodule_update_type(update_string);
} else {
update_type = sub->update_strategy.type;
}
free(key);
if (suc->update.type == SM_UPDATE_NONE
|| (suc->update.type == SM_UPDATE_UNSPECIFIED
&& sub->update_strategy.type == SM_UPDATE_NONE)) {
&& update_type == SM_UPDATE_NONE)) {
strbuf_addf(out, _("Skipping submodule '%s'"), displaypath);
strbuf_addch(out, '\n');
goto cleanup;
@ -822,6 +828,11 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
goto cleanup;
}
strbuf_reset(&sb);
strbuf_addf(&sb, "submodule.%s.url", sub->name);
if (repo_config_get_string_const(the_repository, sb.buf, &url))
url = sub->url;
strbuf_reset(&sb);
strbuf_addf(&sb, "%s/.git", ce->name);
needs_cloning = !file_exists(sb.buf);
@ -851,7 +862,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
argv_array_push(&child->args, "--depth=1");
argv_array_pushl(&child->args, "--path", sub->path, NULL);
argv_array_pushl(&child->args, "--name", sub->name, NULL);
argv_array_pushl(&child->args, "--url", sub->url, NULL);
argv_array_pushl(&child->args, "--url", url, NULL);
if (suc->references.nr) {
struct string_list_item *item;
for_each_string_list_item(item, &suc->references)
@ -1025,10 +1036,6 @@ static int update_clone(int argc, const char **argv, const char *prefix)
if (pathspec.nr)
suc.warn_if_uninitialized = 1;
/* Overlay the parsed .gitmodules file with .git/config */
gitmodules_config();
git_config(submodule_config, NULL);
run_processes_parallel(max_jobs,
update_clone_get_next_task,
update_clone_start_failure,
@ -1066,17 +1073,22 @@ static int resolve_relative_path(int argc, const char **argv, const char *prefix
static const char *remote_submodule_branch(const char *path)
{
const struct submodule *sub;
gitmodules_config();
git_config(submodule_config, NULL);
const char *branch = NULL;
char *key;
sub = submodule_from_path(&null_oid, path);
if (!sub)
return NULL;
if (!sub->branch)
key = xstrfmt("submodule.%s.branch", sub->name);
if (repo_config_get_string_const(the_repository, key, &branch))
branch = sub->branch;
free(key);
if (!branch)
return "master";
if (!strcmp(sub->branch, ".")) {
if (!strcmp(branch, ".")) {
unsigned char sha1[20];
const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
@ -1094,7 +1106,7 @@ static const char *remote_submodule_branch(const char *path)
return refname;
}
return sub->branch;
return branch;
}
static int resolve_remote_submodule_branch(int argc, const char **argv,
@ -1213,9 +1225,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, embed_gitdir_options,
git_submodule_helper_usage, 0);
gitmodules_config();
git_config(submodule_config, NULL);
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
return 1;
@ -1231,8 +1240,6 @@ static int is_active(int argc, const char **argv, const char *prefix)
if (argc != 2)
die("submodule--helper is-active takes exactly 1 argument");
gitmodules_config();
return !is_submodule_active(the_repository, argv[1]);
}

3
diff.c
Просмотреть файл

@ -401,9 +401,6 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
return 0;
}
if (starts_with(var, "submodule."))
return parse_submodule_config_option(var, value);
if (git_diff_heuristic_config(var, value, cb) < 0)
return -1;

Просмотреть файл

@ -18,6 +18,7 @@ struct submodule_cache {
struct hashmap for_path;
struct hashmap for_name;
unsigned initialized:1;
unsigned gitmodules_read:1;
};
/*
@ -99,6 +100,7 @@ static void submodule_cache_clear(struct submodule_cache *cache)
hashmap_free(&cache->for_path, 1);
hashmap_free(&cache->for_name, 1);
cache->initialized = 0;
cache->gitmodules_read = 0;
}
void submodule_cache_free(struct submodule_cache *cache)
@ -455,9 +457,9 @@ static int parse_config(const char *var, const char *value, void *data)
return ret;
}
int gitmodule_oid_from_commit(const struct object_id *treeish_name,
struct object_id *gitmodules_oid,
struct strbuf *rev)
static int gitmodule_oid_from_commit(const struct object_id *treeish_name,
struct object_id *gitmodules_oid,
struct strbuf *rev)
{
int ret = 0;
@ -558,13 +560,11 @@ static void submodule_cache_check_init(struct repository *repo)
submodule_cache_init(repo->submodule_cache);
}
int submodule_config_option(struct repository *repo,
const char *var, const char *value)
static int gitmodules_cb(const char *var, const char *value, void *data)
{
struct repository *repo = data;
struct parse_config_parameter parameter;
submodule_cache_check_init(repo);
parameter.cache = repo->submodule_cache;
parameter.treeish_name = NULL;
parameter.gitmodules_sha1 = null_sha1;
@ -573,22 +573,63 @@ int submodule_config_option(struct repository *repo,
return parse_config(var, value, &parameter);
}
int parse_submodule_config_option(const char *var, const char *value)
void repo_read_gitmodules(struct repository *repo)
{
return submodule_config_option(the_repository, var, value);
submodule_cache_check_init(repo);
if (repo->worktree) {
char *gitmodules;
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);
}
repo->submodule_cache->gitmodules_read = 1;
}
void gitmodules_config_oid(const struct object_id *commit_oid)
{
struct strbuf rev = STRBUF_INIT;
struct object_id oid;
submodule_cache_check_init(the_repository);
if (gitmodule_oid_from_commit(commit_oid, &oid, &rev)) {
git_config_from_blob_oid(gitmodules_cb, rev.buf,
&oid, the_repository);
}
strbuf_release(&rev);
the_repository->submodule_cache->gitmodules_read = 1;
}
static void gitmodules_read_check(struct repository *repo)
{
submodule_cache_check_init(repo);
/* read the repo's .gitmodules file if it hasn't been already */
if (!repo->submodule_cache->gitmodules_read)
repo_read_gitmodules(repo);
}
const struct submodule *submodule_from_name(const struct object_id *treeish_name,
const char *name)
{
submodule_cache_check_init(the_repository);
gitmodules_read_check(the_repository);
return config_from(the_repository->submodule_cache, treeish_name, name, lookup_name);
}
const struct submodule *submodule_from_path(const struct object_id *treeish_name,
const char *path)
{
submodule_cache_check_init(the_repository);
gitmodules_read_check(the_repository);
return config_from(the_repository->submodule_cache, treeish_name, path, lookup_path);
}
@ -596,7 +637,7 @@ const struct submodule *submodule_from_cache(struct repository *repo,
const struct object_id *treeish_name,
const char *key)
{
submodule_cache_check_init(repo);
gitmodules_read_check(repo);
return config_from(repo->submodule_cache, treeish_name,
key, lookup_path);
}

Просмотреть файл

@ -34,9 +34,8 @@ extern int option_fetch_parse_recurse_submodules(const struct option *opt,
const char *arg, int unset);
extern int parse_update_recurse_submodules_arg(const char *opt, const char *arg);
extern int parse_push_recurse_submodules_arg(const char *opt, const char *arg);
extern int parse_submodule_config_option(const char *var, const char *value);
extern int submodule_config_option(struct repository *repo,
const char *var, const char *value);
extern void repo_read_gitmodules(struct repository *repo);
extern void gitmodules_config_oid(const struct object_id *commit_oid);
extern const struct submodule *submodule_from_name(
const struct object_id *commit_or_tree, const char *name);
extern const struct submodule *submodule_from_path(
@ -44,9 +43,6 @@ extern const struct submodule *submodule_from_path(
extern const struct submodule *submodule_from_cache(struct repository *repo,
const struct object_id *treeish_name,
const char *key);
extern int gitmodule_oid_from_commit(const struct object_id *commit_oid,
struct object_id *gitmodules_oid,
struct strbuf *rev);
extern void submodule_free(void);
#endif /* SUBMODULE_CONFIG_H */

Просмотреть файл

@ -165,34 +165,21 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
{
const struct submodule *submodule = submodule_from_path(&null_oid, path);
if (submodule) {
if (submodule->ignore)
handle_ignore_submodules_arg(diffopt, submodule->ignore);
const char *ignore;
char *key;
key = xstrfmt("submodule.%s.ignore", submodule->name);
if (repo_config_get_string_const(the_repository, key, &ignore))
ignore = submodule->ignore;
free(key);
if (ignore)
handle_ignore_submodules_arg(diffopt, ignore);
else if (is_gitmodules_unmerged(&the_index))
DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
}
}
/* For loading from the .gitmodules file. */
static int git_modules_config(const char *var, const char *value, void *cb)
{
if (starts_with(var, "submodule."))
return parse_submodule_config_option(var, value);
return 0;
}
/* Loads all submodule settings from the config. */
int submodule_config(const char *var, const char *value, void *cb)
{
if (!strcmp(var, "submodule.recurse")) {
int v = git_config_bool(var, value) ?
RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
config_update_recurse_submodules = v;
return 0;
} else {
return git_modules_config(var, value, cb);
}
}
/* Cheap function that only determines if we're interested in submodules at all */
int git_default_submodule_config(const char *var, const char *value, void *cb)
{
@ -221,55 +208,6 @@ int option_parse_recurse_submodules_worktree_updater(const struct option *opt,
return 0;
}
void load_submodule_cache(void)
{
if (config_update_recurse_submodules == RECURSE_SUBMODULES_OFF)
return;
gitmodules_config();
git_config(submodule_config, NULL);
}
static int gitmodules_cb(const char *var, const char *value, void *data)
{
struct repository *repo = data;
return submodule_config_option(repo, var, value);
}
void repo_read_gitmodules(struct repository *repo)
{
if (repo->worktree) {
char *gitmodules;
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)
{
struct strbuf rev = STRBUF_INIT;
struct object_id oid;
if (gitmodule_oid_from_commit(commit_oid, &oid, &rev)) {
git_config_from_blob_oid(submodule_config, rev.buf,
&oid, NULL);
}
strbuf_release(&rev);
}
/*
* Determine if a submodule has been initialized at a given 'path'
*/
@ -398,24 +336,38 @@ void die_path_inside_submodule(const struct index_state *istate,
}
}
enum submodule_update_type parse_submodule_update_type(const char *value)
{
if (!strcmp(value, "none"))
return SM_UPDATE_NONE;
else if (!strcmp(value, "checkout"))
return SM_UPDATE_CHECKOUT;
else if (!strcmp(value, "rebase"))
return SM_UPDATE_REBASE;
else if (!strcmp(value, "merge"))
return SM_UPDATE_MERGE;
else if (*value == '!')
return SM_UPDATE_COMMAND;
else
return SM_UPDATE_UNSPECIFIED;
}
int parse_submodule_update_strategy(const char *value,
struct submodule_update_strategy *dst)
{
enum submodule_update_type type;
free((void*)dst->command);
dst->command = NULL;
if (!strcmp(value, "none"))
dst->type = SM_UPDATE_NONE;
else if (!strcmp(value, "checkout"))
dst->type = SM_UPDATE_CHECKOUT;
else if (!strcmp(value, "rebase"))
dst->type = SM_UPDATE_REBASE;
else if (!strcmp(value, "merge"))
dst->type = SM_UPDATE_MERGE;
else if (skip_prefix(value, "!", &value)) {
dst->type = SM_UPDATE_COMMAND;
dst->command = xstrdup(value);
} else
type = parse_submodule_update_type(value);
if (type == SM_UPDATE_UNSPECIFIED)
return -1;
dst->type = type;
if (type == SM_UPDATE_COMMAND)
dst->command = xstrdup(value + 1);
return 0;
}
@ -1130,7 +1082,6 @@ int submodule_touches_in_range(struct object_id *excl_oid,
struct argv_array args = ARGV_ARRAY_INIT;
int ret;
gitmodules_config();
/* No need to check if there are no submodules configured */
if (!submodule_from_path(NULL, NULL))
return 0;
@ -1179,19 +1130,27 @@ static int get_next_submodule(struct child_process *cp,
continue;
submodule = submodule_from_path(&null_oid, ce->name);
if (!submodule)
submodule = submodule_from_name(&null_oid, ce->name);
default_argv = "yes";
if (spf->command_line_option == RECURSE_SUBMODULES_DEFAULT) {
if (submodule &&
submodule->fetch_recurse !=
RECURSE_SUBMODULES_NONE) {
if (submodule->fetch_recurse ==
RECURSE_SUBMODULES_OFF)
int fetch_recurse = RECURSE_SUBMODULES_NONE;
if (submodule) {
char *key;
const char *value;
fetch_recurse = submodule->fetch_recurse;
key = xstrfmt("submodule.%s.fetchRecurseSubmodules", submodule->name);
if (!repo_config_get_string_const(the_repository, key, &value)) {
fetch_recurse = parse_fetch_recurse_submodules_arg(key, value);
}
free(key);
}
if (fetch_recurse != RECURSE_SUBMODULES_NONE) {
if (fetch_recurse == RECURSE_SUBMODULES_OFF)
continue;
if (submodule->fetch_recurse ==
RECURSE_SUBMODULES_ON_DEMAND) {
if (fetch_recurse == RECURSE_SUBMODULES_ON_DEMAND) {
if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
continue;
default_argv = "on-demand";
@ -2029,7 +1988,6 @@ int submodule_to_gitdir(struct strbuf *buf, const char *submodule)
strbuf_addstr(buf, git_dir);
}
if (!is_git_directory(buf->buf)) {
gitmodules_config();
sub = submodule_from_path(&null_oid, submodule);
if (!sub) {
ret = -1;

Просмотреть файл

@ -40,16 +40,11 @@ extern int remove_path_from_gitmodules(const char *path);
extern void stage_updated_gitmodules(void);
extern void set_diffopt_flags_from_submodule_config(struct diff_options *,
const char *path);
extern int submodule_config(const char *var, const char *value, void *cb);
extern int git_default_submodule_config(const char *var, const char *value, void *cb);
struct option;
int option_parse_recurse_submodules_worktree_updater(const struct option *opt,
const char *arg, int unset);
void load_submodule_cache(void);
extern void gitmodules_config(void);
extern void repo_read_gitmodules(struct repository *repo);
extern void gitmodules_config_oid(const struct object_id *commit_oid);
extern int is_submodule_active(struct repository *repo, const char *path);
/*
* Determine if a submodule has been populated at a given 'path' by checking if
@ -62,6 +57,7 @@ extern void die_in_unpopulated_submodule(const struct index_state *istate,
const char *prefix);
extern void die_path_inside_submodule(const struct index_state *istate,
const struct pathspec *ps);
extern enum submodule_update_type parse_submodule_update_type(const char *value);
extern int parse_submodule_update_strategy(const char *value,
struct submodule_update_strategy *dst);
extern const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);

Просмотреть файл

@ -10,11 +10,6 @@ static void die_usage(int argc, const char **argv, const char *msg)
exit(1);
}
static int git_test_config(const char *var, const char *value, void *cb)
{
return parse_submodule_config_option(var, value);
}
int cmd_main(int argc, const char **argv)
{
const char **arg = argv;
@ -37,8 +32,6 @@ int cmd_main(int argc, const char **argv)
die_usage(argc, argv, "Wrong number of arguments.");
setup_git_directory();
gitmodules_config();
git_config(git_test_config, NULL);
while (*arg) {
struct object_id commit_oid;

Просмотреть файл

@ -113,35 +113,6 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)'
! test -s actual4
'
test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.git/config]' '
git config diff.ignoreSubmodules all &&
git diff HEAD >actual &&
! test -s actual &&
git config submodule.subname.ignore none &&
git config submodule.subname.path sub &&
git diff HEAD >actual &&
sed -e "1,/^@@/d" actual >actual.body &&
expect_from_to >expect.body $subprev $subprev-dirty &&
test_cmp expect.body actual.body &&
git config submodule.subname.ignore all &&
git diff HEAD >actual2 &&
! test -s actual2 &&
git config submodule.subname.ignore untracked &&
git diff HEAD >actual3 &&
sed -e "1,/^@@/d" actual3 >actual3.body &&
expect_from_to >expect.body $subprev $subprev-dirty &&
test_cmp expect.body actual3.body &&
git config submodule.subname.ignore dirty &&
git diff HEAD >actual4 &&
! test -s actual4 &&
git diff HEAD --ignore-submodules=none >actual &&
sed -e "1,/^@@/d" actual >actual.body &&
expect_from_to >expect.body $subprev $subprev-dirty &&
test_cmp expect.body actual.body &&
git config --remove-section submodule.subname &&
git config --unset diff.ignoreSubmodules
'
test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match) [.gitmodules]' '
git config diff.ignoreSubmodules dirty &&
git diff HEAD >actual &&
@ -208,24 +179,6 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)'
! test -s actual4
'
test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) [.git/config]' '
git config submodule.subname.ignore all &&
git config submodule.subname.path sub &&
git diff HEAD >actual2 &&
! test -s actual2 &&
git config submodule.subname.ignore untracked &&
git diff HEAD >actual3 &&
! test -s actual3 &&
git config submodule.subname.ignore dirty &&
git diff HEAD >actual4 &&
! test -s actual4 &&
git diff --ignore-submodules=none HEAD >actual &&
sed -e "1,/^@@/d" actual >actual.body &&
expect_from_to >expect.body $subprev $subprev-dirty &&
test_cmp expect.body actual.body &&
git config --remove-section submodule.subname
'
test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match) [.gitmodules]' '
git config --add -f .gitmodules submodule.subname.ignore all &&
git config --add -f .gitmodules submodule.subname.path sub &&
@ -261,26 +214,6 @@ test_expect_success 'git diff between submodule commits' '
! test -s actual
'
test_expect_success 'git diff between submodule commits [.git/config]' '
git diff HEAD^..HEAD >actual &&
sed -e "1,/^@@/d" actual >actual.body &&
expect_from_to >expect.body $subtip $subprev &&
test_cmp expect.body actual.body &&
git config submodule.subname.ignore dirty &&
git config submodule.subname.path sub &&
git diff HEAD^..HEAD >actual &&
sed -e "1,/^@@/d" actual >actual.body &&
expect_from_to >expect.body $subtip $subprev &&
test_cmp expect.body actual.body &&
git config submodule.subname.ignore all &&
git diff HEAD^..HEAD >actual &&
! test -s actual &&
git diff --ignore-submodules=dirty HEAD^..HEAD >actual &&
sed -e "1,/^@@/d" actual >actual.body &&
expect_from_to >expect.body $subtip $subprev &&
git config --remove-section submodule.subname
'
test_expect_success 'git diff between submodule commits [.gitmodules]' '
git diff HEAD^..HEAD >actual &&
sed -e "1,/^@@/d" actual >actual.body &&

Просмотреть файл

@ -46,16 +46,6 @@ test_expect_success 'submodule update aborts on missing gitmodules url' '
test_must_fail git submodule init
'
test_expect_success 'configuration parsing' '
test_when_finished "rm -f .gitmodules" &&
cat >.gitmodules <<-\EOF &&
[submodule "s"]
path
ignore
EOF
test_must_fail git status
'
test_expect_success 'setup - repository in init subdirectory' '
mkdir init &&
(

Просмотреть файл

@ -31,6 +31,21 @@ test_expect_success 'submodule config cache setup' '
)
'
test_expect_success 'configuration parsing with error' '
test_when_finished "rm -rf repo" &&
test_create_repo repo &&
cat >repo/.gitmodules <<-\EOF &&
[submodule "s"]
path
ignore
EOF
(
cd repo &&
test_must_fail test-submodule-config "" s 2>actual &&
test_i18ngrep "bad config" actual
)
'
cat >super/expect <<EOF
Submodule name: 'a' for path 'a'
Submodule name: 'a' for path 'b'
@ -107,78 +122,6 @@ test_expect_success 'using different treeishs works' '
)
'
cat >super/expect_url <<EOF
Submodule url: 'git@somewhere.else.net:a.git' for path 'b'
Submodule url: 'git@somewhere.else.net:submodule.git' for path 'submodule'
EOF
cat >super/expect_local_path <<EOF
Submodule name: 'a' for path 'c'
Submodule name: 'submodule' for path 'submodule'
EOF
test_expect_success 'reading of local configuration' '
(cd super &&
old_a=$(git config submodule.a.url) &&
old_submodule=$(git config submodule.submodule.url) &&
git config submodule.a.url git@somewhere.else.net:a.git &&
git config submodule.submodule.url git@somewhere.else.net:submodule.git &&
test-submodule-config --url \
"" b \
"" submodule \
>actual &&
test_cmp expect_url actual &&
git config submodule.a.path c &&
test-submodule-config \
"" c \
"" submodule \
>actual &&
test_cmp expect_local_path actual &&
git config submodule.a.url "$old_a" &&
git config submodule.submodule.url "$old_submodule" &&
git config --unset submodule.a.path c
)
'
cat >super/expect_url <<EOF
Submodule url: '../submodule' for path 'b'
Submodule url: 'git@somewhere.else.net:submodule.git' for path 'submodule'
EOF
test_expect_success 'reading of local configuration for uninitialized submodules' '
(
cd super &&
git submodule deinit -f b &&
old_submodule=$(git config submodule.submodule.url) &&
git config submodule.submodule.url git@somewhere.else.net:submodule.git &&
test-submodule-config --url \
"" b \
"" submodule \
>actual &&
test_cmp expect_url actual &&
git config submodule.submodule.url "$old_submodule" &&
git submodule init b
)
'
cat >super/expect_fetchrecurse_die.err <<EOF
fatal: bad submodule.submodule.fetchrecursesubmodules argument: blabla
EOF
test_expect_success 'local error in fetchrecursesubmodule dies early' '
(cd super &&
git config submodule.submodule.fetchrecursesubmodules blabla &&
test_must_fail test-submodule-config \
"" b \
"" submodule \
>actual.out 2>actual.err &&
touch expect_fetchrecurse_die.out &&
test_cmp expect_fetchrecurse_die.out actual.out &&
test_cmp expect_fetchrecurse_die.err actual.err &&
git config --unset submodule.submodule.fetchrecursesubmodules
)
'
test_expect_success 'error in history in fetchrecursesubmodule lets continue' '
(cd super &&
git config -f .gitmodules \

Просмотреть файл

@ -1,5 +1,6 @@
#define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h"
#include "repository.h"
#include "config.h"
#include "dir.h"
#include "tree.h"
@ -255,47 +256,41 @@ static int check_submodule_move_head(const struct cache_entry *ce,
{
unsigned flags = SUBMODULE_MOVE_HEAD_DRY_RUN;
const struct submodule *sub = submodule_from_ce(ce);
if (!sub)
return 0;
if (o->reset)
flags |= SUBMODULE_MOVE_HEAD_FORCE;
switch (sub->update_strategy.type) {
case SM_UPDATE_UNSPECIFIED:
case SM_UPDATE_CHECKOUT:
if (submodule_move_head(ce->name, old_id, new_id, flags))
return o->gently ? -1 :
add_rejected_path(o, ERROR_WOULD_LOSE_SUBMODULE, ce->name);
return 0;
case SM_UPDATE_NONE:
return 0;
case SM_UPDATE_REBASE:
case SM_UPDATE_MERGE:
case SM_UPDATE_COMMAND:
default:
warning(_("submodule update strategy not supported for submodule '%s'"), ce->name);
return -1;
}
if (submodule_move_head(ce->name, old_id, new_id, flags))
return o->gently ? -1 :
add_rejected_path(o, ERROR_WOULD_LOSE_SUBMODULE, ce->name);
return 0;
}
static void reload_gitmodules_file(struct index_state *index,
struct checkout *state)
/*
* Preform the loading of the repository's gitmodules file. This function is
* used by 'check_update()' to perform loading of the gitmodules file in two
* differnt situations:
* (1) before removing entries from the working tree if the gitmodules file has
* been marked for removal. This situation is specified by 'state' == NULL.
* (2) before checking out entries to the working tree if the gitmodules file
* has been marked for update. This situation is specified by 'state' != NULL.
*/
static void load_gitmodules_file(struct index_state *index,
struct checkout *state)
{
int i;
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_FILE);
if (r < 0)
continue;
else if (r == 0) {
submodule_free();
checkout_entry(ce, state, NULL);
gitmodules_config();
git_config(submodule_config, NULL);
} else
break;
int pos = index_name_pos(index, GITMODULES_FILE, strlen(GITMODULES_FILE));
if (pos >= 0) {
struct cache_entry *ce = index->cache[pos];
if (!state && ce->ce_flags & CE_WT_REMOVE) {
repo_read_gitmodules(the_repository);
} else if (state && (ce->ce_flags & CE_UPDATE)) {
submodule_free();
checkout_entry(ce, state, NULL);
repo_read_gitmodules(the_repository);
}
}
}
@ -308,19 +303,9 @@ static void unlink_entry(const struct cache_entry *ce)
{
const struct submodule *sub = submodule_from_ce(ce);
if (sub) {
switch (sub->update_strategy.type) {
case SM_UPDATE_UNSPECIFIED:
case SM_UPDATE_CHECKOUT:
case SM_UPDATE_REBASE:
case SM_UPDATE_MERGE:
/* state.force is set at the caller. */
submodule_move_head(ce->name, "HEAD", NULL,
SUBMODULE_MOVE_HEAD_FORCE);
break;
case SM_UPDATE_NONE:
case SM_UPDATE_COMMAND:
return; /* Do not touch the submodule. */
}
/* state.force is set at the caller. */
submodule_move_head(ce->name, "HEAD", NULL,
SUBMODULE_MOVE_HEAD_FORCE);
}
if (!check_leading_path(ce->name, ce_namelen(ce)))
return;
@ -364,6 +349,10 @@ static int check_updates(struct unpack_trees_options *o)
if (o->update)
git_attr_set_direction(GIT_ATTR_CHECKOUT, index);
if (should_update_submodules() && o->update && !o->dry_run)
load_gitmodules_file(index, NULL);
for (i = 0; i < index->cache_nr; i++) {
const struct cache_entry *ce = index->cache[i];
@ -377,7 +366,7 @@ static int check_updates(struct unpack_trees_options *o)
remove_scheduled_dirs();
if (should_update_submodules() && o->update && !o->dry_run)
reload_gitmodules_file(index, &state);
load_gitmodules_file(index, &state);
enable_delayed_checkout(&state);
for (i = 0; i < index->cache_nr; i++) {