From: Prathamesh Chavan <pc44800@gmail.com>
To: git@vger.kernel.org
Cc: sbeller@google.com, christian.couder@gmail.com,
Prathamesh Chavan <pc44800@gmail.com>
Subject: [GSoC][PATCH 13/13] submodule: port submodule subcommand 'foreach' from shell to C
Date: Tue, 25 Jul 2017 02:04:54 +0530 [thread overview]
Message-ID: <20170724203454.13947-14-pc44800@gmail.com> (raw)
In-Reply-To: <20170724203454.13947-1-pc44800@gmail.com>
This aims to make git-submodule foreach a builtin. This is the very
first step taken in this direction. Hence, 'foreach' is ported to
submodule--helper, and submodule--helper is called from git-submodule.sh.
The code is split up to have one function to obtain all the list of
submodules. This function acts as the front-end of git-submodule foreach
subcommand. It calls the function for_each_submodule_list, which basically
loops through the list and calls function fn, which in this case is
runcommand_in_submodule. This third function is a calling function that
takes care of running the command in that submodule, and recursively
perform the same when --recursive is flagged.
The first function module_foreach first parses the options present in
argv, and then with the help of module_list_compute, generates the list of
submodules present in the current working tree.
The second function for_each_submodule_list traverses through the
list, and calls function fn (which in case of submodule subcommand
foreach is runcommand_in_submodule) is called for each entry.
The third function runcommand_in_submodule, generates a submodule struct sub
for $name, value and then later prepends name=sub->name; and other
value assignment to the env argv_array structure of a child_process.
Also the <command> of submodule-foreach is push to args argv_array
structure and finally, using run_command the commands are executed
using a shell.
The third function also takes care of the recursive flag, by creating
a separate child_process structure and prepending "--super-prefix displaypath",
to the args argv_array structure. Other required arguments and the
input <command> of submodule-foreach is also appended to this argv_array.
Helped-by: Brandon Williams <bmwill@google.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com>
---
builtin/submodule--helper.c | 129 ++++++++++++++++++++++++++++++++++++++++++++
git-submodule.sh | 39 +-------------
2 files changed, 130 insertions(+), 38 deletions(-)
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 94d6254f0..be278bf8d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -765,6 +765,134 @@ static int module_name(int argc, const char **argv, const char *prefix)
return 0;
}
+struct cb_foreach {
+ int argc;
+ const char **argv;
+ const char *prefix;
+ unsigned int quiet: 1;
+ unsigned int recursive: 1;
+};
+#define CB_FOREACH_INIT { 0, NULL, NULL, 0, 0 }
+
+static void runcommand_in_submodule(const struct cache_entry *list_item,
+ void *cb_data)
+{
+ struct cb_foreach *info = cb_data;
+ const struct submodule *sub;
+ struct child_process cp = CHILD_PROCESS_INIT;
+ char *displaypath;
+
+ displaypath = get_submodule_displaypath(list_item->name, info->prefix);
+
+ sub = submodule_from_path(null_sha1, list_item->name);
+
+ if (!sub)
+ die(_("No url found for submodule path '%s' in .gitmodules"),
+ displaypath);
+
+ if (!is_submodule_populated_gently(list_item->name, NULL))
+ goto cleanup;
+
+ prepare_submodule_repo_env(&cp.env_array);
+ /* For the purpose of executing <command> in the submodule,
+ * separate shell is used for the purpose of running the
+ * child process.
+ */
+ cp.use_shell = 1;
+ cp.dir = list_item->name;
+
+ if (info->argc == 1) {
+ char *toplevel = xgetcwd();
+
+ argv_array_pushf(&cp.env_array, "name=%s", sub->name);
+ argv_array_pushf(&cp.env_array, "sm_path=%s", list_item->name);
+ argv_array_pushf(&cp.env_array, "displaypath=%s", displaypath);
+ argv_array_pushf(&cp.env_array, "sha1=%s",
+ oid_to_hex(&list_item->oid));
+ argv_array_pushf(&cp.env_array, "toplevel=%s", toplevel);
+
+ /*
+ * Since still the path variable was accessible from the
+ * script before porting, it is also made available.
+ */
+ argv_array_pushf(&cp.args, "path=%s; %s",
+ list_item->name, info->argv[0]);
+ free(toplevel);
+ } else {
+ argv_array_pushv(&cp.args, info->argv);
+ }
+
+ if (!info->quiet)
+ printf(_("Entering '%s'\n"), displaypath);
+
+ if (info->argv[0] && run_command(&cp))
+ die(_("run_command returned non-zero status for %s\n."),
+ displaypath);
+
+ if (info->recursive) {
+ struct child_process cpr = CHILD_PROCESS_INIT;
+
+ cpr.git_cmd = 1;
+ cpr.dir = list_item->name;
+ prepare_submodule_repo_env(&cpr.env_array);
+
+ argv_array_pushl(&cpr.args, "--super-prefix", displaypath,
+ "submodule--helper", "foreach", "--recursive",
+ NULL);
+
+ if (info->quiet)
+ argv_array_push(&cpr.args, "--quiet");
+
+ argv_array_pushv(&cpr.args, info->argv);
+
+ if (run_command(&cpr))
+ die(_("run_command returned non-zero status while"
+ "recursing in the nested submodules of %s\n."),
+ displaypath);
+ }
+
+cleanup:
+ free(displaypath);
+}
+
+static int module_foreach(int argc, const char **argv, const char *prefix)
+{
+ struct cb_foreach info;
+ struct pathspec pathspec;
+ struct module_list list = MODULE_LIST_INIT;
+ int quiet = 0;
+ int recursive = 0;
+
+ struct option module_foreach_options[] = {
+ OPT__QUIET(&quiet, N_("Suppress output of entering each submodule command")),
+ OPT_BOOL(0, "recursive", &recursive,
+ N_("Recurse into nested submodules")),
+ OPT_END()
+ };
+
+ const char *const git_submodule_helper_usage[] = {
+ N_("git submodule--helper foreach [--quiet] [--recursive] <command>"),
+ NULL
+ };
+
+ argc = parse_options(argc, argv, prefix, module_foreach_options,
+ git_submodule_helper_usage, PARSE_OPT_KEEP_UNKNOWN);
+
+ if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
+ BUG("module_list_compute should not choke on empty pathspec");
+
+ info.argc = argc;
+ info.argv = argv;
+ info.prefix = prefix;
+ info.quiet = !!quiet;
+ info.recursive = !!recursive;
+
+ gitmodules_config();
+ for_each_submodule_list(list, runcommand_in_submodule, &info);
+
+ return 0;
+}
+
struct module_cb {
unsigned int mod_src;
unsigned int mod_dst;
@@ -2203,6 +2331,7 @@ static struct cmd_struct commands[] = {
{"resolve-relative-url", resolve_relative_url, 0},
{"resolve-relative-url-test", resolve_relative_url_test, 0},
{"print-name-rev", print_name_rev, 0},
+ {"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
{"init", module_init, SUPPORT_SUPER_PREFIX},
{"status", module_status, SUPPORT_SUPER_PREFIX},
{"print-default-remote", print_default_remote, 0},
diff --git a/git-submodule.sh b/git-submodule.sh
index 493a64372..e25b2c613 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -298,44 +298,7 @@ cmd_foreach()
shift
done
- toplevel=$(pwd)
-
- # dup stdin so that it can be restored when running the external
- # command in the subshell (and a recursive call to this function)
- exec 3<&0
-
- {
- git submodule--helper list --prefix "$wt_prefix" ||
- echo "#unmatched" $?
- } |
- while read -r mode sha1 stage sm_path
- do
- die_if_unmatched "$mode" "$sha1"
- if test -e "$sm_path"/.git
- then
- displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
- say "$(eval_gettext "Entering '\$displaypath'")"
- name=$(git submodule--helper name "$sm_path")
- (
- prefix="$prefix$sm_path/"
- sanitize_submodule_env
- cd "$sm_path" &&
- # we make $path available to scripts ...
- path=$sm_path &&
- if test $# -eq 1
- then
- eval "$1"
- else
- "$@"
- fi &&
- if test -n "$recursive"
- then
- cmd_foreach "--recursive" "$@"
- fi
- ) <&3 3<&- ||
- die "$(eval_gettext "Stopping at '\$displaypath'; script returned non-zero status.")"
- fi
- done
+ git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} "$@"
}
#
--
2.13.0
next prev parent reply other threads:[~2017-07-24 20:36 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-07-24 20:34 [GSoC][PATCH 00/13] Update: Week 10 Prathamesh Chavan
2017-07-24 20:34 ` [GSoC][PATCH 01/13] submodule--helper: introduce get_submodule_displaypath() Prathamesh Chavan
2017-07-24 20:34 ` [GSoC][PATCH 02/13] submodule--helper: introduce for_each_submodule_list() Prathamesh Chavan
2017-07-24 20:34 ` [GSoC][PATCH 03/13] submodule: port set_name_rev() from shell to C Prathamesh Chavan
2017-07-24 20:54 ` Brandon Williams
2017-07-24 20:34 ` [GSoC][PATCH 04/13] submodule: port submodule subcommand 'status' " Prathamesh Chavan
2017-07-24 21:30 ` Brandon Williams
2017-07-24 20:34 ` [GSoC][PATCH 05/13] submodule: port submodule subcommand 'sync' " Prathamesh Chavan
2017-07-24 21:52 ` Brandon Williams
2017-07-24 20:34 ` [GSoC][PATCH 06/13] submodule: port submodule subcommand 'deinit' " Prathamesh Chavan
2017-07-24 23:03 ` Brandon Williams
2017-07-24 20:34 ` [GSoC][PATCH 07/13] diff: change scope of the function count_lines() Prathamesh Chavan
2017-07-24 20:34 ` [GSoC][PATCH 08/13] submodule: port submodule subcommand 'summary' from shell to C Prathamesh Chavan
2017-07-25 0:09 ` Brandon Williams
2017-07-24 20:34 ` [GSoC][PATCH 09/13] submodule foreach: correct '$path' in nested submodules from a subdirectory Prathamesh Chavan
2017-07-25 0:13 ` Brandon Williams
2017-07-24 20:34 ` [GSoC][PATCH 10/13] submodule foreach: document '$sm_path' instead of '$path' Prathamesh Chavan
2017-07-25 0:15 ` Brandon Williams
2017-07-24 20:34 ` [GSoC][PATCH 11/13] submodule foreach: clarify the '$toplevel' variable documentation Prathamesh Chavan
2017-07-24 20:34 ` [GSoC][PATCH 12/13] submodule foreach: document variable '$displaypath' Prathamesh Chavan
2017-07-25 0:16 ` Brandon Williams
2017-07-24 20:34 ` Prathamesh Chavan [this message]
2017-07-25 0:29 ` [GSoC][PATCH 13/13] submodule: port submodule subcommand 'foreach' from shell to C Brandon Williams
2017-07-29 22:23 ` [GSoC][PATCH v2 00/13] Update: Week 10 Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 01/13] submodule--helper: introduce get_submodule_displaypath() Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 02/13] submodule--helper: introduce for_each_submodule_list() Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 03/13] submodule: port set_name_rev() from shell to C Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 04/13] submodule: port submodule subcommand 'status' " Prathamesh Chavan
2017-07-30 5:35 ` Christian Couder
2017-07-29 22:23 ` [GSoC][PATCH v2 05/13] submodule: port submodule subcommand 'sync' " Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 06/13] submodule: port submodule subcommand 'deinit' " Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 07/13] diff: change scope of the function count_lines() Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 08/13] submodule: port submodule subcommand 'summary' from shell to C Prathamesh Chavan
2017-07-30 5:28 ` Christian Couder
2017-07-30 6:33 ` Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 09/13] submodule foreach: correct '$path' in nested submodules from a subdirectory Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 10/13] submodule foreach: document '$sm_path' instead of '$path' Prathamesh Chavan
2017-07-29 22:23 ` [GSoC][PATCH v2 11/13] submodule foreach: clarify the '$toplevel' variable documentation Prathamesh Chavan
2017-07-29 22:24 ` [GSoC][PATCH v2 12/13] submodule foreach: document variable '$displaypath' Prathamesh Chavan
2017-07-29 22:24 ` [GSoC][PATCH v2 13/13] submodule: port submodule subcommand 'foreach' from shell to C Prathamesh Chavan
2017-07-31 20:28 ` [GSoC][PATCH v2 00/13] Update: Week 10 Brandon Williams
-- strict thread matches above, loose matches on Subject: below --
2017-07-31 20:56 [GSoC][PATCH 00/13] Update: Week-11 Prathamesh Chavan
2017-07-31 20:56 ` [GSoC][PATCH 13/13] submodule: port submodule subcommand 'foreach' from shell to C Prathamesh Chavan
2017-07-31 22:20 ` Stefan Beller
2017-08-07 21:18 [GSoC][PATCH 00/13] Update: Week-12 Prathamesh Chavan
2017-08-07 21:19 ` [GSoC][PATCH 13/13] submodule: port submodule subcommand 'foreach' from shell to C Prathamesh Chavan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170724203454.13947-14-pc44800@gmail.com \
--to=pc44800@gmail.com \
--cc=christian.couder@gmail.com \
--cc=git@vger.kernel.org \
--cc=sbeller@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.