From: Junio C Hamano Date: Tue, 9 Jul 2019 22:25:46 +0000 (-0700) Subject: Merge branch 'ms/submodule-foreach-fix' X-Git-Tag: v2.23.0-rc0~57 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/968eecbd01e06aa8cae6c7fd8bf0a7b9bbd3b1fc?ds=inline;hp=-c Merge branch 'ms/submodule-foreach-fix' "git submodule foreach" did not protect command line options passed to the command to be run in each submodule correctly, when the "--recursive" option was in use. * ms/submodule-foreach-fix: submodule foreach: fix recursion of options --- 968eecbd01e06aa8cae6c7fd8bf0a7b9bbd3b1fc diff --combined builtin/submodule--helper.c index 13da32d3b7,61a5bfb1f2..909e77e802 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@@ -1,4 -1,3 +1,4 @@@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "repository.h" #include "cache.h" @@@ -348,7 -347,7 +348,7 @@@ static int module_list_compute(int argc i++; } - if (ps_matched && report_path_error(ps_matched, pathspec, prefix)) + if (ps_matched && report_path_error(ps_matched, pathspec)) result = -1; free(ps_matched); @@@ -540,6 -539,7 +540,7 @@@ static void runcommand_in_submodule_cb( if (info->quiet) argv_array_push(&cpr.args, "--quiet"); + argv_array_push(&cpr.args, "--"); argv_array_pushv(&cpr.args, info->argv); if (run_command(&cpr)) @@@ -566,12 -566,12 +567,12 @@@ static int module_foreach(int argc, con }; const char *const git_submodule_helper_usage[] = { - N_("git submodule--helper foreach [--quiet] [--recursive] "), + N_("git submodule--helper foreach [--quiet] [--recursive] [--] "), NULL }; argc = parse_options(argc, argv, prefix, module_foreach_options, - git_submodule_helper_usage, PARSE_OPT_KEEP_UNKNOWN); + git_submodule_helper_usage, 0); if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0) return 1; @@@ -709,7 -709,7 +710,7 @@@ static int module_init(int argc, const }; const char *const git_submodule_helper_usage[] = { - N_("git submodule--helper init []"), + N_("git submodule--helper init [] []"), NULL }; @@@ -1132,8 -1132,6 +1133,8 @@@ static void deinit_submodule(const cha if (!(flags & OPT_QUIET)) printf(format, displaypath); + submodule_unset_core_worktree(sub); + strbuf_release(&sb_rm); } @@@ -1268,20 -1266,19 +1269,20 @@@ struct submodule_alternate_setup SUBMODULE_ALTERNATE_ERROR_IGNORE, NULL } static int add_possible_reference_from_superproject( - struct alternate_object_database *alt, void *sas_cb) + struct object_directory *odb, void *sas_cb) { struct submodule_alternate_setup *sas = sas_cb; + size_t len; /* * If the alternate object store is another repository, try the * standard layout with .git/(modules/)+/objects */ - if (ends_with(alt->path, "/objects")) { + if (strip_suffix(odb->path, "/objects", &len)) { char *sm_alternate; struct strbuf sb = STRBUF_INIT; struct strbuf err = STRBUF_INIT; - strbuf_add(&sb, alt->path, strlen(alt->path) - strlen("objects")); + strbuf_add(&sb, odb->path, len); /* * We need to end the new path with '/' to mark it as a dir, @@@ -1289,7 -1286,7 +1290,7 @@@ * as the last part of a missing submodule reference would * be taken as a file name. */ - strbuf_addf(&sb, "modules/%s/", sas->submodule_name); + strbuf_addf(&sb, "/modules/%s/", sas->submodule_name); sm_alternate = compute_alternate_path(sb.buf, &err); if (sm_alternate) { @@@ -1301,7 -1298,7 +1302,7 @@@ die(_("submodule '%s' cannot add alternate: %s"), sas->submodule_name, err.buf); case SUBMODULE_ALTERNATE_ERROR_INFO: - fprintf(stderr, _("submodule '%s' cannot add alternate: %s"), + fprintf_ln(stderr, _("submodule '%s' cannot add alternate: %s"), sas->submodule_name, err.buf); case SUBMODULE_ALTERNATE_ERROR_IGNORE: ; /* nothing */ @@@ -1555,7 -1552,7 +1556,7 @@@ struct submodule_update_clone #define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \ SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, \ NULL, NULL, NULL, \ - NULL, 0, 0, 0, NULL, 0, 0, 0} + NULL, 0, 0, 0, NULL, 0, 0, 1} static void next_submodule_warn_missing(struct submodule_update_clone *suc, @@@ -1816,10 -1813,11 +1817,10 @@@ static int update_submodules(struct sub { int i; - run_processes_parallel(suc->max_jobs, - update_clone_get_next_task, - update_clone_start_failure, - update_clone_task_finished, - suc); + run_processes_parallel_tr2(suc->max_jobs, update_clone_get_next_task, + update_clone_start_failure, + update_clone_task_finished, suc, "submodule", + "parallel/update"); /* * We saved the output and put it out all at once now. @@@ -2048,7 -2046,7 +2049,7 @@@ static int ensure_core_worktree(int arg struct repository subrepo; if (argc != 2) - BUG("submodule--helper connect-gitdir-workingtree "); + BUG("submodule--helper ensure-core-worktree "); path = argv[1]; @@@ -2056,7 -2054,7 +2057,7 @@@ if (!sub) BUG("We could get the submodule handle before?"); - if (repo_submodule_init(&subrepo, the_repository, path)) + if (repo_submodule_init(&subrepo, the_repository, sub)) die(_("could not get a repository handle for submodule '%s'"), path); if (!repo_config_get_string(&subrepo, "core.worktree", &cw)) { @@@ -2096,7 -2094,7 +2097,7 @@@ static int absorb_git_dirs(int argc, co }; const char *const git_submodule_helper_usage[] = { - N_("git submodule--helper embed-git-dir [...]"), + N_("git submodule--helper absorb-git-dirs [] [...]"), NULL }; @@@ -2107,7 -2105,8 +2108,7 @@@ return 1; for (i = 0; i < list.nr; i++) - absorb_git_dir_into_superproject(prefix, - list.entries[i]->name, flags); + absorb_git_dir_into_superproject(list.entries[i]->name, flags); return 0; } @@@ -2146,22 -2145,17 +2147,22 @@@ static int check_name(int argc, const c static int module_config(int argc, const char **argv, const char *prefix) { enum { - CHECK_WRITEABLE = 1 + CHECK_WRITEABLE = 1, + DO_UNSET = 2 } command = 0; struct option module_config_options[] = { OPT_CMDMODE(0, "check-writeable", &command, N_("check if it is safe to write to the .gitmodules file"), CHECK_WRITEABLE), + OPT_CMDMODE(0, "unset", &command, + N_("unset the config in the .gitmodules file"), + DO_UNSET), OPT_END() }; const char *const git_submodule_helper_usage[] = { - N_("git submodule--helper config name [value]"), + N_("git submodule--helper config []"), + N_("git submodule--helper config --unset "), N_("git submodule--helper config --check-writeable"), NULL }; @@@ -2173,17 -2167,15 +2174,17 @@@ return is_writing_gitmodules_ok() ? 0 : -1; /* Equivalent to ACTION_GET in builtin/config.c */ - if (argc == 2) + if (argc == 2 && command != DO_UNSET) return print_config_from_gitmodules(the_repository, argv[1]); /* Equivalent to ACTION_SET in builtin/config.c */ - if (argc == 3) { + if (argc == 3 || (argc == 2 && command == DO_UNSET)) { + const char *value = (argc == 3) ? argv[2] : NULL; + if (!is_writing_gitmodules_ok()) die(_("please make sure that the .gitmodules file is in the working tree")); - return config_set_in_gitmodules_file_gently(argv[1], argv[2]); + return config_set_in_gitmodules_file_gently(argv[1], value); } usage_with_options(git_submodule_helper_usage, module_config_options); diff --combined t/t7407-submodule-foreach.sh index 706ae762e0,57e4b7f990..6b2aa917e1 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@@ -411,14 -411,11 +411,21 @@@ test_expect_success 'multi-argument com test_cmp expected actual ' +test_expect_success 'option-like arguments passed to foreach commands are not lost' ' + ( + cd super && + git submodule foreach "echo be --quiet" > ../expected && + git submodule foreach echo be --quiet > ../actual + ) && + grep -sq -e "--quiet" expected && + test_cmp expected actual +' + + test_expect_success 'option-like arguments passed to foreach recurse correctly' ' + git -C clone2 submodule foreach --recursive "echo be --an-option" >expect && + git -C clone2 submodule foreach --recursive echo be --an-option >actual && + grep -e "--an-option" expect && + test_cmp expect actual + ' + test_done