git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[WIP/PATCH 5/9] Teach bisect--helper the --[no-]recurse-submodules option

From
Jens Lehmann <jens.lehmann@web.de>
Date
Feb 3, 2014, 19:51 UTC
Message-ID
<52EFF337.3060308@web.de>
In-Reply-To
<52EFF25E.6080306@web.de>

This is necessary before we can teach 'git bisect' this option, as that calls the bisect--helper to do the actual work which then in turn calls 'git checkout'. The helper just passes the option given on the command line on to checkout. The new recurse_submodules_enum_to_option() is added to avoid having the helper learn the command line representation of the different option values himself.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
---
 bisect.c                 | 33 ++++++++++++++++++++++-----------
 bisect.h                 |  3 ++-
 builtin/bisect--helper.c |  9 ++++++++-
 submodule.c              | 21 +++++++++++++++++++++
 submodule.h              |  1 +
 5 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/bisect.c b/bisect.c
index 37200b4..b84e607 100644
--- a/bisect.c
+++ b/bisect.c
@@ -11,13 +11,13 @@
 #include "bisect.h"
 #include "sha1-array.h"
 #include "argv-array.h"
+#include "submodule.h"

 static struct sha1_array good_revs;
 static struct sha1_array skipped_revs;

 static unsigned char *current_bad_sha1;

-static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
 static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
 static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL};

@@ -683,22 +683,30 @@ static void mark_expected_rev(char *bisect_rev_hex)
 		die("closing file %s: %s", filename, strerror(errno));
 }

-static int bisect_checkout(char *bisect_rev_hex, int no_checkout)
+static int bisect_checkout(char *bisect_rev_hex, int no_checkout,
+			   const char *recurse_submodules)
 {
 	int res;

 	mark_expected_rev(bisect_rev_hex);

-	argv_checkout[2] = bisect_rev_hex;
 	if (no_checkout) {
 		argv_update_ref[3] = bisect_rev_hex;
 		if (run_command_v_opt(argv_update_ref, RUN_GIT_CMD))
 			die("update-ref --no-deref HEAD failed on %s",
 			    bisect_rev_hex);
 	} else {
-		res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
+		struct argv_array argv = ARGV_ARRAY_INIT;
+		argv_array_push(&argv, "checkout");
+		argv_array_push(&argv, "-q");
+		if (recurse_submodules)
+		    argv_array_push(&argv, recurse_submodules);
+		argv_array_push(&argv, bisect_rev_hex);
+		argv_array_push(&argv, "--");
+		res = run_command_v_opt(argv.argv, RUN_GIT_CMD);
 		if (res)
 			exit(res);
+		argv_array_clear(&argv);
 	}

 	argv_show_branch[1] = bisect_rev_hex;
@@ -771,7 +779,7 @@ static void handle_skipped_merge_base(const unsigned char *mb)
  * - If one is "skipped", we can't know but we should warn.
  * - If we don't know, we should check it out and ask the user to test.
  */
-static void check_merge_bases(int no_checkout)
+static void check_merge_bases(int no_checkout, const char *recurse_submodules)
 {
 	struct commit_list *result;
 	int rev_nr;
@@ -789,7 +797,8 @@ static void check_merge_bases(int no_checkout)
 			handle_skipped_merge_base(mb);
 		} else {
 			printf("Bisecting: a merge base must be tested\n");
-			exit(bisect_checkout(sha1_to_hex(mb), no_checkout));
+			exit(bisect_checkout(sha1_to_hex(mb), no_checkout,
+					     recurse_submodules));
 		}
 	}

@@ -832,7 +841,8 @@ static int check_ancestors(const char *prefix)
  * If a merge base must be tested by the user, its source code will be
  * checked out to be tested by the user and we will exit.
  */
-static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
+static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout,
+					    const char *recurse_submodules)
 {
 	char *filename = git_pathdup("BISECT_ANCESTORS_OK");
 	struct stat st;
@@ -851,7 +861,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)

 	/* Check if all good revs are ancestor of the bad rev. */
 	if (check_ancestors(prefix))
-		check_merge_bases(no_checkout);
+		check_merge_bases(no_checkout, recurse_submodules);

 	/* Create file BISECT_ANCESTORS_OK. */
 	fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
@@ -897,7 +907,8 @@ static void show_diff_tree(const char *prefix, struct commit *commit)
  * If no_checkout is non-zero, the bisection process does not
  * checkout the trial commit but instead simply updates BISECT_HEAD.
  */
-int bisect_next_all(const char *prefix, int no_checkout)
+int bisect_next_all(const char *prefix, int no_checkout,
+		    const char *recurse_submodules)
 {
 	struct rev_info revs;
 	struct commit_list *tried;
@@ -908,7 +919,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
 	if (read_bisect_refs())
 		die("reading bisect refs failed");

-	check_good_are_ancestors_of_bad(prefix, no_checkout);
+	check_good_are_ancestors_of_bad(prefix, no_checkout, recurse_submodules);

 	bisect_rev_setup(&revs, prefix, "%s", "^%s", 1);
 	revs.limited = 1;
@@ -954,7 +965,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
 	       "(roughly %d step%s)\n", nr, (nr == 1 ? "" : "s"),
 	       steps, (steps == 1 ? "" : "s"));

-	return bisect_checkout(bisect_rev_hex, no_checkout);
+	return bisect_checkout(bisect_rev_hex, no_checkout, recurse_submodules);
 }

 static inline int log2i(int n)
diff --git a/bisect.h b/bisect.h
index 2a6c831..5c1ea9c 100644
--- a/bisect.h
+++ b/bisect.h
@@ -22,7 +22,8 @@ struct rev_list_info {
 	const char *header_prefix;
 };

-extern int bisect_next_all(const char *prefix, int no_checkout);
+extern int bisect_next_all(const char *prefix, int no_checkout,
+			   const char *recurse_submodules);

 extern int estimate_bisect_steps(int all);

diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 3324229..b30087a 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -2,6 +2,7 @@
 #include "cache.h"
 #include "parse-options.h"
 #include "bisect.h"
+#include "submodule.h"

 static const char * const git_bisect_helper_usage[] = {
 	N_("git bisect--helper --next-all [--no-checkout]"),
@@ -12,11 +13,16 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 {
 	int next_all = 0;
 	int no_checkout = 0;
+	int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
+
 	struct option options[] = {
 		OPT_BOOL(0, "next-all", &next_all,
 			 N_("perform 'git bisect next'")),
 		OPT_BOOL(0, "no-checkout", &no_checkout,
 			 N_("update BISECT_HEAD instead of checking out the current commit")),
+		{ OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
+			"checkout", "control recursive updating of submodules",
+			PARSE_OPT_OPTARG, option_parse_update_submodules },
 		OPT_END()
 	};

@@ -27,5 +33,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 		usage_with_options(git_bisect_helper_usage, options);

 	/* next-all */
-	return bisect_next_all(prefix, no_checkout);
+	return bisect_next_all(prefix, no_checkout,
+			       recurse_submodules_enum_to_option(recurse_submodules));
 }
diff --git a/submodule.c b/submodule.c
index b3eb28d..448b645 100644
--- a/submodule.c
+++ b/submodule.c
@@ -44,6 +44,27 @@ static int gitmodules_is_unmerged;
 static int gitmodules_is_modified;


+/*
+ * Convert values defined in the RECURSE_SUBMODULES_* enum to the string
+ * representation usable as command parameter. Returns NULL if no parameter
+ * is necessary.
+ */
+const char *recurse_submodules_enum_to_option(int recurse_submodules)
+{
+	switch(recurse_submodules) {
+	case RECURSE_SUBMODULES_ON_DEMAND:
+		return "--recurse-submodules=on-demand";
+	case RECURSE_SUBMODULES_OFF:
+		return "--no-recurse-submodules";
+	case RECURSE_SUBMODULES_ON:
+		return "--recurse-submodules";
+	case RECURSE_SUBMODULES_DEFAULT:
+		return NULL;
+	default:
+		die("Invalid recurse submodule value: %d", recurse_submodules);
+	}
+}
+
 int is_staging_gitmodules_ok(void)
 {
 	return !gitmodules_is_modified;
diff --git a/submodule.h b/submodule.h
index 79b336b..5958010 100644
--- a/submodule.h
+++ b/submodule.h
@@ -11,6 +11,7 @@ enum {
 	RECURSE_SUBMODULES_DEFAULT = 1,
 	RECURSE_SUBMODULES_ON = 2
 };
+const char *recurse_submodules_enum_to_option(int recurse_submodules);

 int is_staging_gitmodules_ok(void);
 int update_path_in_gitmodules(const char *oldpath, const char *newpath);
-- 
1.9.rc0.28.ge3363ff
Previous: W. Trevor KingNext: Jens Lehmann
Message 23 of 35 in “What's cooking in git.git (Jan 2014, #01; Mon, 6)”
  1. Junio C HamanoJan 6, 2014
  2. Francesco PrettoJan 6, 2014
  3. Junio C HamanoJan 6, 2014
  4. Francesco PrettoJan 6, 2014
  5. Jens LehmannJan 7, 2014
  6. 0/9 v2 submodule recursive checkout]Jens Lehmann, Feb 3, 2014
  7. 1/9 submodule: prepare for recursive checkout of submodulesJens Lehmann, Feb 3, 2014
  8. Junio C HamanoFeb 3, 2014
  9. Jens LehmannFeb 7, 2014
  10. Jonathan NiederFeb 4, 2014
  11. Jens LehmannFeb 7, 2014
  12. 2/9 Teach reset the --[no-]recurse-submodules optionJens Lehmann, Feb 3, 2014
  13. Junio C HamanoFeb 3, 2014
  14. Jens LehmannFeb 7, 2014
  15. 3/9 Teach checkout the --[no-]recurse-submodules optionJens Lehmann, Feb 3, 2014
  16. Junio C HamanoFeb 3, 2014
  17. Jens LehmannFeb 7, 2014
  18. 4/9 Teach merge the --[no-]recurse-submodules optionJens Lehmann, Feb 3, 2014
  19. Junio C HamanoFeb 3, 2014
  20. Jens LehmannFeb 7, 2014
  21. Junio C HamanoFeb 7, 2014
  22. W. Trevor KingFeb 7, 2014
  23. 5/9 Teach bisect--helper the --[no-]recurse-submodules optionJens Lehmann, Feb 3, 2014
  24. 6/9 Teach bisect the --[no-]recurse-submodules optionJens Lehmann, Feb 3, 2014
  25. W. Trevor KingFeb 3, 2014
  26. Jens LehmannFeb 3, 2014
  27. 7/9 submodule: teach unpack_trees() to remove submodule contentsJens Lehmann, Feb 3, 2014
  28. W. Trevor KingFeb 3, 2014
  29. Jens LehmannFeb 7, 2014
  30. 8/9 submodule: teach unpack_trees() to repopulate submodulesJens Lehmann, Feb 3, 2014
  31. 9/9 submodule: teach unpack_trees() to update submodulesJens Lehmann, Feb 3, 2014
  32. W. Trevor KingFeb 3, 2014
  33. Jens LehmannFeb 7, 2014
  34. Duy NguyenFeb 4, 2014
  35. Jens LehmannFeb 7, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.