git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep
@ 2022-07-28 16:16 Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 01/20] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
                   ` (22 more replies)
  0 siblings, 23 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

This new series based on "master" splits out the non-leak fixes from
v3 of the submodule leaks series [1]. Sorry about the churn, but with
e.g. the thread at [2] the "leaks" series was accumulating a lot of
non-leaks related fixes, just so that we could get to the point of
fixing various leaks.

The immediate reason I split this off was because of the new
"remove..helper" and "test-tool" patches here. I.e. some things that
the leaks series was changing was test-only code, or code that was
simply unused (or we had no business using anymore).

The [1] series will then be re-rolled on top of this series, which
will hopefully make it a lot easier to digest, as it'll now *just*
focus on leak fixes.

A passing CI run for this can be found at [3].

1. https://lore.kernel.org/git/cover-v3-00.26-00000000000-20220721T191249Z-avarab@gmail.com/
2. https://lore.kernel.org/git/220722.86y1wlqmqr.gmgdl@evledraar.gmail.com/
3. https://github.com/avar/git/tree/avar/submodule--helper-cleanup-and-tests

Glen Choo (2):
  submodule--helper: add "const" to copy of "update_data"
  submodule--helper: refactor "errmsg_str" to be a "struct strbuf"

Ævar Arnfjörð Bjarmason (18):
  submodule tests: test usage behavior
  submodule tests: test for "add <repository> <abs-path>"
  submodule--helper: remove unused "name" helper
  submodule--helper: remove unused "list" helper
  test-tool submodule-config: remove unused "--url" handling
  submodule--helper: move "is-active" to a test-tool
  submodule--helper: move "check-name" to a test-tool
  submodule--helper: move "resolve-relative-url-test" to a test-tool
  submodule--helper style: don't separate declared variables with \n\n
  submodule--helper style: add \n\n after variable declarations
  submodule--helper: replace memset() with { 0 }-initialization
  submodule--helper: convert a strbuf_detach() to xstrfmt()
  submodule--helper: stop conflating "sb" in clone_submodule()
  submodule--helper: pass a "const struct module_clone_data" to
    clone_submodule()
  submodule--helper: rename "int res" to "int ret"
  submodule--helper: add skeleton "goto cleanup" to update_submodule()
  submodule--helper: don't exit() on failure, return
  submodule--helper: fix bad config API usage

 Makefile                         |   1 +
 builtin/submodule--helper.c      | 338 ++++++++++++-------------------
 t/helper/test-submodule-config.c |  11 +-
 t/helper/test-submodule.c        | 146 +++++++++++++
 t/helper/test-tool-utils.h       |   9 +
 t/helper/test-tool.c             |   7 +-
 t/helper/test-tool.h             |   1 +
 t/t0060-path-utils.sh            |   2 +-
 t/t7400-submodule-basic.sh       |  56 ++---
 t/t7413-submodule-is-active.sh   |  32 +--
 t/t7450-bad-git-dotfiles.sh      |   2 +-
 11 files changed, 335 insertions(+), 270 deletions(-)
 create mode 100644 t/helper/test-submodule.c
 create mode 100644 t/helper/test-tool-utils.h

Range-diff:
 -:  ----------- >  1:  84b05bda016 submodule tests: test usage behavior
 -:  ----------- >  2:  9671169e348 submodule tests: test for "add <repository> <abs-path>"
 -:  ----------- >  3:  7aa9c14251b submodule--helper: remove unused "name" helper
 -:  ----------- >  4:  27df2efe718 submodule--helper: remove unused "list" helper
 -:  ----------- >  5:  9fe8deb165a test-tool submodule-config: remove unused "--url" handling
 -:  ----------- >  6:  8e4d2b09d56 submodule--helper: move "is-active" to a test-tool
 -:  ----------- >  7:  a2f3d812815 submodule--helper: move "check-name" to a test-tool
 -:  ----------- >  8:  8188657cdfa submodule--helper: move "resolve-relative-url-test" to a test-tool
 -:  ----------- >  9:  79a47f9b94d submodule--helper style: don't separate declared variables with \n\n
 -:  ----------- > 10:  5e13080f894 submodule--helper style: add \n\n after variable declarations
 1:  3c7ae3e0222 ! 11:  dc5ac924496 submodule--helper: replace memset() with { 0 }-initialization
    @@ builtin/submodule--helper.c: static int module_clone(int argc, const char **argv
      	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
     -	struct list_objects_filter_options filter_options;
     +	struct list_objects_filter_options filter_options = { 0 };
    - 
      	struct option module_clone_options[] = {
      		OPT_STRING(0, "prefix", &clone_data.prefix,
    + 			   N_("path"),
     @@ builtin/submodule--helper.c: static int module_clone(int argc, const char **argv, const char *prefix)
      		NULL
      	};
    @@ builtin/submodule--helper.c: static int module_update(int argc, const char **arg
     -	struct list_objects_filter_options filter_options;
     +	struct list_objects_filter_options filter_options = { 0 };
      	int ret;
    - 
      	struct option module_update_options[] = {
    + 		OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
     @@ builtin/submodule--helper.c: static int module_update(int argc, const char **argv, const char *prefix)
      	update_clone_config_from_gitmodules(&opt.max_jobs);
      	git_config(git_update_clone_config, &opt.max_jobs);
 -:  ----------- > 12:  08cc9ce2e24 submodule--helper: convert a strbuf_detach() to xstrfmt()
 2:  32e4ae7ead5 ! 13:  afe34d8b73b submodule--helper: stop conflating "sb" in clone_submodule()
    @@ Metadata
      ## Commit message ##
         submodule--helper: stop conflating "sb" in clone_submodule()
     
    -    Refactor the three uses of a "struct strbuf sb" such that each of them
    +    Refactor the two uses of a "struct strbuf sb" such that each of them
         exists in its own scope. This makes the control flow clearer.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
    @@ builtin/submodule--helper.c: static void prepare_possible_alternates(const char
     +	char *sm_alternate = NULL, *error_strategy = NULL;
     +	struct child_process cp = CHILD_PROCESS_INIT;
      
    - 	if (!is_absolute_path(clone_data->path)) {
    -+		struct strbuf sb = STRBUF_INIT;
    -+
    - 		strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
    - 		clone_data->path = strbuf_detach(&sb, NULL);
    - 	} else {
    + 	if (!is_absolute_path(clone_data->path))
    + 		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
     @@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data *clone_data)
      			die(_("clone of '%s' into submodule path '%s' failed"),
      			    clone_data->url, clone_data->path);
 3:  eee6ca28c6f ! 14:  b364f3200d8 submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
    @@ Commit message
         clobbering the "clone_data->path".
     
         We still need to add to the "reference" member, which is a "struct
    -    string_list". We could do this by having clone_submodule() create its
    -    own, and copy the contents over, but let's instead pass it as a
    -    separate parameter. The main point of doing this is to make it clear
    -    that e.g. "clone_data->path" always comes from the "argv", there's no
    -    ambiguity about whether we can eventually free() the "struct
    -    string_list".
    +    string_list". Let's do this by having clone_submodule() create its
    +    own, and copy the contents over, allowing us to pass it as a
    +    separate parameter.
    +
    +    This new "struct string_list" still leaks memory, just as the "struct
    +    module_clone_data" did before. let's not fix that for now, to fix that
    +    we'll need to add some "goto cleanup" to the relevant code. That will
    +    be done in a follow-up commits, at that point it'll be easier to fix
    +    the memory leak.
    +
    +    The scope of the new "reference" variable in add_submodule() could be
    +    narrowed to the "else" block, but as we'll eventually free it with a
    +    "goto cleanup" let's declare it at the start of the function.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    +@@ builtin/submodule--helper.c: struct module_clone_data {
    + 	const char *url;
    + 	const char *depth;
    + 	struct list_objects_filter_options *filter_options;
    +-	struct string_list reference;
    + 	unsigned int quiet: 1;
    + 	unsigned int progress: 1;
    + 	unsigned int dissociate: 1;
    +@@ builtin/submodule--helper.c: struct module_clone_data {
    + 	int single_branch;
    + };
    + #define MODULE_CLONE_DATA_INIT { \
    +-	.reference = STRING_LIST_INIT_NODUP, \
    + 	.single_branch = -1, \
    + }
    + 
     @@ builtin/submodule--helper.c: static char *clone_submodule_sm_gitdir(const char *name)
      	return sm_gitdir;
      }
    @@ builtin/submodule--helper.c: static char *clone_submodule_sm_gitdir(const char *
      	struct child_process cp = CHILD_PROCESS_INIT;
     +	const char *clone_data_path;
      
    - 	if (!is_absolute_path(clone_data->path)) {
    - 		struct strbuf sb = STRBUF_INIT;
    - 
    - 		strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
    --		clone_data->path = strbuf_detach(&sb, NULL);
    -+		clone_data_path = strbuf_detach(&sb, NULL);
    - 	} else {
    + 	if (!is_absolute_path(clone_data->path))
    +-		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
    +-					   clone_data->path);
    ++		clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
    ++					  clone_data->path);
    + 	else
     -		clone_data->path = xstrdup(clone_data->path);
    -+		clone_data_path = xstrdup(clone_data_path);
    - 	}
    ++		clone_data_path = xstrdup(clone_data->path);
      
      	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
    + 		die(_("refusing to create/use '%s' in another submodule's "
     @@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data *clone_data)
      		if (safe_create_leading_directories_const(sm_gitdir) < 0)
      			die(_("could not create directory '%s'"), sm_gitdir);
    @@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data
     -		if (clone_data->reference.nr) {
     +		if (reference->nr) {
      			struct string_list_item *item;
    + 
     -			for_each_string_list_item(item, &clone_data->reference)
     +			for_each_string_list_item(item, reference)
      				strvec_pushl(&cp.args, "--reference",
    @@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data
      
      	/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
      	git_config_get_string("submodule.alternateLocation", &sm_alternate);
    +@@ builtin/submodule--helper.c: static int module_clone(int argc, const char **argv, const char *prefix)
    + 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
    + 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
    + 	struct list_objects_filter_options filter_options = { 0 };
    ++	struct string_list reference = STRING_LIST_INIT_NODUP;
    + 	struct option module_clone_options[] = {
    + 		OPT_STRING(0, "prefix", &clone_data.prefix,
    + 			   N_("path"),
    +@@ builtin/submodule--helper.c: static int module_clone(int argc, const char **argv, const char *prefix)
    + 		OPT_STRING(0, "url", &clone_data.url,
    + 			   N_("string"),
    + 			   N_("url where to clone the submodule from")),
    +-		OPT_STRING_LIST(0, "reference", &clone_data.reference,
    ++		OPT_STRING_LIST(0, "reference", &reference,
    + 			   N_("repo"),
    + 			   N_("reference repository")),
    + 		OPT_BOOL(0, "dissociate", &dissociate,
     @@ builtin/submodule--helper.c: static int module_clone(int argc, const char **argv, const char *prefix)
      		usage_with_options(git_submodule_helper_usage,
      				   module_clone_options);
      
     -	clone_submodule(&clone_data);
    -+	clone_submodule(&clone_data, &clone_data.reference);
    ++	clone_submodule(&clone_data, &reference);
      	list_objects_filter_release(&filter_options);
      	return 0;
      }
     @@ builtin/submodule--helper.c: static int add_submodule(const struct add_data *add_data)
    + {
    + 	char *submod_gitdir_path;
    + 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
    ++	struct string_list reference = STRING_LIST_INIT_NODUP;
    + 
    + 	/* perhaps the path already exists and is already a git repo, else clone it */
    + 	if (is_directory(add_data->sm_path)) {
    +@@ builtin/submodule--helper.c: static int add_submodule(const struct add_data *add_data)
    + 		free(submod_gitdir_path);
    + 	} else {
    + 		struct child_process cp = CHILD_PROCESS_INIT;
    ++
    + 		submod_gitdir_path = xstrfmt(".git/modules/%s", add_data->sm_name);
    + 
    + 		if (is_directory(submod_gitdir_path)) {
    +@@ builtin/submodule--helper.c: static int add_submodule(const struct add_data *add_data)
    + 		clone_data.quiet = add_data->quiet;
    + 		clone_data.progress = add_data->progress;
    + 		if (add_data->reference_path)
    +-			string_list_append(&clone_data.reference,
    ++			string_list_append(&reference,
    + 					   xstrdup(add_data->reference_path));
    + 		clone_data.dissociate = add_data->dissociate;
      		if (add_data->depth >= 0)
      			clone_data.depth = xstrfmt("%d", add_data->depth);
      
     -		if (clone_submodule(&clone_data))
    -+		if (clone_submodule(&clone_data, &clone_data.reference))
    ++		if (clone_submodule(&clone_data, &reference))
      			return -1;
      
      		prepare_submodule_repo_env(&cp.env);
 4:  26f0caf0386 <  -:  ----------- submodule--helper: fix a leak in "clone_submodule"
 5:  75775bf4f6c <  -:  ----------- submodule--helper: fix trivial get_default_remote_submodule() leak
 6:  7672ef1305f <  -:  ----------- submodule--helper: fix most "struct pathspec" memory leaks
 7:  325aa1521e2 <  -:  ----------- submodule--helper: "struct pathspec" memory leak in module_update()
 8:  424b24961b5 <  -:  ----------- submodule--helper: don't leak {run,capture}_command() cp.dir argument
 9:  abf5c4754a4 = 15:  e319f4edc54 submodule--helper: add "const" to copy of "update_data"
10:  6ab5aabae35 <  -:  ----------- submodule--helper: add and use *_release() functions
11:  feec1f20bf9 = 16:  68202100d9a submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
12:  d368db73de7 <  -:  ----------- submodule--helper: fix "errmsg_str" memory leak
13:  5be941b3d1b <  -:  ----------- submodule--helper: fix "sm_path" and other "module_cb_list" leaks
14:  b8560e8c111 <  -:  ----------- submodule--helper: fix a leak with repo_clear()
15:  abfd61f9f05 <  -:  ----------- submodule--helper: fix a memory leak in get_default_remote_submodule()
16:  b8df96a9cf0 <  -:  ----------- submodule--helper: fix "reference" leak is "module_clone_data"
17:  7811bdbf149 <  -:  ----------- submodule--helper: fix obscure leak in module_add()
18:  01566d63926 <  -:  ----------- submodule--helper: fix a leak in module_add()
19:  7ef89abed86 <  -:  ----------- submodule--helper: fix a memory leak in print_status()
20:  b8d47fc7d70 <  -:  ----------- submodule--helper: free some "displaypath" in "struct update_data"
21:  4fb17f0dff1 ! 17:  e8aacb55a18 submodule--helper: rename "int res" to "int ret"
    @@ Commit message
     
         Rename the "res" variable added in b3c5f5cb048 (submodule: move core
         cmd_update() logic to C, 2022-03-15) to "ret", which is the convention
    -    in the rest of this file. Subsequent commits will change this code to
    -    a "goto cleanup" pattern, let's have the post image look consistent
    -    with the rest.
    +    in the rest of this file.
    +
    +    Eventual follow-up commits will change this code to a "goto cleanup"
    +    pattern, let's have the post image look consistent with the rest.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
22:  af83925046b ! 18:  41fb22d8549 submodule--helper: add skeleton "goto cleanup" to update_submodule()
    @@ Commit message
         submodule--helper: add skeleton "goto cleanup" to update_submodule()
     
         Add a skeleton "goto cleanup" pattern to update_submodule(), rather
    -    than having branches in it "return". This is in preparation for doing
    -    something useful with the "cleanup" label, but for now we're using it
    -    as the equivalent of a "done" label.
    +    than having branches in it "return". This is in preparation for
    +    eventually freeing data with the "cleanup" label, but for now we're
    +    using it as the equivalent of a "done" label.
     
         The "exit()" branch is not handled yet, and neither is the exit() that
         run_update_procedure() might invoke. That'll be handled in a
23:  4c60784d281 ! 19:  5a26c9428be submodule--helper: don't exit() on failure, return
    @@ Commit message
         to the point where we could avoid calling exit() here.
     
         This introduces no functional changes, but makes it easier to both
    -    call these routines as a library in the future, and to avoid leaking
    -    memory.
    +    call these routines as a library in the future, and to eventually
    +    avoid leaking memory.
    +
    +    This and similar control flow in submodule--helper.c could be made
    +    simpler by properly "libifying" it, i.e. to have it consistently
    +    return -1 on failures, and to early return on any non-success.
    +
    +    But let's leave that larger project for now, and (mostly) emulate what
    +    were doing with the "exit(128)" before this change.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
24:  7551af195ad <  -:  ----------- submodule--helper: free rest of "displaypath" in "struct update_data"
25:  f650716cd7e = 20:  579560cb9a8 submodule--helper: fix bad config API usage
26:  581ce0872c0 <  -:  ----------- submodule--helper: fix a configure_added_submodule() leak
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply	[flat|nested] 142+ messages in thread

* [PATCH 01/20] submodule tests: test usage behavior
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-29 20:30   ` Glen Choo
  2022-07-28 16:16 ` [PATCH 02/20] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
                   ` (21 subsequent siblings)
  22 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Test what exit code and output we emit on "git submodule -h", how we
handle "--" when no subcommand is specified, and how the top-level
"--recursive" option is handled.

For "-h" this doesn't make sense, but let's test for it so that any
subsequent eventual behavior change will become clear.

For "--" this follows up on 68cabbfda36 (submodule: document default
behavior, 2019-02-15) and tests that when "status" isn't supplied we
don't support the "--" delimiter. There's no intrinsically good reason
not to support that. We behave this way due to edge cases in
git-submodule.sh's implementation, but as with "-h" let's assert our
current long-standing behavior for now.

For "--recursive" the exclusion of it from the top-level appears to
have been an omission in 15fc56a8536 (git submodule foreach: Add
--recursive to recurse into nested submodules, 2009-08-19), there
doesn't seem to be a reason not to support it alongside "--quiet" and
"--cached", but let's likewise assert our existing behavior for now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t7400-submodule-basic.sh | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index e7cec2e457a..b858871a953 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -14,6 +14,32 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./test-lib.sh
 
+test_expect_success 'submodule usage: -h' '
+	git submodule -h >out 2>err &&
+	grep "^usage: git submodule" out &&
+	test_must_be_empty err
+'
+
+test_expect_success 'submodule usage: --recursive' '
+	test_expect_code 1 git submodule --recursive >out 2>err &&
+	grep "^usage: git submodule" err &&
+	test_must_be_empty out
+'
+
+test_expect_success 'submodule usage: status --' '
+	test_expect_code 1 git submodule -- &&
+	test_expect_code 1 git submodule --end-of-options
+'
+
+for opt in '--quiet' '--cached'
+do
+	test_expect_success "submodule usage: status $opt" '
+		git submodule $opt &&
+		git submodule status $opt &&
+		git submodule $opt status
+	'
+done
+
 test_expect_success 'submodule deinit works on empty repository' '
 	git submodule deinit --all
 '
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 02/20] submodule tests: test for "add <repository> <abs-path>"
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 01/20] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 03/20] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add a missing test for ""add <repository> <path>" where "<path>" is an
absolute path. This tests code added in [1] and later turned into an
"else" branch in clone_submodule() in [2] that's never been tested.

This needs to be skipped on WINDOWS because all of $PWD, $(pwd) and
the "$(pwd -P)" we get via "$submodurl" would fail in CI with e.g.:

	fatal: could not create directory 'D:/a/git/git/t/trash
	directory.t7400-submodule-basic/.git/modules/D:/a/git/git/t/trash
	directory.t7400-submodule-basic/add-abs'

I.e. we can't handle these sorts of paths in this context on that
platform.

I'm not sure where we run into the edges of "$PWD" behavior on
Windows (see [1] for a previous loose end on the topic), but for the
purposes of this test it's sufficient that we test this on other
platforms.

1. ee8838d1577 (submodule: rewrite `module_clone` shell function in C,
   2015-09-08)
2. f8eaa0ba98b (submodule--helper, module_clone: always operate on
   absolute paths, 2016-03-31)

1. https://lore.kernel.org/git/220630.86edz6c75c.gmgdl@evledraar.gmail.com/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t7400-submodule-basic.sh | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index b858871a953..6a77d817a82 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -178,6 +178,11 @@ test_expect_success 'submodule add' '
 	test_must_be_empty untracked
 '
 
+test_expect_success !WINDOWS 'submodule add (absolute path)' '
+	test_when_finished "git reset --hard" &&
+	git submodule add "$submodurl" "$submodurl/add-abs"
+'
+
 test_expect_success 'setup parent and one repository' '
 	test_create_repo parent &&
 	test_commit -C parent one
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 03/20] submodule--helper: remove unused "name" helper
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 01/20] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 02/20] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 04/20] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The "name" helper has not been used since e83e3333b57 (submodule: port
submodule subcommand 'summary' from shell to C, 2020-08-13).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fac52ade5e1..ac2553ba9d3 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -771,24 +771,6 @@ static int module_status(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static int module_name(int argc, const char **argv, const char *prefix)
-{
-	const struct submodule *sub;
-
-	if (argc != 2)
-		usage(_("git submodule--helper name <path>"));
-
-	sub = submodule_from_path(the_repository, null_oid(), argv[1]);
-
-	if (!sub)
-		die(_("no submodule mapping found in .gitmodules for path '%s'"),
-		    argv[1]);
-
-	printf("%s\n", sub->name);
-
-	return 0;
-}
-
 struct module_cb {
 	unsigned int mod_src;
 	unsigned int mod_dst;
@@ -3359,7 +3341,6 @@ struct cmd_struct {
 
 static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
-	{"name", module_name, 0},
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 04/20] submodule--helper: remove unused "list" helper
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (2 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 03/20] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-29 21:31   ` Glen Choo
  2022-07-28 16:16 ` [PATCH 05/20] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
                   ` (18 subsequent siblings)
  22 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Remove the "submodule--helper list" sub-command, which hasn't been
used by git-submodule.sh since 2964d6e5e1e (submodule: port subcommand
'set-branch' from shell to C, 2020-06-02).

There was a test added in 2b56bb7a87a (submodule helper list: respect
correct path prefix, 2016-02-24) which relied on it, but the right
thing to do here is to delete that test as well.

That test was regression testing the "list" subcommand itself. We're
not getting anything useful from the "list | cut -f2" invocation that
we couldn't get from "foreach 'echo $sm_path'".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 40 -------------------------------------
 t/t7400-submodule-basic.sh  | 25 -----------------------
 2 files changed, 65 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index ac2553ba9d3..47ed24c6a60 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -266,45 +266,6 @@ static char *get_up_path(const char *path)
 	return strbuf_detach(&sb, NULL);
 }
 
-static int module_list(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-
-	struct option module_list_options[] = {
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper list [--prefix=<path>] [<path>...]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_list_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	for (i = 0; i < list.nr; i++) {
-		const struct cache_entry *ce = list.entries[i];
-
-		if (ce_stage(ce))
-			printf("%06o %s U\t", ce->ce_mode,
-			       oid_to_hex(null_oid()));
-		else
-			printf("%06o %s %d\t", ce->ce_mode,
-			       oid_to_hex(&ce->oid), ce_stage(ce));
-
-		fprintf(stdout, "%s\n", ce->name);
-	}
-	return 0;
-}
-
 static void for_each_listed_submodule(const struct module_list *list,
 				      each_submodule_fn fn, void *cb_data)
 {
@@ -3340,7 +3301,6 @@ struct cmd_struct {
 };
 
 static struct cmd_struct commands[] = {
-	{"list", module_list, 0},
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 6a77d817a82..b50db3f1031 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -1255,31 +1255,6 @@ test_expect_success 'submodule add clone shallow submodule' '
 	)
 '
 
-test_expect_success 'submodule helper list is not confused by common prefixes' '
-	mkdir -p dir1/b &&
-	(
-		cd dir1/b &&
-		git init &&
-		echo hi >testfile2 &&
-		git add . &&
-		git commit -m "test1"
-	) &&
-	mkdir -p dir2/b &&
-	(
-		cd dir2/b &&
-		git init &&
-		echo hello >testfile1 &&
-		git add .  &&
-		git commit -m "test2"
-	) &&
-	git submodule add /dir1/b dir1/b &&
-	git submodule add /dir2/b dir2/b &&
-	git commit -m "first submodule commit" &&
-	git submodule--helper list dir1/b | cut -f 2 >actual &&
-	echo "dir1/b" >expect &&
-	test_cmp expect actual
-'
-
 test_expect_success 'setup superproject with submodules' '
 	git init sub1 &&
 	test_commit -C sub1 test &&
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 05/20] test-tool submodule-config: remove unused "--url" handling
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (3 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 04/20] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 06/20] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

No test has used this "--url" parameter since the test code that made
use of it was removed in 32bc548329d (submodule-config: remove support
for overlaying repository config, 2017-08-03).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/helper/test-submodule-config.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index e2692746dfd..22a41c40926 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -15,14 +15,11 @@ int cmd__submodule_config(int argc, const char **argv)
 {
 	const char **arg = argv;
 	int my_argc = argc;
-	int output_url = 0;
 	int lookup_name = 0;
 
 	arg++;
 	my_argc--;
 	while (arg[0] && starts_with(arg[0], "--")) {
-		if (!strcmp(arg[0], "--url"))
-			output_url = 1;
 		if (!strcmp(arg[0], "--name"))
 			lookup_name = 1;
 		arg++;
@@ -57,12 +54,8 @@ int cmd__submodule_config(int argc, const char **argv)
 		if (!submodule)
 			die_usage(argc, argv, "Submodule not found.");
 
-		if (output_url)
-			printf("Submodule url: '%s' for path '%s'\n",
-					submodule->url, submodule->path);
-		else
-			printf("Submodule name: '%s' for path '%s'\n",
-					submodule->name, submodule->path);
+		printf("Submodule name: '%s' for path '%s'\n", submodule->name,
+		       submodule->path);
 
 		arg += 2;
 	}
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 06/20] submodule--helper: move "is-active" to a test-tool
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (4 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 05/20] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-29 21:45   ` Glen Choo
  2022-07-28 16:16 ` [PATCH 07/20] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Create a new "test-tool submodule" and move the "is-active" subcommand
over to it. It was added in 5c2bd8b77ae (submodule--helper: add
is-active subcommand, 2017-03-16), since
a452128a36c (submodule--helper: introduce add-config subcommand,
2021-08-06) it hasn't been used by git-submodule.sh.

Since we're creating a command dispatch similar to test-tool.c itself
let's split out the "struct test_cmd" into a new test-tool-utils.h,
which both this new code and test-tool.c itself can use.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Makefile                       |  1 +
 builtin/submodule--helper.c    |  9 ------
 t/helper/test-submodule.c      | 58 ++++++++++++++++++++++++++++++++++
 t/helper/test-tool-utils.h     |  9 ++++++
 t/helper/test-tool.c           |  7 ++--
 t/helper/test-tool.h           |  1 +
 t/t7413-submodule-is-active.sh | 32 +++++++++----------
 7 files changed, 87 insertions(+), 30 deletions(-)
 create mode 100644 t/helper/test-submodule.c
 create mode 100644 t/helper/test-tool-utils.h

diff --git a/Makefile b/Makefile
index 1624471badc..ad7fbd36885 100644
--- a/Makefile
+++ b/Makefile
@@ -785,6 +785,7 @@ TEST_BUILTINS_OBJS += test-strcmp-offset.o
 TEST_BUILTINS_OBJS += test-string-list.o
 TEST_BUILTINS_OBJS += test-submodule-config.o
 TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
+TEST_BUILTINS_OBJS += test-submodule.o
 TEST_BUILTINS_OBJS += test-subprocess.o
 TEST_BUILTINS_OBJS += test-trace2.o
 TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 47ed24c6a60..b2fc732b5d8 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2728,14 +2728,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static int is_active(int argc, const char **argv, const char *prefix)
-{
-	if (argc != 2)
-		die("submodule--helper is-active takes exactly 1 argument");
-
-	return !is_submodule_active(the_repository, argv[1]);
-}
-
 /*
  * Exit non-zero if any of the submodule names given on the command line is
  * invalid. If no names are given, filter stdin to print only valid names
@@ -3313,7 +3305,6 @@ static struct cmd_struct commands[] = {
 	{"summary", module_summary, 0},
 	{"push-check", push_check, 0},
 	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
-	{"is-active", is_active, 0},
 	{"check-name", check_name, 0},
 	{"config", module_config, 0},
 	{"set-url", module_set_url, 0},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
new file mode 100644
index 00000000000..494c6558d9f
--- /dev/null
+++ b/t/helper/test-submodule.c
@@ -0,0 +1,58 @@
+#include "test-tool.h"
+#include "test-tool-utils.h"
+#include "cache.h"
+#include "parse-options.h"
+#include "submodule.h"
+
+#define TEST_TOOL_IS_ACTIVE_USAGE \
+	"test-tool submodule is-active <name>"
+static const char *submodule_is_active_usage[] = {
+	TEST_TOOL_IS_ACTIVE_USAGE,
+	NULL
+};
+
+static const char *submodule_usage[] = {
+	TEST_TOOL_IS_ACTIVE_USAGE,
+	NULL
+};
+
+static int cmd__submodule_is_active(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_is_active_usage, 0);
+	if (argc != 1)
+		usage_with_options(submodule_is_active_usage, options);
+
+	setup_git_directory();
+
+	return !is_submodule_active(the_repository, argv[0]);
+}
+
+static struct test_cmd cmds[] = {
+	{ "is-active", cmd__submodule_is_active },
+};
+
+int cmd__submodule(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	size_t i;
+
+	argc = parse_options(argc, argv, "test-tools", options, submodule_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (argc < 1)
+		usage_with_options(submodule_usage, options);
+
+	for (i = 0; i < ARRAY_SIZE(cmds); i++)
+		if (!strcmp(cmds[i].name, argv[0]))
+			return cmds[i].fn(argc, argv);
+
+	usage_msg_optf("unknown subcommand '%s'", submodule_usage, options,
+		       argv[0]);
+
+	return 0;
+}
diff --git a/t/helper/test-tool-utils.h b/t/helper/test-tool-utils.h
new file mode 100644
index 00000000000..6a0e5e0074f
--- /dev/null
+++ b/t/helper/test-tool-utils.h
@@ -0,0 +1,9 @@
+#ifndef TEST_TOOL_UTILS_H
+#define TEST_TOOL_UTILS_H
+
+struct test_cmd {
+	const char *name;
+	int (*fn)(int argc, const char **argv);
+};
+
+#endif
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 318fdbab0c3..7a6a8b88a91 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "test-tool.h"
+#include "test-tool-utils.h"
 #include "trace2.h"
 #include "parse-options.h"
 
@@ -8,11 +9,6 @@ static const char * const test_tool_usage[] = {
 	NULL
 };
 
-struct test_cmd {
-	const char *name;
-	int (*fn)(int argc, const char **argv);
-};
-
 static struct test_cmd cmds[] = {
 	{ "advise", cmd__advise_if_enabled },
 	{ "bitmap", cmd__bitmap },
@@ -78,6 +74,7 @@ static struct test_cmd cmds[] = {
 	{ "simple-ipc", cmd__simple_ipc },
 	{ "strcmp-offset", cmd__strcmp_offset },
 	{ "string-list", cmd__string_list },
+	{ "submodule", cmd__submodule },
 	{ "submodule-config", cmd__submodule_config },
 	{ "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
 	{ "subprocess", cmd__subprocess },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index bb799271631..5f4f69dee81 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -68,6 +68,7 @@ int cmd__sigchain(int argc, const char **argv);
 int cmd__simple_ipc(int argc, const char **argv);
 int cmd__strcmp_offset(int argc, const char **argv);
 int cmd__string_list(int argc, const char **argv);
+int cmd__submodule(int argc, const char **argv);
 int cmd__submodule_config(int argc, const char **argv);
 int cmd__submodule_nested_repo_config(int argc, const char **argv);
 int cmd__subprocess(int argc, const char **argv);
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index c8e7e983317..9ead083371a 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -1,8 +1,8 @@
 #!/bin/sh
 
-test_description='Test submodule--helper is-active
+test_description='Test with test-tool submodule is-active
 
-This test verifies that `git submodue--helper is-active` correctly identifies
+This test verifies that `test-tool submodule is-active` correctly identifies
 submodules which are "active" and interesting to the user.
 '
 
@@ -25,13 +25,13 @@ test_expect_success 'setup' '
 '
 
 test_expect_success 'is-active works with urls' '
-	git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2 &&
+	test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2 &&
 
 	git -C super config --unset submodule.sub1.URL &&
-	test_must_fail git -C super submodule--helper is-active sub1 &&
+	test_must_fail test-tool -C super submodule is-active sub1 &&
 	git -C super config submodule.sub1.URL ../sub &&
-	git -C super submodule--helper is-active sub1
+	test-tool -C super submodule is-active sub1
 '
 
 test_expect_success 'is-active works with submodule.<name>.active config' '
@@ -39,11 +39,11 @@ test_expect_success 'is-active works with submodule.<name>.active config' '
 	test_when_finished "git -C super config submodule.sub1.URL ../sub" &&
 
 	git -C super config --bool submodule.sub1.active "false" &&
-	test_must_fail git -C super submodule--helper is-active sub1 &&
+	test_must_fail test-tool -C super submodule is-active sub1 &&
 
 	git -C super config --bool submodule.sub1.active "true" &&
 	git -C super config --unset submodule.sub1.URL &&
-	git -C super submodule--helper is-active sub1
+	test-tool -C super submodule is-active sub1
 '
 
 test_expect_success 'is-active works with basic submodule.active config' '
@@ -53,17 +53,17 @@ test_expect_success 'is-active works with basic submodule.active config' '
 	git -C super config --add submodule.active "." &&
 	git -C super config --unset submodule.sub1.URL &&
 
-	git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active correctly works with paths that are not submodules' '
 	test_when_finished "git -C super config --unset-all submodule.active" &&
 
-	test_must_fail git -C super submodule--helper is-active not-a-submodule &&
+	test_must_fail test-tool -C super submodule is-active not-a-submodule &&
 
 	git -C super config --add submodule.active "." &&
-	test_must_fail git -C super submodule--helper is-active not-a-submodule
+	test_must_fail test-tool -C super submodule is-active not-a-submodule
 '
 
 test_expect_success 'is-active works with exclusions in submodule.active config' '
@@ -72,8 +72,8 @@ test_expect_success 'is-active works with exclusions in submodule.active config'
 	git -C super config --add submodule.active "." &&
 	git -C super config --add submodule.active ":(exclude)sub1" &&
 
-	test_must_fail git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test_must_fail test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active with submodule.active and submodule.<name>.active' '
@@ -85,8 +85,8 @@ test_expect_success 'is-active with submodule.active and submodule.<name>.active
 	git -C super config --bool submodule.sub1.active "false" &&
 	git -C super config --bool submodule.sub2.active "true" &&
 
-	test_must_fail git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test_must_fail test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active, submodule.active and submodule add' '
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 07/20] submodule--helper: move "check-name" to a test-tool
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (5 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 06/20] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-29 21:55   ` Glen Choo
  2022-07-28 16:16 ` [PATCH 08/20] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Move the "check-name" helper to a test-tool, since
a6226fd772b (submodule--helper: convert the bulk of cmd_add() to C,
2021-08-10) it has only been used by this test, not git-submodule.sh.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 24 -------------------
 t/helper/test-submodule.c   | 46 +++++++++++++++++++++++++++++++++++++
 t/t7450-bad-git-dotfiles.sh |  2 +-
 3 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b2fc732b5d8..06307886080 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2728,29 +2728,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-/*
- * Exit non-zero if any of the submodule names given on the command line is
- * invalid. If no names are given, filter stdin to print only valid names
- * (which is primarily intended for testing).
- */
-static int check_name(int argc, const char **argv, const char *prefix)
-{
-	if (argc > 1) {
-		while (*++argv) {
-			if (check_submodule_name(*argv) < 0)
-				return 1;
-		}
-	} else {
-		struct strbuf buf = STRBUF_INIT;
-		while (strbuf_getline(&buf, stdin) != EOF) {
-			if (!check_submodule_name(buf.buf))
-				printf("%s\n", buf.buf);
-		}
-		strbuf_release(&buf);
-	}
-	return 0;
-}
-
 static int module_config(int argc, const char **argv, const char *prefix)
 {
 	enum {
@@ -3305,7 +3282,6 @@ static struct cmd_struct commands[] = {
 	{"summary", module_summary, 0},
 	{"push-check", push_check, 0},
 	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
-	{"check-name", check_name, 0},
 	{"config", module_config, 0},
 	{"set-url", module_set_url, 0},
 	{"set-branch", module_set_branch, 0},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 494c6558d9f..9f0eb440192 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -2,8 +2,16 @@
 #include "test-tool-utils.h"
 #include "cache.h"
 #include "parse-options.h"
+#include "submodule-config.h"
 #include "submodule.h"
 
+#define TEST_TOOL_CHECK_NAME_USAGE \
+	"test-tool submodule check-name <name>"
+static const char *submodule_check_name_usage[] = {
+	TEST_TOOL_CHECK_NAME_USAGE,
+	NULL
+};
+
 #define TEST_TOOL_IS_ACTIVE_USAGE \
 	"test-tool submodule is-active <name>"
 static const char *submodule_is_active_usage[] = {
@@ -12,10 +20,47 @@ static const char *submodule_is_active_usage[] = {
 };
 
 static const char *submodule_usage[] = {
+	TEST_TOOL_CHECK_NAME_USAGE,
 	TEST_TOOL_IS_ACTIVE_USAGE,
 	NULL
 };
 
+/*
+ * Exit non-zero if any of the submodule names given on the command line is
+ * invalid. If no names are given, filter stdin to print only valid names
+ * (which is primarily intended for testing).
+ */
+static int check_name(int argc, const char **argv)
+{
+	if (argc > 1) {
+		while (*++argv) {
+			if (check_submodule_name(*argv) < 0)
+				return 1;
+		}
+	} else {
+		struct strbuf buf = STRBUF_INIT;
+		while (strbuf_getline(&buf, stdin) != EOF) {
+			if (!check_submodule_name(buf.buf))
+				printf("%s\n", buf.buf);
+		}
+		strbuf_release(&buf);
+	}
+	return 0;
+}
+
+static int cmd__submodule_check_name(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_check_name_usage, 0);
+	if (argc)
+		usage_with_options(submodule_check_name_usage, options);
+
+	return check_name(argc, argv);
+}
+
 static int cmd__submodule_is_active(int argc, const char **argv)
 {
 	struct option options[] = {
@@ -32,6 +77,7 @@ static int cmd__submodule_is_active(int argc, const char **argv)
 }
 
 static struct test_cmd cmds[] = {
+	{ "check-name", cmd__submodule_check_name },
 	{ "is-active", cmd__submodule_is_active },
 };
 
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index 41706c1c9ff..2c24f120da3 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -21,7 +21,7 @@ test_expect_success 'check names' '
 	valid/with/paths
 	EOF
 
-	git submodule--helper check-name >actual <<-\EOF &&
+	test-tool submodule check-name >actual <<-\EOF &&
 	valid
 	valid/with/paths
 
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 08/20] submodule--helper: move "resolve-relative-url-test" to a test-tool
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (6 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 07/20] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-29 21:58   ` Glen Choo
  2022-07-28 16:16 ` [PATCH 09/20] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
                   ` (14 subsequent siblings)
  22 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

As its name suggests the "resolve-relative-url-test" has never been
used outside of the test suite, see 63e95beb085 (submodule: port
resolve_relative_url from shell to C, 2016-04-15) for its original
addition.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 23 --------------------
 t/helper/test-submodule.c   | 42 +++++++++++++++++++++++++++++++++++++
 t/t0060-path-utils.sh       |  2 +-
 3 files changed, 43 insertions(+), 24 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 06307886080..246457ec2e9 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -96,28 +96,6 @@ static char *resolve_relative_url(const char *rel_url, const char *up_path, int
 	return resolved_url;
 }
 
-static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
-{
-	char *remoteurl, *res;
-	const char *up_path, *url;
-
-	if (argc != 4)
-		die("resolve-relative-url-test only accepts three arguments: <up_path> <remoteurl> <url>");
-
-	up_path = argv[1];
-	remoteurl = xstrdup(argv[2]);
-	url = argv[3];
-
-	if (!strcmp(up_path, "(null)"))
-		up_path = NULL;
-
-	res = relative_url(remoteurl, url, up_path);
-	puts(res);
-	free(res);
-	free(remoteurl);
-	return 0;
-}
-
 /* the result should be freed by the caller. */
 static char *get_submodule_displaypath(const char *path, const char *prefix)
 {
@@ -3273,7 +3251,6 @@ static struct cmd_struct commands[] = {
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
-	{"resolve-relative-url-test", resolve_relative_url_test, 0},
 	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
 	{"init", module_init, 0},
 	{"status", module_status, SUPPORT_SUPER_PREFIX},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 9f0eb440192..e0e0c53d386 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -2,6 +2,7 @@
 #include "test-tool-utils.h"
 #include "cache.h"
 #include "parse-options.h"
+#include "remote.h"
 #include "submodule-config.h"
 #include "submodule.h"
 
@@ -19,9 +20,17 @@ static const char *submodule_is_active_usage[] = {
 	NULL
 };
 
+#define TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE \
+	"test-tool submodule resolve-relative-url <up_path> <remoteurl> <url>"
+static const char *submodule_resolve_relative_url_usage[] = {
+	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
+	NULL,
+};
+
 static const char *submodule_usage[] = {
 	TEST_TOOL_CHECK_NAME_USAGE,
 	TEST_TOOL_IS_ACTIVE_USAGE,
+	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
 	NULL
 };
 
@@ -76,9 +85,42 @@ static int cmd__submodule_is_active(int argc, const char **argv)
 	return !is_submodule_active(the_repository, argv[0]);
 }
 
+static int resolve_relative_url(int argc, const char **argv)
+{
+	char *remoteurl, *res;
+	const char *up_path, *url;
+
+	up_path = argv[0];
+	remoteurl = xstrdup(argv[1]);
+	url = argv[2];
+
+	if (!strcmp(up_path, "(null)"))
+		up_path = NULL;
+
+	res = relative_url(remoteurl, url, up_path);
+	puts(res);
+	free(res);
+	free(remoteurl);
+	return 0;
+}
+
+static int cmd__submodule_resolve_relative_url(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_resolve_relative_url_usage, 0);
+	if (argc != 3)
+		usage_with_options(submodule_resolve_relative_url_usage, options);
+
+	return resolve_relative_url(argc, argv);
+}
+
 static struct test_cmd cmds[] = {
 	{ "check-name", cmd__submodule_check_name },
 	{ "is-active", cmd__submodule_is_active },
+	{ "resolve-relative-url", cmd__submodule_resolve_relative_url},
 };
 
 int cmd__submodule(int argc, const char **argv)
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 1f2007e62b7..68e29c904a6 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -22,7 +22,7 @@ relative_path() {
 
 test_submodule_relative_url() {
 	test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" "
-		actual=\$(git submodule--helper resolve-relative-url-test '$1' '$2' '$3') &&
+		actual=\$(test-tool submodule resolve-relative-url '$1' '$2' '$3') &&
 		test \"\$actual\" = '$4'
 	"
 }
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 09/20] submodule--helper style: don't separate declared variables with \n\n
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (7 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 08/20] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 10/20] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The usual style in the codebase is to separate declared variables with
a single newline, not two, let's adjust this code to conform to
that. This makes the eventual addition of various "int ret" variables
more consistent.

In doing this the comment added in 2964d6e5e1e (submodule: port
subcommand 'set-branch' from shell to C, 2020-06-02) might become
ambiguous to some, although it should be clear what it's referring to,
let's move it above the 'OPT_NOOP_NOARG('q', "quiet")' to make that
clearer.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 33 +++++----------------------------
 1 file changed, 5 insertions(+), 28 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 246457ec2e9..53b9e14767d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -368,14 +368,12 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	struct foreach_cb info = FOREACH_CB_INIT;
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
-
 	struct option module_foreach_options[] = {
 		OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
 		OPT_BOOL(0, "recursive", &info.recursive,
 			 N_("recurse into nested submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
 		NULL
@@ -504,12 +502,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
-
 	struct option module_init_options[] = {
 		OPT__QUIET(&quiet, N_("suppress output for initializing a submodule")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule init [<options>] [<path>]"),
 		NULL
@@ -682,14 +678,12 @@ static int module_status(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
-
 	struct option module_status_options[] = {
 		OPT__QUIET(&quiet, N_("suppress submodule status output")),
 		OPT_BIT(0, "cached", &info.flags, N_("use commit stored in the index instead of the one stored in the submodule HEAD"), OPT_CACHED),
 		OPT_BIT(0, "recursive", &info.flags, N_("recurse into nested submodules"), OPT_RECURSIVE),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
 		NULL
@@ -1082,7 +1076,6 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 	enum diff_cmd diff_cmd = DIFF_INDEX;
 	struct object_id head_oid;
 	int ret;
-
 	struct option module_summary_options[] = {
 		OPT_BOOL(0, "cached", &cached,
 			 N_("use the commit stored in the index instead of the submodule HEAD")),
@@ -1094,7 +1087,6 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 			     N_("limit the summary size")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule summary [<options>] [<commit>] [--] [<path>]"),
 		NULL
@@ -1251,14 +1243,12 @@ static int module_sync(int argc, const char **argv, const char *prefix)
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
 	int recursive = 0;
-
 	struct option module_sync_options[] = {
 		OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
 		OPT_BOOL(0, "recursive", &recursive,
 			N_("recurse into nested submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule sync [--quiet] [--recursive] [<path>]"),
 		NULL
@@ -1390,14 +1380,12 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
 	int quiet = 0;
 	int force = 0;
 	int all = 0;
-
 	struct option module_deinit_options[] = {
 		OPT__QUIET(&quiet, N_("suppress submodule status output")),
 		OPT__FORCE(&force, N_("remove submodule working trees even if they contain local changes"), 0),
 		OPT_BOOL(0, "all", &all, N_("unregister all submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
 		NULL
@@ -1666,7 +1654,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
 	struct list_objects_filter_options filter_options;
-
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1698,7 +1685,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule--helper clone [--prefix=<path>] [--quiet] "
 		   "[--reference <repository>] [--name <name>] [--depth <depth>] "
@@ -2486,7 +2472,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 	struct update_data opt = UPDATE_DATA_INIT;
 	struct list_objects_filter_options filter_options;
 	int ret;
-
 	struct option module_update_options[] = {
 		OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
 		OPT_BOOL(0, "init", &opt.init,
@@ -2530,7 +2515,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule [--quiet] update"
 		" [--init [--filter=<filter-spec>]] [--remote]"
@@ -2679,7 +2663,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
-
 	struct option embed_gitdir_options[] = {
 		OPT_STRING(0, "prefix", &prefix,
 			   N_("path"),
@@ -2688,7 +2671,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 			ABSORB_GITDIR_RECURSE_SUBMODULES),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule absorbgitdirs [<options>] [<path>...]"),
 		NULL
@@ -2712,7 +2694,6 @@ static int module_config(int argc, const char **argv, const char *prefix)
 		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"),
@@ -2758,7 +2739,6 @@ static int module_set_url(int argc, const char **argv, const char *prefix)
 	const char *newurl;
 	const char *path;
 	char *config_name;
-
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("suppress output for setting url of a submodule")),
 		OPT_END()
@@ -2789,13 +2769,13 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
 	const char *opt_branch = NULL;
 	const char *path;
 	char *config_name;
-
-	/*
-	 * We accept the `quiet` option for uniformity across subcommands,
-	 * though there is nothing to make less verbose in this subcommand.
-	 */
 	struct option options[] = {
+		/*
+		 * We accept the `quiet` option for uniformity across subcommands,
+		 * though there is nothing to make less verbose in this subcommand.
+		 */
 		OPT_NOOP_NOARG('q', "quiet"),
+
 		OPT_BOOL('d', "default", &opt_default,
 			N_("set the default tracking branch to master")),
 		OPT_STRING('b', "branch", &opt_branch, N_("branch"),
@@ -2830,7 +2810,6 @@ static int module_create_branch(int argc, const char **argv, const char *prefix)
 {
 	enum branch_track track;
 	int quiet = 0, force = 0, reflog = 0, dry_run = 0;
-
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("print only error messages")),
 		OPT__FORCE(&force, N_("force creation"), 0),
@@ -3129,7 +3108,6 @@ static int module_add(int argc, const char **argv, const char *prefix)
 	int force = 0, quiet = 0, progress = 0, dissociate = 0;
 	struct add_data add_data = ADD_DATA_INIT;
 	char *to_free = NULL;
-
 	struct option options[] = {
 		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
 			   N_("branch of repository to add as submodule")),
@@ -3146,7 +3124,6 @@ static int module_add(int argc, const char **argv, const char *prefix)
 		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
 		OPT_END()
 	};
-
 	const char *const usage[] = {
 		N_("git submodule add [<options>] [--] <repository> [<path>]"),
 		NULL
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 10/20] submodule--helper style: add \n\n after variable declarations
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (8 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 09/20] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 11/20] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Since the preceding commit fixed style issues with \n\n among the
declared variables let's fix the minor stylistic issues with those
variables not being consistently followed by a \n\n.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 53b9e14767d..15bf89910f4 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -167,6 +167,7 @@ static int module_list_compute(int argc, const char **argv,
 {
 	int i, result = 0;
 	char *ps_matched = NULL;
+
 	parse_pathspec(pathspec, 0,
 		       PATHSPEC_PREFER_FULL,
 		       prefix, argv);
@@ -248,6 +249,7 @@ static void for_each_listed_submodule(const struct module_list *list,
 				      each_submodule_fn fn, void *cb_data)
 {
 	int i;
+
 	for (i = 0; i < list->nr; i++)
 		fn(list->entries[i], cb_data);
 }
@@ -267,7 +269,6 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
 	struct foreach_cb *info = cb_data;
 	const char *path = list_item->name;
 	const struct object_id *ce_oid = &list_item->oid;
-
 	const struct submodule *sub;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *displaypath;
@@ -456,6 +457,7 @@ static void init_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(url) ||
 		    starts_with_dot_slash(url)) {
 			char *oldurl = url;
+
 			url = resolve_relative_url(oldurl, NULL, 0);
 			free(oldurl);
 		}
@@ -493,6 +495,7 @@ static void init_submodule(const char *path, const char *prefix,
 static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
 {
 	struct init_cb *info = cb_data;
+
 	init_submodule(list_item->name, info->prefix, info->flags);
 }
 
@@ -562,6 +565,7 @@ static int handle_submodule_head_ref(const char *refname,
 				     void *cb_data)
 {
 	struct object_id *output = cb_data;
+
 	if (oid)
 		oidcpy(output, oid);
 
@@ -668,6 +672,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
 				void *cb_data)
 {
 	struct status_cb *info = cb_data;
+
 	status_submodule(list_item->name, &list_item->oid, list_item->ce_flags,
 			 info->prefix, info->flags);
 }
@@ -820,6 +825,7 @@ static void generate_submodule_summary(struct summary_cb *info,
 	if (!info->cached && oideq(&p->oid_dst, null_oid())) {
 		if (S_ISGITLINK(p->mod_dst)) {
 			struct ref_store *refs = get_submodule_ref_store(p->sm_path);
+
 			if (refs)
 				refs_head_ref(refs, handle_submodule_head_ref, &p->oid_dst);
 		} else if (S_ISLNK(p->mod_dst) || S_ISREG(p->mod_dst)) {
@@ -1158,6 +1164,7 @@ static void sync_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
 			char *up_path = get_up_path(path);
+
 			sub_origin_url = resolve_relative_url(sub->url, up_path, 1);
 			super_config_url = resolve_relative_url(sub->url, NULL, 1);
 			free(up_path);
@@ -1233,6 +1240,7 @@ static void sync_submodule(const char *path, const char *prefix,
 static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data)
 {
 	struct sync_cb *info = cb_data;
+
 	sync_submodule(list_item->name, info->prefix, info->flags);
 }
 
@@ -1312,6 +1320,7 @@ static void deinit_submodule(const char *path, const char *prefix,
 
 		if (!(flags & OPT_FORCE)) {
 			struct child_process cp_rm = CHILD_PROCESS_INIT;
+
 			cp_rm.git_cmd = 1;
 			strvec_pushl(&cp_rm.args, "rm", "-qn",
 				     path, NULL);
@@ -1348,6 +1357,7 @@ static void deinit_submodule(const char *path, const char *prefix,
 	/* remove the .git/config entries (unless the user already did it) */
 	if (!capture_command(&cp_config, &sb_config, 0) && sb_config.len) {
 		char *sub_key = xstrfmt("submodule.%s", sub->name);
+
 		/*
 		 * remove the whole section so we have a clean state when
 		 * the user later decides to init this submodule again
@@ -1585,6 +1595,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
 		if (clone_data->reference.nr) {
 			struct string_list_item *item;
+
 			for_each_string_list_item(item, &clone_data->reference)
 				strvec_pushl(&cp.args, "--reference",
 					     item->string, NULL);
@@ -1935,6 +1946,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	strvec_pushl(&child->args, "--url", url, NULL);
 	if (suc->update_data->references.nr) {
 		struct string_list_item *item;
+
 		for_each_string_list_item(item, &suc->update_data->references)
 			strvec_pushl(&child->args, "--reference", item->string, NULL);
 	}
@@ -1967,6 +1979,7 @@ static int update_clone_get_next_task(struct child_process *child,
 		ce = suc->update_data->list.entries[suc->current];
 		if (prepare_to_clone_next_submodule(ce, child, suc, err)) {
 			int *p = xmalloc(sizeof(*p));
+
 			*p = suc->current;
 			*idx_task_cb = p;
 			suc->current++;
@@ -1982,6 +1995,7 @@ static int update_clone_get_next_task(struct child_process *child,
 	index = suc->current - suc->update_data->list.nr;
 	if (index < suc->failed_clones_nr) {
 		int *p;
+
 		ce = suc->failed_clones[index];
 		if (!prepare_to_clone_next_submodule(ce, child, suc, err)) {
 			suc->current ++;
@@ -2005,6 +2019,7 @@ static int update_clone_start_failure(struct strbuf *err,
 				      void *idx_task_cb)
 {
 	struct submodule_update_clone *suc = suc_cb;
+
 	suc->quickstop = 1;
 	return 1;
 }
@@ -2016,9 +2031,9 @@ static int update_clone_task_finished(int result,
 {
 	const struct cache_entry *ce;
 	struct submodule_update_clone *suc = suc_cb;
-
 	int *idxP = idx_task_cb;
 	int idx = *idxP;
+
 	free(idxP);
 
 	if (!result)
@@ -2051,6 +2066,7 @@ static int git_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;
@@ -2091,6 +2107,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	if (oid) {
 		char *hex = oid_to_hex(oid);
 		char *remote = get_default_remote();
+
 		strvec_pushl(&cp.args, remote, hex, NULL);
 		free(remote);
 	}
@@ -2340,6 +2357,7 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 
 	if (update_data->references.nr) {
 		struct string_list_item *item;
+
 		for_each_string_list_item(item, &update_data->references)
 			strvec_pushl(args, "--reference", item->string, NULL);
 	}
@@ -2872,8 +2890,10 @@ static void append_fetch_remotes(struct strbuf *msg, const char *git_dir_path)
 	if (!capture_command(&cp_remote, &sb_remote_out, 0)) {
 		char *next_line;
 		char *line = sb_remote_out.buf;
+
 		while ((next_line = strchr(line, '\n')) != NULL) {
 			size_t len = next_line - line;
+
 			if (strip_suffix_mem(line, &len, " (fetch)"))
 				strbuf_addf(msg, "  %.*s\n", (int)len, line);
 			line = next_line + 1;
@@ -3180,6 +3200,7 @@ static int module_add(int argc, const char **argv, const char *prefix)
 		int exit_code = -1;
 		struct strbuf sb = STRBUF_INIT;
 		struct child_process cp = CHILD_PROCESS_INIT;
+
 		cp.git_cmd = 1;
 		cp.no_stdout = 1;
 		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 11/20] submodule--helper: replace memset() with { 0 }-initialization
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (9 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 10/20] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 12/20] submodule--helper: convert a strbuf_detach() to xstrfmt() Ævar Arnfjörð Bjarmason
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Use the less verbose { 0 }-initialization syntax rather than memset()
in builtin/submodule--helper.c, this doesn't make a difference in
terms of behavior, but as we're about to modify adjacent code makes
this more consistent, and lets us avoid worrying about when the
memset() happens v.s. a "goto cleanup".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 15bf89910f4..60165a848a2 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1664,7 +1664,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 {
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
-	struct list_objects_filter_options filter_options;
+	struct list_objects_filter_options filter_options = { 0 };
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1704,7 +1704,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		NULL
 	};
 
-	memset(&filter_options, 0, sizeof(filter_options));
 	argc = parse_options(argc, argv, prefix, module_clone_options,
 			     git_submodule_helper_usage, 0);
 
@@ -2488,7 +2487,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
 {
 	struct pathspec pathspec;
 	struct update_data opt = UPDATE_DATA_INIT;
-	struct list_objects_filter_options filter_options;
+	struct list_objects_filter_options filter_options = { 0 };
 	int ret;
 	struct option module_update_options[] = {
 		OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
@@ -2546,7 +2545,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 	update_clone_config_from_gitmodules(&opt.max_jobs);
 	git_config(git_update_clone_config, &opt.max_jobs);
 
-	memset(&filter_options, 0, sizeof(filter_options));
 	argc = parse_options(argc, argv, prefix, module_update_options,
 			     git_submodule_helper_usage, 0);
 
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 12/20] submodule--helper: convert a strbuf_detach() to xstrfmt()
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (10 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 11/20] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:16 ` [PATCH 13/20] submodule--helper: stop conflating "sb" in clone_submodule() Ævar Arnfjörð Bjarmason
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Convert a case where we had no reason to use a "struct strbuf" to use
an xstrfmt(). This code was added along with other uses of "struct
strbuf" in this function in ee8838d1577 (submodule: rewrite
`module_clone` shell function in C, 2015-09-08).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 60165a848a2..f74957444e1 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1568,12 +1568,11 @@ static int clone_submodule(struct module_clone_data *clone_data)
 	sm_gitdir = absolute_pathdup(sb.buf);
 	strbuf_reset(&sb);
 
-	if (!is_absolute_path(clone_data->path)) {
-		strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
-		clone_data->path = strbuf_detach(&sb, NULL);
-	} else {
+	if (!is_absolute_path(clone_data->path))
+		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
+					   clone_data->path);
+	else
 		clone_data->path = xstrdup(clone_data->path);
-	}
 
 	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
 		die(_("refusing to create/use '%s' in another submodule's "
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 13/20] submodule--helper: stop conflating "sb" in clone_submodule()
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (11 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 12/20] submodule--helper: convert a strbuf_detach() to xstrfmt() Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-29 17:08   ` Glen Choo
  2022-07-28 16:16 ` [PATCH 14/20] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Refactor the two uses of a "struct strbuf sb" such that each of them
exists in its own scope. This makes the control flow clearer.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f74957444e1..6cedcc5b239 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1557,16 +1557,24 @@ static void prepare_possible_alternates(const char *sm_name,
 	free(error_strategy);
 }
 
-static int clone_submodule(struct module_clone_data *clone_data)
+static char *clone_submodule_sm_gitdir(const char *name)
 {
-	char *p, *sm_gitdir;
-	char *sm_alternate = NULL, *error_strategy = NULL;
 	struct strbuf sb = STRBUF_INIT;
-	struct child_process cp = CHILD_PROCESS_INIT;
+	char *sm_gitdir;
 
-	submodule_name_to_gitdir(&sb, the_repository, clone_data->name);
+	submodule_name_to_gitdir(&sb, the_repository, name);
 	sm_gitdir = absolute_pathdup(sb.buf);
-	strbuf_reset(&sb);
+	strbuf_release(&sb);
+
+	return sm_gitdir;
+}
+
+static int clone_submodule(struct module_clone_data *clone_data)
+{
+	char *p;
+	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
+	char *sm_alternate = NULL, *error_strategy = NULL;
+	struct child_process cp = CHILD_PROCESS_INIT;
 
 	if (!is_absolute_path(clone_data->path))
 		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
@@ -1624,6 +1632,8 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			die(_("clone of '%s' into submodule path '%s' failed"),
 			    clone_data->url, clone_data->path);
 	} else {
+		struct strbuf sb = STRBUF_INIT;
+
 		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
 		    !is_empty_dir(clone_data->path))
 			die(_("directory not empty: '%s'"), clone_data->path);
@@ -1631,7 +1641,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			die(_("could not create directory '%s'"), clone_data->path);
 		strbuf_addf(&sb, "%s/index", sm_gitdir);
 		unlink_or_warn(sb.buf);
-		strbuf_reset(&sb);
+		strbuf_release(&sb);
 	}
 
 	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
@@ -1653,7 +1663,6 @@ static int clone_submodule(struct module_clone_data *clone_data)
 	free(sm_alternate);
 	free(error_strategy);
 
-	strbuf_release(&sb);
 	free(sm_gitdir);
 	free(p);
 	return 0;
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 14/20] submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (12 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 13/20] submodule--helper: stop conflating "sb" in clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:16 ` Ævar Arnfjörð Bjarmason
  2022-07-29 22:09   ` Glen Choo
  2022-07-28 16:17 ` [PATCH 15/20] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
                   ` (8 subsequent siblings)
  22 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:16 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add "const" to the "struct module_clone_data" that we pass to
clone_submodule(), which makes the ownership clear, and stops us from
clobbering the "clone_data->path".

We still need to add to the "reference" member, which is a "struct
string_list". Let's do this by having clone_submodule() create its
own, and copy the contents over, allowing us to pass it as a
separate parameter.

This new "struct string_list" still leaks memory, just as the "struct
module_clone_data" did before. let's not fix that for now, to fix that
we'll need to add some "goto cleanup" to the relevant code. That will
be done in a follow-up commits, at that point it'll be easier to fix
the memory leak.

The scope of the new "reference" variable in add_submodule() could be
narrowed to the "else" block, but as we'll eventually free it with a
"goto cleanup" let's declare it at the start of the function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 49 ++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6cedcc5b239..e235acce985 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1434,7 +1434,6 @@ struct module_clone_data {
 	const char *url;
 	const char *depth;
 	struct list_objects_filter_options *filter_options;
-	struct string_list reference;
 	unsigned int quiet: 1;
 	unsigned int progress: 1;
 	unsigned int dissociate: 1;
@@ -1442,7 +1441,6 @@ struct module_clone_data {
 	int single_branch;
 };
 #define MODULE_CLONE_DATA_INIT { \
-	.reference = STRING_LIST_INIT_NODUP, \
 	.single_branch = -1, \
 }
 
@@ -1569,18 +1567,20 @@ static char *clone_submodule_sm_gitdir(const char *name)
 	return sm_gitdir;
 }
 
-static int clone_submodule(struct module_clone_data *clone_data)
+static int clone_submodule(const struct module_clone_data *clone_data,
+			   struct string_list *reference)
 {
 	char *p;
 	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
 	char *sm_alternate = NULL, *error_strategy = NULL;
 	struct child_process cp = CHILD_PROCESS_INIT;
+	const char *clone_data_path;
 
 	if (!is_absolute_path(clone_data->path))
-		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
-					   clone_data->path);
+		clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
+					  clone_data->path);
 	else
-		clone_data->path = xstrdup(clone_data->path);
+		clone_data_path = xstrdup(clone_data->path);
 
 	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
 		die(_("refusing to create/use '%s' in another submodule's "
@@ -1590,7 +1590,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 		if (safe_create_leading_directories_const(sm_gitdir) < 0)
 			die(_("could not create directory '%s'"), sm_gitdir);
 
-		prepare_possible_alternates(clone_data->name, &clone_data->reference);
+		prepare_possible_alternates(clone_data->name, reference);
 
 		strvec_push(&cp.args, "clone");
 		strvec_push(&cp.args, "--no-checkout");
@@ -1600,10 +1600,10 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			strvec_push(&cp.args, "--progress");
 		if (clone_data->depth && *(clone_data->depth))
 			strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
-		if (clone_data->reference.nr) {
+		if (reference->nr) {
 			struct string_list_item *item;
 
-			for_each_string_list_item(item, &clone_data->reference)
+			for_each_string_list_item(item, reference)
 				strvec_pushl(&cp.args, "--reference",
 					     item->string, NULL);
 		}
@@ -1622,7 +1622,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 
 		strvec_push(&cp.args, "--");
 		strvec_push(&cp.args, clone_data->url);
-		strvec_push(&cp.args, clone_data->path);
+		strvec_push(&cp.args, clone_data_path);
 
 		cp.git_cmd = 1;
 		prepare_submodule_repo_env(&cp.env);
@@ -1630,25 +1630,25 @@ static int clone_submodule(struct module_clone_data *clone_data)
 
 		if(run_command(&cp))
 			die(_("clone of '%s' into submodule path '%s' failed"),
-			    clone_data->url, clone_data->path);
+			    clone_data->url, clone_data_path);
 	} else {
 		struct strbuf sb = STRBUF_INIT;
 
-		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
-		    !is_empty_dir(clone_data->path))
-			die(_("directory not empty: '%s'"), clone_data->path);
-		if (safe_create_leading_directories_const(clone_data->path) < 0)
-			die(_("could not create directory '%s'"), clone_data->path);
+		if (clone_data->require_init && !access(clone_data_path, X_OK) &&
+		    !is_empty_dir(clone_data_path))
+			die(_("directory not empty: '%s'"), clone_data_path);
+		if (safe_create_leading_directories_const(clone_data_path) < 0)
+			die(_("could not create directory '%s'"), clone_data_path);
 		strbuf_addf(&sb, "%s/index", sm_gitdir);
 		unlink_or_warn(sb.buf);
 		strbuf_release(&sb);
 	}
 
-	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
+	connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0);
 
-	p = git_pathdup_submodule(clone_data->path, "config");
+	p = git_pathdup_submodule(clone_data_path, "config");
 	if (!p)
-		die(_("could not get submodule directory for '%s'"), clone_data->path);
+		die(_("could not get submodule directory for '%s'"), clone_data_path);
 
 	/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
 	git_config_get_string("submodule.alternateLocation", &sm_alternate);
@@ -1673,6 +1673,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
 	struct list_objects_filter_options filter_options = { 0 };
+	struct string_list reference = STRING_LIST_INIT_NODUP;
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1686,7 +1687,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		OPT_STRING(0, "url", &clone_data.url,
 			   N_("string"),
 			   N_("url where to clone the submodule from")),
-		OPT_STRING_LIST(0, "reference", &clone_data.reference,
+		OPT_STRING_LIST(0, "reference", &reference,
 			   N_("repo"),
 			   N_("reference repository")),
 		OPT_BOOL(0, "dissociate", &dissociate,
@@ -1725,7 +1726,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		usage_with_options(git_submodule_helper_usage,
 				   module_clone_options);
 
-	clone_submodule(&clone_data);
+	clone_submodule(&clone_data, &reference);
 	list_objects_filter_release(&filter_options);
 	return 0;
 }
@@ -2913,6 +2914,7 @@ static int add_submodule(const struct add_data *add_data)
 {
 	char *submod_gitdir_path;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
+	struct string_list reference = STRING_LIST_INIT_NODUP;
 
 	/* perhaps the path already exists and is already a git repo, else clone it */
 	if (is_directory(add_data->sm_path)) {
@@ -2929,6 +2931,7 @@ static int add_submodule(const struct add_data *add_data)
 		free(submod_gitdir_path);
 	} else {
 		struct child_process cp = CHILD_PROCESS_INIT;
+
 		submod_gitdir_path = xstrfmt(".git/modules/%s", add_data->sm_name);
 
 		if (is_directory(submod_gitdir_path)) {
@@ -2968,13 +2971,13 @@ static int add_submodule(const struct add_data *add_data)
 		clone_data.quiet = add_data->quiet;
 		clone_data.progress = add_data->progress;
 		if (add_data->reference_path)
-			string_list_append(&clone_data.reference,
+			string_list_append(&reference,
 					   xstrdup(add_data->reference_path));
 		clone_data.dissociate = add_data->dissociate;
 		if (add_data->depth >= 0)
 			clone_data.depth = xstrfmt("%d", add_data->depth);
 
-		if (clone_submodule(&clone_data))
+		if (clone_submodule(&clone_data, &reference))
 			return -1;
 
 		prepare_submodule_repo_env(&cp.env);
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 15/20] submodule--helper: add "const" to copy of "update_data"
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (13 preceding siblings ...)
  2022-07-28 16:16 ` [PATCH 14/20] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:17 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:17 ` [PATCH 16/20] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

From: Glen Choo <chooglen@google.com>

Add a "const" to the copy of "struct update_data" that's tracked by
the "struct submodule_update_clone", as it neither owns nor modifies
it.

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e235acce985..fe92c9858ce 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1777,7 +1777,7 @@ struct submodule_update_clone {
 	int current;
 
 	/* configuration parameters which are passed on to the children */
-	struct update_data *update_data;
+	const struct update_data *update_data;
 
 	/* to be consumed by update_submodule() */
 	struct update_clone_data *update_clone;
@@ -1862,7 +1862,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	const char *update_string;
 	enum submodule_update_type update_type;
 	char *key;
-	struct update_data *ud = suc->update_data;
+	const struct update_data *ud = suc->update_data;
 	char *displaypath = get_submodule_displaypath(ce->name, ud->prefix);
 	struct strbuf sb = STRBUF_INIT;
 	int needs_cloning = 0;
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 16/20] submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (14 preceding siblings ...)
  2022-07-28 16:17 ` [PATCH 15/20] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:17 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:17 ` [PATCH 17/20] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

From: Glen Choo <chooglen@google.com>

Refactor code added in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13) so that "errmsg" and
"errmsg_str" are folded into one. The distinction between the empty
string and NULL is something that's tested for by
e.g. "t/t7401-submodule-summary.sh".

This is in preparation for fixing a memory leak the "struct strbuf" in
the pre-image.

Let's also pass a "const char *" to print_submodule_summary(), as it
should not be modifying the "errmsg".

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fe92c9858ce..f451704af79 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -761,7 +761,7 @@ static char *verify_submodule_committish(const char *sm_path,
 	return strbuf_detach(&result, NULL);
 }
 
-static void print_submodule_summary(struct summary_cb *info, char *errmsg,
+static void print_submodule_summary(struct summary_cb *info, const char *errmsg,
 				    int total_commits, const char *displaypath,
 				    const char *src_abbrev, const char *dst_abbrev,
 				    struct module_cb *p)
@@ -819,7 +819,7 @@ static void generate_submodule_summary(struct summary_cb *info,
 {
 	char *displaypath, *src_abbrev = NULL, *dst_abbrev;
 	int missing_src = 0, missing_dst = 0;
-	char *errmsg = NULL;
+	struct strbuf errmsg = STRBUF_INIT;
 	int total_commits = -1;
 
 	if (!info->cached && oideq(&p->oid_dst, null_oid())) {
@@ -920,23 +920,21 @@ static void generate_submodule_summary(struct summary_cb *info,
 		 * submodule, i.e., deleted or changed to blob
 		 */
 		if (S_ISGITLINK(p->mod_dst)) {
-			struct strbuf errmsg_str = STRBUF_INIT;
 			if (missing_src && missing_dst) {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commits %s and %s\n",
+				strbuf_addf(&errmsg, "  Warn: %s doesn't contain commits %s and %s\n",
 					    displaypath, oid_to_hex(&p->oid_src),
 					    oid_to_hex(&p->oid_dst));
 			} else {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commit %s\n",
+				strbuf_addf(&errmsg, "  Warn: %s doesn't contain commit %s\n",
 					    displaypath, missing_src ?
 					    oid_to_hex(&p->oid_src) :
 					    oid_to_hex(&p->oid_dst));
 			}
-			errmsg = strbuf_detach(&errmsg_str, NULL);
 		}
 	}
 
-	print_submodule_summary(info, errmsg, total_commits,
-				displaypath, src_abbrev,
+	print_submodule_summary(info, errmsg.len ? errmsg.buf : NULL,
+				total_commits, displaypath, src_abbrev,
 				dst_abbrev, p);
 
 	free(displaypath);
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 17/20] submodule--helper: rename "int res" to "int ret"
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (15 preceding siblings ...)
  2022-07-28 16:17 ` [PATCH 16/20] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:17 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:17 ` [PATCH 18/20] submodule--helper: add skeleton "goto cleanup" to update_submodule() Ævar Arnfjörð Bjarmason
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Rename the "res" variable added in b3c5f5cb048 (submodule: move core
cmd_update() logic to C, 2022-03-15) to "ret", which is the convention
in the rest of this file.

Eventual follow-up commits will change this code to a "goto cleanup"
pattern, let's have the post image look consistent with the rest.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f451704af79..349fe7f269c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2424,7 +2424,7 @@ static int update_submodule(struct update_data *update_data)
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		struct update_data next = *update_data;
-		int res;
+		int ret;
 
 		next.prefix = NULL;
 		oidcpy(&next.oid, null_oid());
@@ -2436,14 +2436,14 @@ static int update_submodule(struct update_data *update_data)
 		update_data_to_args(&next, &cp.args);
 
 		/* die() if child process die()'d */
-		res = run_command(&cp);
-		if (!res)
+		ret = run_command(&cp);
+		if (!ret)
 			return 0;
 		die_message(_("Failed to recurse into submodule path '%s'"),
 			    update_data->displaypath);
-		if (res == 128)
-			exit(res);
-		else if (res)
+		if (ret == 128)
+			exit(ret);
+		else if (ret)
 			return 1;
 	}
 
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 18/20] submodule--helper: add skeleton "goto cleanup" to update_submodule()
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (16 preceding siblings ...)
  2022-07-28 16:17 ` [PATCH 17/20] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:17 ` Ævar Arnfjörð Bjarmason
  2022-07-28 16:17 ` [PATCH 19/20] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add a skeleton "goto cleanup" pattern to update_submodule(), rather
than having branches in it "return". This is in preparation for
eventually freeing data with the "cleanup" label, but for now we're
using it as the equivalent of a "done" label.

The "exit()" branch is not handled yet, and neither is the exit() that
run_update_procedure() might invoke. That'll be handled in a
subsequent commit.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 349fe7f269c..68aa10a26cd 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2383,6 +2383,8 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 
 static int update_submodule(struct update_data *update_data)
 {
+	int ret = 1;
+
 	ensure_core_worktree(update_data->sm_path);
 
 	update_data->displaypath = get_submodule_displaypath(
@@ -2417,14 +2419,14 @@ static int update_submodule(struct update_data *update_data)
 		free(remote_ref);
 	}
 
-	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force)
+	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
 		if (run_update_procedure(update_data))
-			return 1;
+			goto cleanup;
+	}
 
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		struct update_data next = *update_data;
-		int ret;
 
 		next.prefix = NULL;
 		oidcpy(&next.oid, null_oid());
@@ -2438,16 +2440,20 @@ static int update_submodule(struct update_data *update_data)
 		/* die() if child process die()'d */
 		ret = run_command(&cp);
 		if (!ret)
-			return 0;
+			goto cleanup;
 		die_message(_("Failed to recurse into submodule path '%s'"),
 			    update_data->displaypath);
-		if (ret == 128)
+		if (ret == 128) {
 			exit(ret);
-		else if (ret)
-			return 1;
+		} else if (ret) {
+			ret = 1;
+			goto cleanup;
+		}
 	}
 
-	return 0;
+	ret = 0;
+cleanup:
+	return ret;
 }
 
 static int update_submodules(struct update_data *update_data)
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 19/20] submodule--helper: don't exit() on failure, return
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (17 preceding siblings ...)
  2022-07-28 16:17 ` [PATCH 18/20] submodule--helper: add skeleton "goto cleanup" to update_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:17 ` Ævar Arnfjörð Bjarmason
  2022-07-29 22:23   ` Glen Choo
  2022-07-28 16:17 ` [PATCH 20/20] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
                   ` (3 subsequent siblings)
  22 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Change code downstream of module_update() to short-circuit and return
to the top-level on failure, rather than calling exit().

To do so we need to diligently check whether we "must_die_on_failure",
which is a pattern started in c51f8f94e5b (submodule--helper: run
update procedures from C, 2021-08-24), but which hadn't been completed
to the point where we could avoid calling exit() here.

This introduces no functional changes, but makes it easier to both
call these routines as a library in the future, and to eventually
avoid leaking memory.

This and similar control flow in submodule--helper.c could be made
simpler by properly "libifying" it, i.e. to have it consistently
return -1 on failures, and to early return on any non-success.

But let's leave that larger project for now, and (mostly) emulate what
were doing with the "exit(128)" before this change.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 68aa10a26cd..d3f22f03766 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2121,7 +2121,8 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	return run_command(&cp);
 }
 
-static int run_update_command(struct update_data *ud, int subforce)
+static int run_update_command(struct update_data *ud, int subforce,
+			      int *must_die_on_failurep)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
@@ -2183,8 +2184,10 @@ static int run_update_command(struct update_data *ud, int subforce)
 			BUG("unexpected update strategy type: %s",
 			    submodule_strategy_to_string(&ud->update_strategy));
 		}
-		if (must_die_on_failure)
-			exit(128);
+		if (must_die_on_failure) {
+			*must_die_on_failurep = 1;
+			return 128;
+		}
 
 		/* the command failed, but update must continue */
 		return 1;
@@ -2218,7 +2221,8 @@ static int run_update_command(struct update_data *ud, int subforce)
 	return 0;
 }
 
-static int run_update_procedure(struct update_data *ud)
+static int run_update_procedure(struct update_data *ud,
+				int *must_die_on_failure)
 {
 	int subforce = is_null_oid(&ud->suboid) || ud->force;
 
@@ -2245,7 +2249,7 @@ static int run_update_procedure(struct update_data *ud)
 			    ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
-	return run_update_command(ud, subforce);
+	return run_update_command(ud, subforce, must_die_on_failure);
 }
 
 static const char *remote_submodule_branch(const char *path)
@@ -2381,7 +2385,8 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 				    "--no-single-branch");
 }
 
-static int update_submodule(struct update_data *update_data)
+static int update_submodule(struct update_data *update_data,
+			    int *must_die_on_failure)
 {
 	int ret = 1;
 
@@ -2420,8 +2425,13 @@ static int update_submodule(struct update_data *update_data)
 	}
 
 	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
-		if (run_update_procedure(update_data))
+		ret = run_update_procedure(update_data, must_die_on_failure);
+		if (ret && *must_die_on_failure) {
+			goto cleanup;
+		} else if (ret) {
+			ret = 1;
 			goto cleanup;
+		}
 	}
 
 	if (update_data->recursive) {
@@ -2444,7 +2454,8 @@ static int update_submodule(struct update_data *update_data)
 		die_message(_("Failed to recurse into submodule path '%s'"),
 			    update_data->displaypath);
 		if (ret == 128) {
-			exit(ret);
+			*must_die_on_failure = 1;
+			goto cleanup;
 		} else if (ret) {
 			ret = 1;
 			goto cleanup;
@@ -2482,13 +2493,18 @@ static int update_submodules(struct update_data *update_data)
 
 	for (i = 0; i < suc.update_clone_nr; i++) {
 		struct update_clone_data ucd = suc.update_clone[i];
+		int code;
+		int must_die_on_failure = 0;
 
 		oidcpy(&update_data->oid, &ucd.oid);
 		update_data->just_cloned = ucd.just_cloned;
 		update_data->sm_path = ucd.sub->path;
 
-		if (update_submodule(update_data))
-			res = 1;
+		code = update_submodule(update_data, &must_die_on_failure);
+		if (code)
+			res = code;
+		if (must_die_on_failure)
+			goto cleanup;
 	}
 
 cleanup:
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH 20/20] submodule--helper: fix bad config API usage
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (18 preceding siblings ...)
  2022-07-28 16:17 ` [PATCH 19/20] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
@ 2022-07-28 16:17 ` Ævar Arnfjörð Bjarmason
  2022-07-29 22:52 ` [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Glen Choo
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-07-28 16:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Fix bad config API usage added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06). After
git_config_get_string() returns successfully we know the "char **dest"
will be non-NULL.

A coccinelle patch that transforms this turns up a couple of other
such issues, one in fetch-pack.c, and another in upload-pack.c:

	@@
	identifier F =~ "^(repo|git)_config_get_string(_tmp)?$";
	identifier V;
	@@
	  !F(..., &V)
	- && (V)

But let's focus narrowly on submodule--helper for now, we can fix
those some other time.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d3f22f03766..22c79353bb0 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3083,7 +3083,7 @@ static void configure_added_submodule(struct add_data *add_data)
 	 * is_submodule_active(), since that function needs to find
 	 * out the value of "submodule.active" again anyway.
 	 */
-	if (!git_config_get_string("submodule.active", &val) && val) {
+	if (!git_config_get_string("submodule.active", &val)) {
 		/*
 		 * If the submodule being added isn't already covered by the
 		 * current configured pathspec, set the submodule's active flag
-- 
2.37.1.1167.g38fda70d8c4


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* Re: [PATCH 13/20] submodule--helper: stop conflating "sb" in clone_submodule()
  2022-07-28 16:16 ` [PATCH 13/20] submodule--helper: stop conflating "sb" in clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-29 17:08   ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-07-29 17:08 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Refactor the two uses of a "struct strbuf sb" such that each of them
> exists in its own scope. This makes the control flow clearer.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 25 +++++++++++++++++--------
>  1 file changed, 17 insertions(+), 8 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index f74957444e1..6cedcc5b239 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -1557,16 +1557,24 @@ static void prepare_possible_alternates(const char *sm_name,
>  	free(error_strategy);
>  }
>  
> -static int clone_submodule(struct module_clone_data *clone_data)
> +static char *clone_submodule_sm_gitdir(const char *name)
>  {
> -	char *p, *sm_gitdir;
> -	char *sm_alternate = NULL, *error_strategy = NULL;
>  	struct strbuf sb = STRBUF_INIT;
> -	struct child_process cp = CHILD_PROCESS_INIT;
> +	char *sm_gitdir;
>  
> -	submodule_name_to_gitdir(&sb, the_repository, clone_data->name);
> +	submodule_name_to_gitdir(&sb, the_repository, name);
>  	sm_gitdir = absolute_pathdup(sb.buf);
> -	strbuf_reset(&sb);
> +	strbuf_release(&sb);
> +
> +	return sm_gitdir;
> +}
> +
> +static int clone_submodule(struct module_clone_data *clone_data)
> +{
> +	char *p;
> +	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
> +	char *sm_alternate = NULL, *error_strategy = NULL;
> +	struct child_process cp = CHILD_PROCESS_INIT;
>  
>  	if (!is_absolute_path(clone_data->path))
>  		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
> @@ -1624,6 +1632,8 @@ static int clone_submodule(struct module_clone_data *clone_data)
>  			die(_("clone of '%s' into submodule path '%s' failed"),
>  			    clone_data->url, clone_data->path);
>  	} else {
> +		struct strbuf sb = STRBUF_INIT;
> +
>  		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
>  		    !is_empty_dir(clone_data->path))
>  			die(_("directory not empty: '%s'"), clone_data->path);
> @@ -1631,7 +1641,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
>  			die(_("could not create directory '%s'"), clone_data->path);
>  		strbuf_addf(&sb, "%s/index", sm_gitdir);
>  		unlink_or_warn(sb.buf);
> -		strbuf_reset(&sb);
> +		strbuf_release(&sb);
>  	}

As Junio mentioned in
https://lore.kernel.org/git/xmqqlesmf9or.fsf@gitster.g, we could also
replace this with xstrfmt(). I think that gets rid of all of the
users of "sb", so I doubt we'll even need this patch once we
make that change :)

>  
>  	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
> @@ -1653,7 +1663,6 @@ static int clone_submodule(struct module_clone_data *clone_data)
>  	free(sm_alternate);
>  	free(error_strategy);
>  
> -	strbuf_release(&sb);
>  	free(sm_gitdir);
>  	free(p);
>  	return 0;
> -- 
> 2.37.1.1167.g38fda70d8c4

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH 01/20] submodule tests: test usage behavior
  2022-07-28 16:16 ` [PATCH 01/20] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
@ 2022-07-29 20:30   ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-07-29 20:30 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Test what exit code and output we emit on "git submodule -h", how we
> handle "--" when no subcommand is specified, and how the top-level
> "--recursive" option is handled.
>
> For "-h" this doesn't make sense, but let's test for it so that any
> subsequent eventual behavior change will become clear.

As a smoke test, this makes sense.

>
> For "--" this follows up on 68cabbfda36 (submodule: document default
> behavior, 2019-02-15) and tests that when "status" isn't supplied we
> don't support the "--" delimiter. There's no intrinsically good reason
> not to support that. We behave this way due to edge cases in
> git-submodule.sh's implementation, but as with "-h" let's assert our
> current long-standing behavior for now.

By this, do you mean that git-submodule.sh inserts "--" when it invokes
"git submodule--helper"? That also seems ok.

>
> For "--recursive" the exclusion of it from the top-level appears to
> have been an omission in 15fc56a8536 (git submodule foreach: Add
> --recursive to recurse into nested submodules, 2009-08-19), there
> doesn't seem to be a reason not to support it alongside "--quiet" and
> "--cached", but let's likewise assert our existing behavior for now.

I'm not sure about this one. "--recursive" isn't a top level option, and
15fc56a8536 doesn't seem to suggest that it was meant to be one (but I
did realize that git-submodule.txt documents all of the options to all
subcommands, which is very confusing.)

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  t/t7400-submodule-basic.sh | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
>
> diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
> index e7cec2e457a..b858871a953 100755
> --- a/t/t7400-submodule-basic.sh
> +++ b/t/t7400-submodule-basic.sh
> @@ -14,6 +14,32 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>  
>  . ./test-lib.sh
>  
> +test_expect_success 'submodule usage: -h' '
> +	git submodule -h >out 2>err &&
> +	grep "^usage: git submodule" out &&
> +	test_must_be_empty err
> +'
> +
> +test_expect_success 'submodule usage: --recursive' '
> +	test_expect_code 1 git submodule --recursive >out 2>err &&
> +	grep "^usage: git submodule" err &&
> +	test_must_be_empty out
> +'
> +
> +test_expect_success 'submodule usage: status --' '
> +	test_expect_code 1 git submodule -- &&
> +	test_expect_code 1 git submodule --end-of-options
> +'
> +
> +for opt in '--quiet' '--cached'
> +do
> +	test_expect_success "submodule usage: status $opt" '
> +		git submodule $opt &&
> +		git submodule status $opt &&
> +		git submodule $opt status
> +	'
> +done
> +
>  test_expect_success 'submodule deinit works on empty repository' '
>  	git submodule deinit --all
>  '
> -- 
> 2.37.1.1167.g38fda70d8c4

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH 04/20] submodule--helper: remove unused "list" helper
  2022-07-28 16:16 ` [PATCH 04/20] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
@ 2022-07-29 21:31   ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-07-29 21:31 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Remove the "submodule--helper list" sub-command, which hasn't been
> used by git-submodule.sh since 2964d6e5e1e (submodule: port subcommand
> 'set-branch' from shell to C, 2020-06-02).
>
> There was a test added in 2b56bb7a87a (submodule helper list: respect
> correct path prefix, 2016-02-24) which relied on it, but the right
> thing to do here is to delete that test as well.
>
> That test was regression testing the "list" subcommand itself. We're
> not getting anything useful from the "list | cut -f2" invocation that
> we couldn't get from "foreach 'echo $sm_path'".
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 40 -------------------------------------
>  t/t7400-submodule-basic.sh  | 25 -----------------------
>  2 files changed, 65 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index ac2553ba9d3..47ed24c6a60 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -266,45 +266,6 @@ static char *get_up_path(const char *path)
>  	return strbuf_detach(&sb, NULL);
>  }
>  
> -static int module_list(int argc, const char **argv, const char *prefix)
> -{
> -	int i;
> -	struct pathspec pathspec;
> -	struct module_list list = MODULE_LIST_INIT;
> -
> -	struct option module_list_options[] = {
> -		OPT_STRING(0, "prefix", &prefix,
> -			   N_("path"),
> -			   N_("alternative anchor for relative paths")),
> -		OPT_END()
> -	};
> -
> -	const char *const git_submodule_helper_usage[] = {
> -		N_("git submodule--helper list [--prefix=<path>] [<path>...]"),
> -		NULL
> -	};
> -
> -	argc = parse_options(argc, argv, prefix, module_list_options,
> -			     git_submodule_helper_usage, 0);
> -
> -	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
> -		return 1;
> -
> -	for (i = 0; i < list.nr; i++) {
> -		const struct cache_entry *ce = list.entries[i];
> -
> -		if (ce_stage(ce))
> -			printf("%06o %s U\t", ce->ce_mode,
> -			       oid_to_hex(null_oid()));
> -		else
> -			printf("%06o %s %d\t", ce->ce_mode,
> -			       oid_to_hex(&ce->oid), ce_stage(ce));
> -
> -		fprintf(stdout, "%s\n", ce->name);
> -	}
> -	return 0;
> -}
> -

Hooray for nuking dead code! Thanks :)

I'm happy that we're taking a sh -> C path that's catching little things
like this.

>  static void for_each_listed_submodule(const struct module_list *list,
>  				      each_submodule_fn fn, void *cb_data)
>  {
> @@ -3340,7 +3301,6 @@ struct cmd_struct {
>  };
>  
>  static struct cmd_struct commands[] = {
> -	{"list", module_list, 0},
>  	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
>  	{"add", module_add, 0},
>  	{"update", module_update, SUPPORT_SUPER_PREFIX},
> diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
> index 6a77d817a82..b50db3f1031 100755
> --- a/t/t7400-submodule-basic.sh
> +++ b/t/t7400-submodule-basic.sh
> @@ -1255,31 +1255,6 @@ test_expect_success 'submodule add clone shallow submodule' '
>  	)
>  '
>  
> -test_expect_success 'submodule helper list is not confused by common prefixes' '
> -	mkdir -p dir1/b &&
> -	(
> -		cd dir1/b &&
> -		git init &&
> -		echo hi >testfile2 &&
> -		git add . &&
> -		git commit -m "test1"
> -	) &&
> -	mkdir -p dir2/b &&
> -	(
> -		cd dir2/b &&
> -		git init &&
> -		echo hello >testfile1 &&
> -		git add .  &&
> -		git commit -m "test2"
> -	) &&
> -	git submodule add /dir1/b dir1/b &&
> -	git submodule add /dir2/b dir2/b &&
> -	git commit -m "first submodule commit" &&
> -	git submodule--helper list dir1/b | cut -f 2 >actual &&
> -	echo "dir1/b" >expect &&
> -	test_cmp expect actual
> -'
> -
>  test_expect_success 'setup superproject with submodules' '
>  	git init sub1 &&
>  	test_commit -C sub1 test &&
> -- 
> 2.37.1.1167.g38fda70d8c4

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH 06/20] submodule--helper: move "is-active" to a test-tool
  2022-07-28 16:16 ` [PATCH 06/20] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
@ 2022-07-29 21:45   ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-07-29 21:45 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Create a new "test-tool submodule" and move the "is-active" subcommand
> over to it. It was added in 5c2bd8b77ae (submodule--helper: add
> is-active subcommand, 2017-03-16), since
> a452128a36c (submodule--helper: introduce add-config subcommand,
> 2021-08-06) it hasn't been used by git-submodule.sh.
>
> Since we're creating a command dispatch similar to test-tool.c itself
> let's split out the "struct test_cmd" into a new test-tool-utils.h,
> which both this new code and test-tool.c itself can use.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  Makefile                       |  1 +
>  builtin/submodule--helper.c    |  9 ------
>  t/helper/test-submodule.c      | 58 ++++++++++++++++++++++++++++++++++
>  t/helper/test-tool-utils.h     |  9 ++++++
>  t/helper/test-tool.c           |  7 ++--
>  t/helper/test-tool.h           |  1 +
>  t/t7413-submodule-is-active.sh | 32 +++++++++----------
>  7 files changed, 87 insertions(+), 30 deletions(-)
>  create mode 100644 t/helper/test-submodule.c
>  create mode 100644 t/helper/test-tool-utils.h
>
> diff --git a/Makefile b/Makefile
> index 1624471badc..ad7fbd36885 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -785,6 +785,7 @@ TEST_BUILTINS_OBJS += test-strcmp-offset.o
>  TEST_BUILTINS_OBJS += test-string-list.o
>  TEST_BUILTINS_OBJS += test-submodule-config.o
>  TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
> +TEST_BUILTINS_OBJS += test-submodule.o
>  TEST_BUILTINS_OBJS += test-subprocess.o
>  TEST_BUILTINS_OBJS += test-trace2.o
>  TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 47ed24c6a60..b2fc732b5d8 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2728,14 +2728,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
>  	return 0;
>  }
>  
> -static int is_active(int argc, const char **argv, const char *prefix)
> -{
> -	if (argc != 2)
> -		die("submodule--helper is-active takes exactly 1 argument");
> -
> -	return !is_submodule_active(the_repository, argv[1]);
> -}
> -
>  /*
>   * Exit non-zero if any of the submodule names given on the command line is
>   * invalid. If no names are given, filter stdin to print only valid names
> @@ -3313,7 +3305,6 @@ static struct cmd_struct commands[] = {
>  	{"summary", module_summary, 0},
>  	{"push-check", push_check, 0},
>  	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
> -	{"is-active", is_active, 0},
>  	{"check-name", check_name, 0},
>  	{"config", module_config, 0},
>  	{"set-url", module_set_url, 0},
> diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
> new file mode 100644
> index 00000000000..494c6558d9f
> --- /dev/null
> +++ b/t/helper/test-submodule.c
> @@ -0,0 +1,58 @@
> +#include "test-tool.h"
> +#include "test-tool-utils.h"
> +#include "cache.h"
> +#include "parse-options.h"
> +#include "submodule.h"
> +
> +#define TEST_TOOL_IS_ACTIVE_USAGE \
> +	"test-tool submodule is-active <name>"
> +static const char *submodule_is_active_usage[] = {
> +	TEST_TOOL_IS_ACTIVE_USAGE,
> +	NULL
> +};
> +
> +static const char *submodule_usage[] = {
> +	TEST_TOOL_IS_ACTIVE_USAGE,
> +	NULL
> +};
> +
> +static int cmd__submodule_is_active(int argc, const char **argv)
> +{
> +	struct option options[] = {
> +		OPT_END()
> +	};
> +	argc = parse_options(argc, argv, "test-tools", options,
> +			     submodule_is_active_usage, 0);
> +	if (argc != 1)
> +		usage_with_options(submodule_is_active_usage, options);
> +
> +	setup_git_directory();
> +
> +	return !is_submodule_active(the_repository, argv[0]);
> +}
> +
> +static struct test_cmd cmds[] = {
> +	{ "is-active", cmd__submodule_is_active },
> +};
> +
> +int cmd__submodule(int argc, const char **argv)
> +{
> +	struct option options[] = {
> +		OPT_END()
> +	};
> +	size_t i;
> +
> +	argc = parse_options(argc, argv, "test-tools", options, submodule_usage,
> +			     PARSE_OPT_STOP_AT_NON_OPTION);
> +	if (argc < 1)
> +		usage_with_options(submodule_usage, options);
> +
> +	for (i = 0; i < ARRAY_SIZE(cmds); i++)
> +		if (!strcmp(cmds[i].name, argv[0]))
> +			return cmds[i].fn(argc, argv);
> +
> +	usage_msg_optf("unknown subcommand '%s'", submodule_usage, options,
> +		       argv[0]);
> +
> +	return 0;
> +}
> diff --git a/t/helper/test-tool-utils.h b/t/helper/test-tool-utils.h
> new file mode 100644
> index 00000000000..6a0e5e0074f
> --- /dev/null
> +++ b/t/helper/test-tool-utils.h
> @@ -0,0 +1,9 @@
> +#ifndef TEST_TOOL_UTILS_H
> +#define TEST_TOOL_UTILS_H
> +
> +struct test_cmd {
> +	const char *name;
> +	int (*fn)(int argc, const char **argv);
> +};
> +
> +#endif
> diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
> index 318fdbab0c3..7a6a8b88a91 100644
> --- a/t/helper/test-tool.c
> +++ b/t/helper/test-tool.c
> @@ -1,5 +1,6 @@
>  #include "git-compat-util.h"
>  #include "test-tool.h"
> +#include "test-tool-utils.h"
>  #include "trace2.h"
>  #include "parse-options.h"
>  
> @@ -8,11 +9,6 @@ static const char * const test_tool_usage[] = {
>  	NULL
>  };
>  
> -struct test_cmd {
> -	const char *name;
> -	int (*fn)(int argc, const char **argv);
> -};
> -
>  static struct test_cmd cmds[] = {
>  	{ "advise", cmd__advise_if_enabled },
>  	{ "bitmap", cmd__bitmap },
> @@ -78,6 +74,7 @@ static struct test_cmd cmds[] = {
>  	{ "simple-ipc", cmd__simple_ipc },
>  	{ "strcmp-offset", cmd__strcmp_offset },
>  	{ "string-list", cmd__string_list },
> +	{ "submodule", cmd__submodule },
>  	{ "submodule-config", cmd__submodule_config },
>  	{ "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
>  	{ "subprocess", cmd__subprocess },
> diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
> index bb799271631..5f4f69dee81 100644
> --- a/t/helper/test-tool.h
> +++ b/t/helper/test-tool.h
> @@ -68,6 +68,7 @@ int cmd__sigchain(int argc, const char **argv);
>  int cmd__simple_ipc(int argc, const char **argv);
>  int cmd__strcmp_offset(int argc, const char **argv);
>  int cmd__string_list(int argc, const char **argv);
> +int cmd__submodule(int argc, const char **argv);
>  int cmd__submodule_config(int argc, const char **argv);
>  int cmd__submodule_nested_repo_config(int argc, const char **argv);
>  int cmd__subprocess(int argc, const char **argv);

I'm underqualified to comment on structure of test-tool, so I won't
comment on that, but it makes sense to convert code that is only used in
tests into test helpers.

That said, don't we only use "git submodule--helper is-active" inside
the tests for "git submodule--helper is-active"? If so, I'd think the
right thing to do is to just get rid of the code altogether.

The exception IMO, is if we think that we want a kind of "unit test"
that checks our logic for determining if a submodule is active. I don't
really think that's necessary, but if so, we probably want to update the
description of t7413 to describe that intent.

> diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
> index c8e7e983317..9ead083371a 100755
> --- a/t/t7413-submodule-is-active.sh
> +++ b/t/t7413-submodule-is-active.sh
> @@ -1,8 +1,8 @@
>  #!/bin/sh
>  
> -test_description='Test submodule--helper is-active
> +test_description='Test with test-tool submodule is-active
>  
> -This test verifies that `git submodue--helper is-active` correctly identifies
> +This test verifies that `test-tool submodule is-active` correctly identifies
>  submodules which are "active" and interesting to the user.
>  '
>  
> @@ -25,13 +25,13 @@ test_expect_success 'setup' '
>  '
>  
>  test_expect_success 'is-active works with urls' '
> -	git -C super submodule--helper is-active sub1 &&
> -	git -C super submodule--helper is-active sub2 &&
> +	test-tool -C super submodule is-active sub1 &&
> +	test-tool -C super submodule is-active sub2 &&
>  
>  	git -C super config --unset submodule.sub1.URL &&
> -	test_must_fail git -C super submodule--helper is-active sub1 &&
> +	test_must_fail test-tool -C super submodule is-active sub1 &&
>  	git -C super config submodule.sub1.URL ../sub &&
> -	git -C super submodule--helper is-active sub1
> +	test-tool -C super submodule is-active sub1
>  '
>  
>  test_expect_success 'is-active works with submodule.<name>.active config' '
> @@ -39,11 +39,11 @@ test_expect_success 'is-active works with submodule.<name>.active config' '
>  	test_when_finished "git -C super config submodule.sub1.URL ../sub" &&
>  
>  	git -C super config --bool submodule.sub1.active "false" &&
> -	test_must_fail git -C super submodule--helper is-active sub1 &&
> +	test_must_fail test-tool -C super submodule is-active sub1 &&
>  
>  	git -C super config --bool submodule.sub1.active "true" &&
>  	git -C super config --unset submodule.sub1.URL &&
> -	git -C super submodule--helper is-active sub1
> +	test-tool -C super submodule is-active sub1
>  '
>  
>  test_expect_success 'is-active works with basic submodule.active config' '
> @@ -53,17 +53,17 @@ test_expect_success 'is-active works with basic submodule.active config' '
>  	git -C super config --add submodule.active "." &&
>  	git -C super config --unset submodule.sub1.URL &&
>  
> -	git -C super submodule--helper is-active sub1 &&
> -	git -C super submodule--helper is-active sub2
> +	test-tool -C super submodule is-active sub1 &&
> +	test-tool -C super submodule is-active sub2
>  '
>  
>  test_expect_success 'is-active correctly works with paths that are not submodules' '
>  	test_when_finished "git -C super config --unset-all submodule.active" &&
>  
> -	test_must_fail git -C super submodule--helper is-active not-a-submodule &&
> +	test_must_fail test-tool -C super submodule is-active not-a-submodule &&
>  
>  	git -C super config --add submodule.active "." &&
> -	test_must_fail git -C super submodule--helper is-active not-a-submodule
> +	test_must_fail test-tool -C super submodule is-active not-a-submodule
>  '
>  
>  test_expect_success 'is-active works with exclusions in submodule.active config' '
> @@ -72,8 +72,8 @@ test_expect_success 'is-active works with exclusions in submodule.active config'
>  	git -C super config --add submodule.active "." &&
>  	git -C super config --add submodule.active ":(exclude)sub1" &&
>  
> -	test_must_fail git -C super submodule--helper is-active sub1 &&
> -	git -C super submodule--helper is-active sub2
> +	test_must_fail test-tool -C super submodule is-active sub1 &&
> +	test-tool -C super submodule is-active sub2
>  '
>  
>  test_expect_success 'is-active with submodule.active and submodule.<name>.active' '
> @@ -85,8 +85,8 @@ test_expect_success 'is-active with submodule.active and submodule.<name>.active
>  	git -C super config --bool submodule.sub1.active "false" &&
>  	git -C super config --bool submodule.sub2.active "true" &&
>  
> -	test_must_fail git -C super submodule--helper is-active sub1 &&
> -	git -C super submodule--helper is-active sub2
> +	test_must_fail test-tool -C super submodule is-active sub1 &&
> +	test-tool -C super submodule is-active sub2
>  '
>  
>  test_expect_success 'is-active, submodule.active and submodule add' '
> -- 
> 2.37.1.1167.g38fda70d8c4

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH 07/20] submodule--helper: move "check-name" to a test-tool
  2022-07-28 16:16 ` [PATCH 07/20] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
@ 2022-07-29 21:55   ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-07-29 21:55 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Move the "check-name" helper to a test-tool, since
> a6226fd772b (submodule--helper: convert the bulk of cmd_add() to C,
> 2021-08-10) it has only been used by this test, not git-submodule.sh.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 24 -------------------
>  t/helper/test-submodule.c   | 46 +++++++++++++++++++++++++++++++++++++
>  t/t7450-bad-git-dotfiles.sh |  2 +-
>  3 files changed, 47 insertions(+), 25 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index b2fc732b5d8..06307886080 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2728,29 +2728,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
>  	return 0;
>  }
>  
> -/*
> - * Exit non-zero if any of the submodule names given on the command line is
> - * invalid. If no names are given, filter stdin to print only valid names
> - * (which is primarily intended for testing).
> - */
> -static int check_name(int argc, const char **argv, const char *prefix)
> -{
> -	if (argc > 1) {
> -		while (*++argv) {
> -			if (check_submodule_name(*argv) < 0)
> -				return 1;
> -		}
> -	} else {
> -		struct strbuf buf = STRBUF_INIT;
> -		while (strbuf_getline(&buf, stdin) != EOF) {
> -			if (!check_submodule_name(buf.buf))
> -				printf("%s\n", buf.buf);
> -		}
> -		strbuf_release(&buf);
> -	}
> -	return 0;
> -}
> -
>  static int module_config(int argc, const char **argv, const char *prefix)
>  {
>  	enum {
> @@ -3305,7 +3282,6 @@ static struct cmd_struct commands[] = {
>  	{"summary", module_summary, 0},
>  	{"push-check", push_check, 0},
>  	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
> -	{"check-name", check_name, 0},
>  	{"config", module_config, 0},
>  	{"set-url", module_set_url, 0},
>  	{"set-branch", module_set_branch, 0},
> diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
> index 494c6558d9f..9f0eb440192 100644
> --- a/t/helper/test-submodule.c
> +++ b/t/helper/test-submodule.c
> @@ -2,8 +2,16 @@
>  #include "test-tool-utils.h"
>  #include "cache.h"
>  #include "parse-options.h"
> +#include "submodule-config.h"
>  #include "submodule.h"
>  
> +#define TEST_TOOL_CHECK_NAME_USAGE \
> +	"test-tool submodule check-name <name>"
> +static const char *submodule_check_name_usage[] = {
> +	TEST_TOOL_CHECK_NAME_USAGE,
> +	NULL
> +};
> +
>  #define TEST_TOOL_IS_ACTIVE_USAGE \
>  	"test-tool submodule is-active <name>"
>  static const char *submodule_is_active_usage[] = {
> @@ -12,10 +20,47 @@ static const char *submodule_is_active_usage[] = {
>  };
>  
>  static const char *submodule_usage[] = {
> +	TEST_TOOL_CHECK_NAME_USAGE,
>  	TEST_TOOL_IS_ACTIVE_USAGE,
>  	NULL
>  };
>  
> +/*
> + * Exit non-zero if any of the submodule names given on the command line is
> + * invalid. If no names are given, filter stdin to print only valid names
> + * (which is primarily intended for testing).
> + */
> +static int check_name(int argc, const char **argv)
> +{
> +	if (argc > 1) {
> +		while (*++argv) {
> +			if (check_submodule_name(*argv) < 0)
> +				return 1;
> +		}
> +	} else {
> +		struct strbuf buf = STRBUF_INIT;
> +		while (strbuf_getline(&buf, stdin) != EOF) {
> +			if (!check_submodule_name(buf.buf))
> +				printf("%s\n", buf.buf);
> +		}
> +		strbuf_release(&buf);
> +	}
> +	return 0;
> +}
> +
> +static int cmd__submodule_check_name(int argc, const char **argv)
> +{
> +	struct option options[] = {
> +		OPT_END()
> +	};
> +	argc = parse_options(argc, argv, "test-tools", options,
> +			     submodule_check_name_usage, 0);
> +	if (argc)
> +		usage_with_options(submodule_check_name_usage, options);
> +
> +	return check_name(argc, argv);
> +}
> +
>  static int cmd__submodule_is_active(int argc, const char **argv)
>  {
>  	struct option options[] = {
> @@ -32,6 +77,7 @@ static int cmd__submodule_is_active(int argc, const char **argv)
>  }
>  
>  static struct test_cmd cmds[] = {
> +	{ "check-name", cmd__submodule_check_name },
>  	{ "is-active", cmd__submodule_is_active },
>  };
>  
> diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
> index 41706c1c9ff..2c24f120da3 100755
> --- a/t/t7450-bad-git-dotfiles.sh
> +++ b/t/t7450-bad-git-dotfiles.sh
> @@ -21,7 +21,7 @@ test_expect_success 'check names' '
>  	valid/with/paths
>  	EOF
>  
> -	git submodule--helper check-name >actual <<-\EOF &&
> +	test-tool submodule check-name >actual <<-\EOF &&
>  	valid
>  	valid/with/paths

Similar to the previous patch, the only tests that use this are
verifying the behavior of "check-name" itself. But I think it makes
sense to keep this one since this seems to have always been intended to
be a sort of "unit test"; it was introduced in 0383bbb901
(submodule-config: verify submodule names as paths, 2018-04-30), and the
commit message indicates that this test protects us against certain
vulnerabilities from maliciously-crafted submodule names.

>  
> -- 
> 2.37.1.1167.g38fda70d8c4

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH 08/20] submodule--helper: move "resolve-relative-url-test" to a test-tool
  2022-07-28 16:16 ` [PATCH 08/20] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
@ 2022-07-29 21:58   ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-07-29 21:58 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> As its name suggests the "resolve-relative-url-test" has never been
> used outside of the test suite, see 63e95beb085 (submodule: port
> resolve_relative_url from shell to C, 2016-04-15) for its original
> addition.

[...]

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>
> diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
> index 1f2007e62b7..68e29c904a6 100755
> --- a/t/t0060-path-utils.sh
> +++ b/t/t0060-path-utils.sh
> @@ -22,7 +22,7 @@ relative_path() {
>  
>  test_submodule_relative_url() {
>  	test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" "
> -		actual=\$(git submodule--helper resolve-relative-url-test '$1' '$2' '$3') &&
> +		actual=\$(test-tool submodule resolve-relative-url '$1' '$2' '$3') &&
>  		test \"\$actual\" = '$4'
>  	"
>  }

It seems like this was only ever intended as a regression test when
porting resolve_relative_url from sh -> C. Unless we see a good reason
to "unit test" resolve_relative_url, I'm ok to drop this test too.

> -- 
> 2.37.1.1167.g38fda70d8c4

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH 14/20] submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
  2022-07-28 16:16 ` [PATCH 14/20] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-07-29 22:09   ` Glen Choo
  2022-08-01 15:05     ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 142+ messages in thread
From: Glen Choo @ 2022-07-29 22:09 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Add "const" to the "struct module_clone_data" that we pass to
> clone_submodule(), which makes the ownership clear, and stops us from
> clobbering the "clone_data->path".
>
> We still need to add to the "reference" member, which is a "struct
> string_list". Let's do this by having clone_submodule() create its
> own, and copy the contents over, allowing us to pass it as a
> separate parameter.

I can't help but think that this would be easier to review as part of
the leaks series since:

- Outside of leaks, I don't think we really care about ownership (though
  please please correct me if I'm off base).

- The ownership of "reference" is still quite messy (downstream code
  might append to it, but its members are sometimes free()-able and
  sometimes not), so it's hard to visualize what we're getting out of
  this change without seeing the corresponding leak fix.

and...

> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 6cedcc5b239..e235acce985 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -1569,18 +1567,20 @@ static char *clone_submodule_sm_gitdir(const char *name)
>  	return sm_gitdir;
>  }
>  
> -static int clone_submodule(struct module_clone_data *clone_data)
> +static int clone_submodule(const struct module_clone_data *clone_data,
> +			   struct string_list *reference)
>  {
>  	char *p;
>  	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
>  	char *sm_alternate = NULL, *error_strategy = NULL;
>  	struct child_process cp = CHILD_PROCESS_INIT;
> +	const char *clone_data_path;
>  
>  	if (!is_absolute_path(clone_data->path))
> -		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
> -					   clone_data->path);
> +		clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
> +					  clone_data->path);

- (this is pretty minor) It feels weird to see that we're intentionally
  leaking clone_data_path at its inception. We aren't introducing any
  new leaks, but moving this to the leaks series makes it clearer that
  we eventually do the right thing.

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH 19/20] submodule--helper: don't exit() on failure, return
  2022-07-28 16:17 ` [PATCH 19/20] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
@ 2022-07-29 22:23   ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-07-29 22:23 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Change code downstream of module_update() to short-circuit and return
> to the top-level on failure, rather than calling exit().
>
> To do so we need to diligently check whether we "must_die_on_failure",
> which is a pattern started in c51f8f94e5b (submodule--helper: run
> update procedures from C, 2021-08-24), but which hadn't been completed
> to the point where we could avoid calling exit() here.
>
> This introduces no functional changes, but makes it easier to both
> call these routines as a library in the future, and to eventually
> avoid leaking memory.
>
> This and similar control flow in submodule--helper.c could be made
> simpler by properly "libifying" it, i.e. to have it consistently
> return -1 on failures, and to early return on any non-success.
>
> But let's leave that larger project for now, and (mostly) emulate what
> were doing with the "exit(128)" before this change.

Thanks! This is a lot clearer. I'm still kind of iffy on this change
though. On the one hand, we know for sure that we're doing the right
thing because we have tests for "git submodule update --recursive". But
on the other, we return 128 from so deep inside the call chain that I
don't think it's easy for a casual reader to convince themselves that
this is indeed the same.

If the "libification" isn't too hard, I'd strongly prefer to have that
now, but since we already have tests in place, I don't feel strongly
enough to block this patch.

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 36 ++++++++++++++++++++++++++----------
>  1 file changed, 26 insertions(+), 10 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 68aa10a26cd..d3f22f03766 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2121,7 +2121,8 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
>  	return run_command(&cp);
>  }
>  
> -static int run_update_command(struct update_data *ud, int subforce)
> +static int run_update_command(struct update_data *ud, int subforce,
> +			      int *must_die_on_failurep)
>  {
>  	struct child_process cp = CHILD_PROCESS_INIT;
>  	char *oid = oid_to_hex(&ud->oid);
> @@ -2183,8 +2184,10 @@ static int run_update_command(struct update_data *ud, int subforce)
>  			BUG("unexpected update strategy type: %s",
>  			    submodule_strategy_to_string(&ud->update_strategy));
>  		}
> -		if (must_die_on_failure)
> -			exit(128);
> +		if (must_die_on_failure) {
> +			*must_die_on_failurep = 1;
> +			return 128;
> +		}
>  
>  		/* the command failed, but update must continue */
>  		return 1;
> @@ -2218,7 +2221,8 @@ static int run_update_command(struct update_data *ud, int subforce)
>  	return 0;
>  }
>  
> -static int run_update_procedure(struct update_data *ud)
> +static int run_update_procedure(struct update_data *ud,
> +				int *must_die_on_failure)
>  {
>  	int subforce = is_null_oid(&ud->suboid) || ud->force;
>  
> @@ -2245,7 +2249,7 @@ static int run_update_procedure(struct update_data *ud)
>  			    ud->displaypath, oid_to_hex(&ud->oid));
>  	}
>  
> -	return run_update_command(ud, subforce);
> +	return run_update_command(ud, subforce, must_die_on_failure);
>  }
>  
>  static const char *remote_submodule_branch(const char *path)
> @@ -2381,7 +2385,8 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
>  				    "--no-single-branch");
>  }
>  
> -static int update_submodule(struct update_data *update_data)
> +static int update_submodule(struct update_data *update_data,
> +			    int *must_die_on_failure)
>  {
>  	int ret = 1;
>  
> @@ -2420,8 +2425,13 @@ static int update_submodule(struct update_data *update_data)
>  	}
>  
>  	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
> -		if (run_update_procedure(update_data))
> +		ret = run_update_procedure(update_data, must_die_on_failure);
> +		if (ret && *must_die_on_failure) {
> +			goto cleanup;
> +		} else if (ret) {
> +			ret = 1;
>  			goto cleanup;
> +		}
>  	}
>  
>  	if (update_data->recursive) {
> @@ -2444,7 +2454,8 @@ static int update_submodule(struct update_data *update_data)
>  		die_message(_("Failed to recurse into submodule path '%s'"),
>  			    update_data->displaypath);
>  		if (ret == 128) {
> -			exit(ret);
> +			*must_die_on_failure = 1;
> +			goto cleanup;
>  		} else if (ret) {
>  			ret = 1;
>  			goto cleanup;
> @@ -2482,13 +2493,18 @@ static int update_submodules(struct update_data *update_data)
>  
>  	for (i = 0; i < suc.update_clone_nr; i++) {
>  		struct update_clone_data ucd = suc.update_clone[i];
> +		int code;
> +		int must_die_on_failure = 0;
>  
>  		oidcpy(&update_data->oid, &ucd.oid);
>  		update_data->just_cloned = ucd.just_cloned;
>  		update_data->sm_path = ucd.sub->path;
>  
> -		if (update_submodule(update_data))
> -			res = 1;
> +		code = update_submodule(update_data, &must_die_on_failure);
> +		if (code)
> +			res = code;
> +		if (must_die_on_failure)
> +			goto cleanup;
>  	}
>  
>  cleanup:
> -- 
> 2.37.1.1167.g38fda70d8c4

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (19 preceding siblings ...)
  2022-07-28 16:17 ` [PATCH 20/20] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
@ 2022-07-29 22:52 ` Glen Choo
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  22 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-07-29 22:52 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> This new series based on "master" splits out the non-leak fixes from
> v3 of the submodule leaks series [1]. Sorry about the churn, but with
> e.g. the thread at [2] the "leaks" series was accumulating a lot of
> non-leaks related fixes, just so that we could get to the point of
> fixing various leaks.
>
> The immediate reason I split this off was because of the new
> "remove..helper" and "test-tool" patches here. I.e. some things that
> the leaks series was changing was test-only code, or code that was
> simply unused (or we had no business using anymore).
>
> The [1] series will then be re-rolled on top of this series, which
> will hopefully make it a lot easier to digest, as it'll now *just*
> focus on leak fixes.


Thanks! I was worried about the churn at first, but most of these
patches are just the ones we already reviewed in previous versions, and
the leaks series looks a lot easier to review.

I left the bigger comments in-thread. Some themes I saw in the patches:

>   submodule tests: test usage behavior
>   submodule tests: test for "add <repository> <abs-path>"

I assume these tests are meant for catching regressions?

>   submodule--helper: remove unused "name" helper
>   submodule--helper: remove unused "list" helper

Hooray for rm-ing dead code!

>   test-tool submodule-config: remove unused "--url" handling
>   submodule--helper: move "is-active" to a test-tool
>   submodule--helper: move "check-name" to a test-tool
>   submodule--helper: move "resolve-relative-url-test" to a test-tool

Each of these commands are only used in _their own_ tests as opposed to
be used in tests for _other_ commands (or, to borrow the language of
garbage collection, the only references we have are weak references ;)),
which makes me think that we could:

a) be more ruthless in considering these dead code
b) be more explicit in calling them "unit tests"
c) (somewhere down the line) absorb them into the rest of the test suite
instead of creating a special testing escape hatch.

>   submodule--helper: add "const" to copy of "update_data"
>   submodule--helper: pass a "const struct module_clone_data" to
>     clone_submodule()

I suspect these changes to ownership make more sense in the leaks
series. For the former patch, it would explain why we don't have to
plug leaks in "update_data". For latter, the ownership rules are still a
bit confusing (for historical reasons, not anything you introduced), so
the leak fix might help explain why the new ownership is better than
what we had before.

>   submodule--helper: stop conflating "sb" in clone_submodule()
>   submodule--helper: add skeleton "goto cleanup" to update_submodule()
>   submodule--helper: don't exit() on failure, return

IMO this refactoring doesn't really stand on its own unless we also take
the leaks fixes. Might be nice to move these to that series, but I don't
feel strongly about it.

>   submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
>   submodule--helper style: don't separate declared variables with \n\n
>   submodule--helper style: add \n\n after variable declarations
>   submodule--helper: rename "int res" to "int ret"
>   submodule--helper: replace memset() with { 0 }-initialization
>   submodule--helper: convert a strbuf_detach() to xstrfmt()
>   submodule--helper: fix bad config API usage

Style and API fixes that make sense on their own :)

Since we now have an extra topic for cleanup, I wonder what you think
about incorporating [1], i.e. refactor out init_submodules() to be
called from module_update(). It's a bit big, but it would make [2]
obsolete.

[1] https://lore.kernel.org/git/kl6lbktitf6e.fsf@chooglen-macbookpro.roam.corp.google.com
[2] https://lore.kernel.org/git/patch-v4-04.17-683d327752f-20220728T162442Z-avarab@gmail.com

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH 14/20] submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
  2022-07-29 22:09   ` Glen Choo
@ 2022-08-01 15:05     ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-01 15:05 UTC (permalink / raw)
  To: Glen Choo; +Cc: git, Junio C Hamano, Atharva Raykar, Prathamesh Chavan


On Fri, Jul 29 2022, Glen Choo wrote:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> Add "const" to the "struct module_clone_data" that we pass to
>> clone_submodule(), which makes the ownership clear, and stops us from
>> clobbering the "clone_data->path".
>>
>> We still need to add to the "reference" member, which is a "struct
>> string_list". Let's do this by having clone_submodule() create its
>> own, and copy the contents over, allowing us to pass it as a
>> separate parameter.
>
> I can't help but think that this would be easier to review as part of
> the leaks series since:
>
> - Outside of leaks, I don't think we really care about ownership (though
>   please please correct me if I'm off base).
>
> - The ownership of "reference" is still quite messy (downstream code
>   might append to it, but its members are sometimes free()-able and
>   sometimes not), so it's hard to visualize what we're getting out of
>   this change without seeing the corresponding leak fix.

I'll amend the commit message. I'll leave this in this series, as
starting to split "is this really just for the leak fix?" out of this
will generally lead to the slippery slope of bundling most of this up
again.

I think the addition of "const" helps things along independently of
that.

>> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
>> index 6cedcc5b239..e235acce985 100644
>> --- a/builtin/submodule--helper.c
>> +++ b/builtin/submodule--helper.c
>> @@ -1569,18 +1567,20 @@ static char *clone_submodule_sm_gitdir(const char *name)
>>  	return sm_gitdir;
>>  }
>>  
>> -static int clone_submodule(struct module_clone_data *clone_data)
>> +static int clone_submodule(const struct module_clone_data *clone_data,
>> +			   struct string_list *reference)
>>  {
>>  	char *p;
>>  	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
>>  	char *sm_alternate = NULL, *error_strategy = NULL;
>>  	struct child_process cp = CHILD_PROCESS_INIT;
>> +	const char *clone_data_path;
>>  
>>  	if (!is_absolute_path(clone_data->path))
>> -		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
>> -					   clone_data->path);
>> +		clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
>> +					  clone_data->path);
>
> - (this is pretty minor) It feels weird to see that we're intentionally
>   leaking clone_data_path at its inception. We aren't introducing any
>   new leaks, but moving this to the leaks series makes it clearer that
>   we eventually do the right thing.

Here we're just preserving the status quo, memory leaks aren't really
tied to variable scope (except as a reporting convenience in some
tools). We're leaking in the same way before & after this. I think it's
better to fix the leak in the follow-up series to separate the concerns
here.

^ permalink raw reply	[flat|nested] 142+ messages in thread

* [PATCH v2 00/28] submodule--helper: add tests, rm dead code, refactor & leak prep
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (20 preceding siblings ...)
  2022-07-29 22:52 ` [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Glen Choo
@ 2022-08-02 15:45 ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 01/28] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
                     ` (27 more replies)
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  22 siblings, 28 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

This series is a "prep" series for the meaty leak fixes for
submodule--helper, see [1] (which will be re-rolled on top of this
v2).

Change since v1:

 * This hopefully addresses all of Glen's comments on v1.

 * The "libification" of "update" suggested in [2] is (almost)
   complete here. See 27/28 for the "almost". This is why the series
   grew from 20 to 28 patches.

   There's a lot of incremental "showing work" here.

 * The "goto cleanup" in update_submodule() change is gone, it's
   needed for the current v4 of the follow-up, but I'll submit a
   re-roll which solves that problem in a cleaner way.

   For this series it means we can end up with just a "return
   die_message(...)" rather than "ret = die_message(...); goto
   cleanup" in that code, which is a lot less verbose.

 * Various other small changes, see the range-diff below.

A CI run for this & branch is at [3].

1. https://lore.kernel.org/git/cover-v4-00.17-00000000000-20220728T162442Z-avarab@gmail.com/
2. https://lore.kernel.org/git/kl6lilnfr22i.fsf@chooglen-macbookpro.roam.corp.google.com/
3. https://github.com/avar/git/tree/avar/submodule--helper-cleanup-and-tests-2

Glen Choo (2):
  submodule--helper: add "const" to copy of "update_data"
  submodule--helper: refactor "errmsg_str" to be a "struct strbuf"

Ævar Arnfjörð Bjarmason (26):
  submodule tests: test usage behavior
  submodule tests: test for "add <repository> <abs-path>"
  submodule--helper: remove unused "name" helper
  submodule--helper: remove unused "list" helper
  test-tool submodule-config: remove unused "--url" handling
  submodule--helper: move "is-active" to a test-tool
  submodule--helper: move "check-name" to a test-tool
  submodule--helper: move "resolve-relative-url-test" to a test-tool
  submodule--helper style: don't separate declared variables with \n\n
  submodule--helper style: add \n\n after variable declarations
  submodule--helper: replace memset() with { 0 }-initialization
  submodule--helper: use xstrfmt() in clone_submodule()
  submodule--helper: move "sb" in clone_submodule() to its own scope
  submodule--helper: pass a "const struct module_clone_data" to
    clone_submodule()
  submodule--helper: don't redundantly check "else if (res)"
  submodule--helper: rename "int res" to "int ret"
  submodule--helper: return "ret", not "1" from update_submodule()
  submodule--helper: add missing braces to "else" arm
  submodule--helper: don't call submodule_strategy_to_string() in BUG()
  submodule--helper: move submodule_strategy_to_string() to only user
  submodule--helper: use "code" in run_update_command()
  submodule--helper: don't exit() on failure, return
  submodule--helper: libify determine_submodule_update_strategy()
  submodule--helper: libify "must_die_on_failure" code paths
  submodule--helper: libify "must_die_on_failure" code paths (for die)
  submodule--helper: fix bad config API usage

 Makefile                         |   1 +
 builtin/submodule--helper.c      | 451 +++++++++++++------------------
 submodule.c                      |  21 --
 submodule.h                      |   1 -
 t/helper/test-submodule-config.c |  11 +-
 t/helper/test-submodule.c        | 146 ++++++++++
 t/helper/test-tool-utils.h       |   9 +
 t/helper/test-tool.c             |   7 +-
 t/helper/test-tool.h             |   1 +
 t/t0060-path-utils.sh            |   2 +-
 t/t7400-submodule-basic.sh       |  56 ++--
 t/t7406-submodule-update.sh      |   2 +-
 t/t7413-submodule-is-active.sh   |  35 +--
 t/t7450-bad-git-dotfiles.sh      |   2 +-
 14 files changed, 403 insertions(+), 342 deletions(-)
 create mode 100644 t/helper/test-submodule.c
 create mode 100644 t/helper/test-tool-utils.h

Range-diff against v1:
 1:  84b05bda016 !  1:  daa5d3f9962 submodule tests: test usage behavior
    @@ Commit message
         subsequent eventual behavior change will become clear.
     
         For "--" this follows up on 68cabbfda36 (submodule: document default
    -    behavior, 2019-02-15) and tests that when "status" isn't supplied we
    -    don't support the "--" delimiter. There's no intrinsically good reason
    -    not to support that. We behave this way due to edge cases in
    +    behavior, 2019-02-15) and tests that "status" doesn't don't support
    +    the "--" delimiter. There's no intrinsically good reason not to
    +    support that. We behave this way due to edge cases in
         git-submodule.sh's implementation, but as with "-h" let's assert our
         current long-standing behavior for now.
     
 2:  9671169e348 =  2:  9d920326df3 submodule tests: test for "add <repository> <abs-path>"
 3:  7aa9c14251b =  3:  d981db49fa1 submodule--helper: remove unused "name" helper
 4:  27df2efe718 =  4:  6f78f9c9274 submodule--helper: remove unused "list" helper
 5:  9fe8deb165a =  5:  43902201701 test-tool submodule-config: remove unused "--url" handling
 6:  8e4d2b09d56 !  6:  e2a8bb0a28e submodule--helper: move "is-active" to a test-tool
    @@ t/t7413-submodule-is-active.sh
     -This test verifies that `git submodue--helper is-active` correctly identifies
     +This test verifies that `test-tool submodule is-active` correctly identifies
      submodules which are "active" and interesting to the user.
    ++
    ++This is a unit test of the submodule.c is_submodule_active() function,
    ++which is also indirectly tested elsewhere.
      '
      
    + . ./test-lib.sh
     @@ t/t7413-submodule-is-active.sh: test_expect_success 'setup' '
      '
      
 7:  a2f3d812815 !  7:  b209532eb17 submodule--helper: move "check-name" to a test-tool
    @@ Commit message
         a6226fd772b (submodule--helper: convert the bulk of cmd_add() to C,
         2021-08-10) it has only been used by this test, not git-submodule.sh.
     
    +    As noted with its introduction in 0383bbb9015 (submodule-config:
    +    verify submodule names as paths, 2018-04-30) the intent of
    +    t7450-bad-git-dotfiles.sh has always been to unit test the
    +    check_submodule_name() function.
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
 8:  8188657cdfa !  8:  de49f31dab0 submodule--helper: move "resolve-relative-url-test" to a test-tool
    @@ Commit message
         resolve_relative_url from shell to C, 2016-04-15) for its original
         addition.
     
    +    Perhaps it would make sense to drop this code entirely, as we feel
    +    that we've got enough indirect test coverage, but let's leave that
    +    question to a possible follow-up change. For now let's keep the test
    +    coverage this gives us.
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
 9:  79a47f9b94d =  9:  b0238f699ce submodule--helper style: don't separate declared variables with \n\n
10:  5e13080f894 = 10:  5f5e68a868b submodule--helper style: add \n\n after variable declarations
11:  dc5ac924496 = 11:  72dcf19e1c4 submodule--helper: replace memset() with { 0 }-initialization
12:  08cc9ce2e24 ! 12:  e5e267dccd5 submodule--helper: convert a strbuf_detach() to xstrfmt()
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    submodule--helper: convert a strbuf_detach() to xstrfmt()
    +    submodule--helper: use xstrfmt() in clone_submodule()
     
    -    Convert a case where we had no reason to use a "struct strbuf" to use
    -    an xstrfmt(). This code was added along with other uses of "struct
    +    Use xstrfmt() in clone_submodule() instead of a "struct strbuf" in two
    +    cases where we weren't getting anything out of using the "struct
    +    strbuf".
    +
    +    This changes code that was was added along with other uses of "struct
         strbuf" in this function in ee8838d1577 (submodule: rewrite
         `module_clone` shell function in C, 2015-09-08).
     
    @@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data
      
      	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
      		die(_("refusing to create/use '%s' in another submodule's "
    +@@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data *clone_data)
    + 			die(_("clone of '%s' into submodule path '%s' failed"),
    + 			    clone_data->url, clone_data->path);
    + 	} else {
    ++		char *path;
    ++
    + 		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
    + 		    !is_empty_dir(clone_data->path))
    + 			die(_("directory not empty: '%s'"), clone_data->path);
    + 		if (safe_create_leading_directories_const(clone_data->path) < 0)
    + 			die(_("could not create directory '%s'"), clone_data->path);
    +-		strbuf_addf(&sb, "%s/index", sm_gitdir);
    +-		unlink_or_warn(sb.buf);
    +-		strbuf_reset(&sb);
    ++		path = xstrfmt("%s/index", sm_gitdir);
    ++		unlink_or_warn(path);
    ++		free(path);
    + 	}
    + 
    + 	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
13:  afe34d8b73b ! 13:  91558745e2e submodule--helper: stop conflating "sb" in clone_submodule()
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    submodule--helper: stop conflating "sb" in clone_submodule()
    +    submodule--helper: move "sb" in clone_submodule() to its own scope
     
    -    Refactor the two uses of a "struct strbuf sb" such that each of them
    -    exists in its own scope. This makes the control flow clearer.
    +    Refactor the only remaining use of a "struct strbuf sb" in
    +    clone_submodule() to live in its own scope. This makes the code
    +    clearer by limiting its lifetime.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ builtin/submodule--helper.c: static void prepare_possible_alternates(const char
      
      	if (!is_absolute_path(clone_data->path))
      		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
    -@@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data *clone_data)
    - 			die(_("clone of '%s' into submodule path '%s' failed"),
    - 			    clone_data->url, clone_data->path);
    - 	} else {
    -+		struct strbuf sb = STRBUF_INIT;
    -+
    - 		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
    - 		    !is_empty_dir(clone_data->path))
    - 			die(_("directory not empty: '%s'"), clone_data->path);
    -@@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data *clone_data)
    - 			die(_("could not create directory '%s'"), clone_data->path);
    - 		strbuf_addf(&sb, "%s/index", sm_gitdir);
    - 		unlink_or_warn(sb.buf);
    --		strbuf_reset(&sb);
    -+		strbuf_release(&sb);
    - 	}
    - 
    - 	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
     @@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data *clone_data)
      	free(sm_alternate);
      	free(error_strategy);
14:  b364f3200d8 ! 14:  866b8397a59 submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
    @@ Commit message
         This new "struct string_list" still leaks memory, just as the "struct
         module_clone_data" did before. let's not fix that for now, to fix that
         we'll need to add some "goto cleanup" to the relevant code. That will
    -    be done in a follow-up commits, at that point it'll be easier to fix
    -    the memory leak.
    +    eventually be done in follow-up commits, this change makes it easier
    +    to fix the memory leak.
     
         The scope of the new "reference" variable in add_submodule() could be
         narrowed to the "else" block, but as we'll eventually free it with a
    @@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data
     -			    clone_data->url, clone_data->path);
     +			    clone_data->url, clone_data_path);
      	} else {
    - 		struct strbuf sb = STRBUF_INIT;
    + 		char *path;
      
     -		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
     -		    !is_empty_dir(clone_data->path))
    @@ builtin/submodule--helper.c: static int clone_submodule(struct module_clone_data
     +			die(_("directory not empty: '%s'"), clone_data_path);
     +		if (safe_create_leading_directories_const(clone_data_path) < 0)
     +			die(_("could not create directory '%s'"), clone_data_path);
    - 		strbuf_addf(&sb, "%s/index", sm_gitdir);
    - 		unlink_or_warn(sb.buf);
    - 		strbuf_release(&sb);
    + 		path = xstrfmt("%s/index", sm_gitdir);
    + 		unlink_or_warn(path);
    + 		free(path);
      	}
      
     -	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
15:  e319f4edc54 = 15:  1ff380ec7b5 submodule--helper: add "const" to copy of "update_data"
16:  68202100d9a = 16:  d3a7e646adc submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
 -:  ----------- > 17:  23eb07176d9 submodule--helper: don't redundantly check "else if (res)"
17:  e8aacb55a18 ! 18:  78f74df6d5e submodule--helper: rename "int res" to "int ret"
    @@ Commit message
         cmd_update() logic to C, 2022-03-15) to "ret", which is the convention
         in the rest of this file.
     
    -    Eventual follow-up commits will change this code to a "goto cleanup"
    -    pattern, let's have the post image look consistent with the rest.
    +    Eventual follow-up commits will change the code in update_submodule()
    +    to a "goto cleanup" pattern, let's have the post image look consistent
    +    with the rest. For update_submodules() let's also use a "ret" for
    +    consistency, that use was also added in b3c5f5cb048. We'll be
    +    modifying that codepath in subsequent commits.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *upd
      			    update_data->displaypath);
     -		if (res == 128)
     -			exit(res);
    --		else if (res)
     +		if (ret == 128)
     +			exit(ret);
    -+		else if (ret)
    - 			return 1;
    + 		return 1;
      	}
      
    +@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
    + 
    + static int update_submodules(struct update_data *update_data)
    + {
    +-	int i, res = 0;
    ++	int i, ret = 0;
    + 	struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
    + 
    + 	suc.update_data = update_data;
    +@@ builtin/submodule--helper.c: static int update_submodules(struct update_data *update_data)
    + 	 * - the listener can avoid doing any work if fetching failed.
    + 	 */
    + 	if (suc.quickstop) {
    +-		res = 1;
    ++		ret = 1;
    + 		goto cleanup;
    + 	}
    + 
    +@@ builtin/submodule--helper.c: static int update_submodules(struct update_data *update_data)
    + 		update_data->sm_path = ucd.sub->path;
    + 
    + 		if (update_submodule(update_data))
    +-			res = 1;
    ++			ret = 1;
    + 	}
    + 
    + cleanup:
    + 	string_list_clear(&update_data->references, 0);
    +-	return res;
    ++	return ret;
    + }
    + 
    + static int module_update(int argc, const char **argv, const char *prefix)
18:  41fb22d8549 <  -:  ----------- submodule--helper: add skeleton "goto cleanup" to update_submodule()
 -:  ----------- > 19:  f0258e37ebe submodule--helper: return "ret", not "1" from update_submodule()
 -:  ----------- > 20:  70f030cca4e submodule--helper: add missing braces to "else" arm
 -:  ----------- > 21:  bce1a014a2f submodule--helper: don't call submodule_strategy_to_string() in BUG()
 -:  ----------- > 22:  98c3e562c82 submodule--helper: move submodule_strategy_to_string() to only user
 -:  ----------- > 23:  db2d2fb5a21 submodule--helper: use "code" in run_update_command()
19:  5a26c9428be ! 24:  d33260487bd submodule--helper: don't exit() on failure, return
    @@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_pa
      
     -static int run_update_command(struct update_data *ud, int subforce)
     +static int run_update_command(struct update_data *ud, int subforce,
    -+			      int *must_die_on_failurep)
    ++			      int *must_die_on_failure)
      {
      	struct child_process cp = CHILD_PROCESS_INIT;
      	char *oid = oid_to_hex(&ud->oid);
     @@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    - 			BUG("unexpected update strategy type: %s",
    - 			    submodule_strategy_to_string(&ud->update_strategy));
      		}
    --		if (must_die_on_failure)
    --			exit(128);
    -+		if (must_die_on_failure) {
    -+			*must_die_on_failurep = 1;
    -+			return 128;
    -+		}
    - 
    - 		/* the command failed, but update must continue */
    - 		return 1;
    + 
    + 		if (ret == 128)
    +-			exit(ret);
    ++			*must_die_on_failure = 1;
    + 		return ret;
    + 	}
    + 
     @@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
      	return 0;
      }
    @@ builtin/submodule--helper.c: static void update_data_to_args(struct update_data
     +static int update_submodule(struct update_data *update_data,
     +			    int *must_die_on_failure)
      {
    - 	int ret = 1;
    + 	ensure_core_worktree(update_data->sm_path);
      
     @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
    + 		free(remote_ref);
      	}
      
    - 	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
    +-	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force)
     -		if (run_update_procedure(update_data))
    ++	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
    ++		int ret;
    ++
     +		ret = run_update_procedure(update_data, must_die_on_failure);
    -+		if (ret && *must_die_on_failure) {
    -+			goto cleanup;
    -+		} else if (ret) {
    -+			ret = 1;
    - 			goto cleanup;
    -+		}
    - 	}
    ++		if (*must_die_on_failure)
    ++			return ret;
    ++		if (ret)
    + 			return 1;
    ++	}
      
      	if (update_data->recursive) {
    + 		struct child_process cp = CHILD_PROCESS_INIT;
     @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
      		die_message(_("Failed to recurse into submodule path '%s'"),
      			    update_data->displaypath);
    - 		if (ret == 128) {
    + 		if (ret == 128)
     -			exit(ret);
     +			*must_die_on_failure = 1;
    -+			goto cleanup;
    - 		} else if (ret) {
    - 			ret = 1;
    - 			goto cleanup;
    + 		return ret;
    + 	}
    + 
     @@ builtin/submodule--helper.c: static int update_submodules(struct update_data *update_data)
      
      	for (i = 0; i < suc.update_clone_nr; i++) {
      		struct update_clone_data ucd = suc.update_clone[i];
    -+		int code;
     +		int must_die_on_failure = 0;
    ++		int code;
      
      		oidcpy(&update_data->oid, &ucd.oid);
      		update_data->just_cloned = ucd.just_cloned;
      		update_data->sm_path = ucd.sub->path;
      
     -		if (update_submodule(update_data))
    --			res = 1;
     +		code = update_submodule(update_data, &must_die_on_failure);
     +		if (code)
    -+			res = code;
    ++			ret = code;
     +		if (must_die_on_failure)
     +			goto cleanup;
    ++		else if (code)
    + 			ret = 1;
      	}
      
    - cleanup:
 -:  ----------- > 25:  9981a75d7e8 submodule--helper: libify determine_submodule_update_strategy()
 -:  ----------- > 26:  b48705c6cc0 submodule--helper: libify "must_die_on_failure" code paths
 -:  ----------- > 27:  93cd1ccde54 submodule--helper: libify "must_die_on_failure" code paths (for die)
20:  579560cb9a8 = 28:  6160a1ab250 submodule--helper: fix bad config API usage
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply	[flat|nested] 142+ messages in thread

* [PATCH v2 01/28] submodule tests: test usage behavior
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 22:30     ` Glen Choo
  2022-08-02 15:45   ` [PATCH v2 02/28] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
                     ` (26 subsequent siblings)
  27 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Test what exit code and output we emit on "git submodule -h", how we
handle "--" when no subcommand is specified, and how the top-level
"--recursive" option is handled.

For "-h" this doesn't make sense, but let's test for it so that any
subsequent eventual behavior change will become clear.

For "--" this follows up on 68cabbfda36 (submodule: document default
behavior, 2019-02-15) and tests that "status" doesn't don't support
the "--" delimiter. There's no intrinsically good reason not to
support that. We behave this way due to edge cases in
git-submodule.sh's implementation, but as with "-h" let's assert our
current long-standing behavior for now.

For "--recursive" the exclusion of it from the top-level appears to
have been an omission in 15fc56a8536 (git submodule foreach: Add
--recursive to recurse into nested submodules, 2009-08-19), there
doesn't seem to be a reason not to support it alongside "--quiet" and
"--cached", but let's likewise assert our existing behavior for now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t7400-submodule-basic.sh | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index e7cec2e457a..b858871a953 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -14,6 +14,32 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./test-lib.sh
 
+test_expect_success 'submodule usage: -h' '
+	git submodule -h >out 2>err &&
+	grep "^usage: git submodule" out &&
+	test_must_be_empty err
+'
+
+test_expect_success 'submodule usage: --recursive' '
+	test_expect_code 1 git submodule --recursive >out 2>err &&
+	grep "^usage: git submodule" err &&
+	test_must_be_empty out
+'
+
+test_expect_success 'submodule usage: status --' '
+	test_expect_code 1 git submodule -- &&
+	test_expect_code 1 git submodule --end-of-options
+'
+
+for opt in '--quiet' '--cached'
+do
+	test_expect_success "submodule usage: status $opt" '
+		git submodule $opt &&
+		git submodule status $opt &&
+		git submodule $opt status
+	'
+done
+
 test_expect_success 'submodule deinit works on empty repository' '
 	git submodule deinit --all
 '
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 02/28] submodule tests: test for "add <repository> <abs-path>"
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 01/28] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 03/28] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
                     ` (25 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add a missing test for ""add <repository> <path>" where "<path>" is an
absolute path. This tests code added in [1] and later turned into an
"else" branch in clone_submodule() in [2] that's never been tested.

This needs to be skipped on WINDOWS because all of $PWD, $(pwd) and
the "$(pwd -P)" we get via "$submodurl" would fail in CI with e.g.:

	fatal: could not create directory 'D:/a/git/git/t/trash
	directory.t7400-submodule-basic/.git/modules/D:/a/git/git/t/trash
	directory.t7400-submodule-basic/add-abs'

I.e. we can't handle these sorts of paths in this context on that
platform.

I'm not sure where we run into the edges of "$PWD" behavior on
Windows (see [1] for a previous loose end on the topic), but for the
purposes of this test it's sufficient that we test this on other
platforms.

1. ee8838d1577 (submodule: rewrite `module_clone` shell function in C,
   2015-09-08)
2. f8eaa0ba98b (submodule--helper, module_clone: always operate on
   absolute paths, 2016-03-31)

1. https://lore.kernel.org/git/220630.86edz6c75c.gmgdl@evledraar.gmail.com/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t7400-submodule-basic.sh | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index b858871a953..6a77d817a82 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -178,6 +178,11 @@ test_expect_success 'submodule add' '
 	test_must_be_empty untracked
 '
 
+test_expect_success !WINDOWS 'submodule add (absolute path)' '
+	test_when_finished "git reset --hard" &&
+	git submodule add "$submodurl" "$submodurl/add-abs"
+'
+
 test_expect_success 'setup parent and one repository' '
 	test_create_repo parent &&
 	test_commit -C parent one
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 03/28] submodule--helper: remove unused "name" helper
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 01/28] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 02/28] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 04/28] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
                     ` (24 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The "name" helper has not been used since e83e3333b57 (submodule: port
submodule subcommand 'summary' from shell to C, 2020-08-13).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fac52ade5e1..ac2553ba9d3 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -771,24 +771,6 @@ static int module_status(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static int module_name(int argc, const char **argv, const char *prefix)
-{
-	const struct submodule *sub;
-
-	if (argc != 2)
-		usage(_("git submodule--helper name <path>"));
-
-	sub = submodule_from_path(the_repository, null_oid(), argv[1]);
-
-	if (!sub)
-		die(_("no submodule mapping found in .gitmodules for path '%s'"),
-		    argv[1]);
-
-	printf("%s\n", sub->name);
-
-	return 0;
-}
-
 struct module_cb {
 	unsigned int mod_src;
 	unsigned int mod_dst;
@@ -3359,7 +3341,6 @@ struct cmd_struct {
 
 static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
-	{"name", module_name, 0},
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 04/28] submodule--helper: remove unused "list" helper
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (2 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 03/28] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 05/28] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
                     ` (23 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Remove the "submodule--helper list" sub-command, which hasn't been
used by git-submodule.sh since 2964d6e5e1e (submodule: port subcommand
'set-branch' from shell to C, 2020-06-02).

There was a test added in 2b56bb7a87a (submodule helper list: respect
correct path prefix, 2016-02-24) which relied on it, but the right
thing to do here is to delete that test as well.

That test was regression testing the "list" subcommand itself. We're
not getting anything useful from the "list | cut -f2" invocation that
we couldn't get from "foreach 'echo $sm_path'".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 40 -------------------------------------
 t/t7400-submodule-basic.sh  | 25 -----------------------
 2 files changed, 65 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index ac2553ba9d3..47ed24c6a60 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -266,45 +266,6 @@ static char *get_up_path(const char *path)
 	return strbuf_detach(&sb, NULL);
 }
 
-static int module_list(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-
-	struct option module_list_options[] = {
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper list [--prefix=<path>] [<path>...]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_list_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	for (i = 0; i < list.nr; i++) {
-		const struct cache_entry *ce = list.entries[i];
-
-		if (ce_stage(ce))
-			printf("%06o %s U\t", ce->ce_mode,
-			       oid_to_hex(null_oid()));
-		else
-			printf("%06o %s %d\t", ce->ce_mode,
-			       oid_to_hex(&ce->oid), ce_stage(ce));
-
-		fprintf(stdout, "%s\n", ce->name);
-	}
-	return 0;
-}
-
 static void for_each_listed_submodule(const struct module_list *list,
 				      each_submodule_fn fn, void *cb_data)
 {
@@ -3340,7 +3301,6 @@ struct cmd_struct {
 };
 
 static struct cmd_struct commands[] = {
-	{"list", module_list, 0},
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 6a77d817a82..b50db3f1031 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -1255,31 +1255,6 @@ test_expect_success 'submodule add clone shallow submodule' '
 	)
 '
 
-test_expect_success 'submodule helper list is not confused by common prefixes' '
-	mkdir -p dir1/b &&
-	(
-		cd dir1/b &&
-		git init &&
-		echo hi >testfile2 &&
-		git add . &&
-		git commit -m "test1"
-	) &&
-	mkdir -p dir2/b &&
-	(
-		cd dir2/b &&
-		git init &&
-		echo hello >testfile1 &&
-		git add .  &&
-		git commit -m "test2"
-	) &&
-	git submodule add /dir1/b dir1/b &&
-	git submodule add /dir2/b dir2/b &&
-	git commit -m "first submodule commit" &&
-	git submodule--helper list dir1/b | cut -f 2 >actual &&
-	echo "dir1/b" >expect &&
-	test_cmp expect actual
-'
-
 test_expect_success 'setup superproject with submodules' '
 	git init sub1 &&
 	test_commit -C sub1 test &&
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 05/28] test-tool submodule-config: remove unused "--url" handling
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (3 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 04/28] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 06/28] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
                     ` (22 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

No test has used this "--url" parameter since the test code that made
use of it was removed in 32bc548329d (submodule-config: remove support
for overlaying repository config, 2017-08-03).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/helper/test-submodule-config.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index e2692746dfd..22a41c40926 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -15,14 +15,11 @@ int cmd__submodule_config(int argc, const char **argv)
 {
 	const char **arg = argv;
 	int my_argc = argc;
-	int output_url = 0;
 	int lookup_name = 0;
 
 	arg++;
 	my_argc--;
 	while (arg[0] && starts_with(arg[0], "--")) {
-		if (!strcmp(arg[0], "--url"))
-			output_url = 1;
 		if (!strcmp(arg[0], "--name"))
 			lookup_name = 1;
 		arg++;
@@ -57,12 +54,8 @@ int cmd__submodule_config(int argc, const char **argv)
 		if (!submodule)
 			die_usage(argc, argv, "Submodule not found.");
 
-		if (output_url)
-			printf("Submodule url: '%s' for path '%s'\n",
-					submodule->url, submodule->path);
-		else
-			printf("Submodule name: '%s' for path '%s'\n",
-					submodule->name, submodule->path);
+		printf("Submodule name: '%s' for path '%s'\n", submodule->name,
+		       submodule->path);
 
 		arg += 2;
 	}
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 06/28] submodule--helper: move "is-active" to a test-tool
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (4 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 05/28] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 07/28] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
                     ` (21 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Create a new "test-tool submodule" and move the "is-active" subcommand
over to it. It was added in 5c2bd8b77ae (submodule--helper: add
is-active subcommand, 2017-03-16), since
a452128a36c (submodule--helper: introduce add-config subcommand,
2021-08-06) it hasn't been used by git-submodule.sh.

Since we're creating a command dispatch similar to test-tool.c itself
let's split out the "struct test_cmd" into a new test-tool-utils.h,
which both this new code and test-tool.c itself can use.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Makefile                       |  1 +
 builtin/submodule--helper.c    |  9 ------
 t/helper/test-submodule.c      | 58 ++++++++++++++++++++++++++++++++++
 t/helper/test-tool-utils.h     |  9 ++++++
 t/helper/test-tool.c           |  7 ++--
 t/helper/test-tool.h           |  1 +
 t/t7413-submodule-is-active.sh | 35 ++++++++++----------
 7 files changed, 90 insertions(+), 30 deletions(-)
 create mode 100644 t/helper/test-submodule.c
 create mode 100644 t/helper/test-tool-utils.h

diff --git a/Makefile b/Makefile
index 1624471badc..ad7fbd36885 100644
--- a/Makefile
+++ b/Makefile
@@ -785,6 +785,7 @@ TEST_BUILTINS_OBJS += test-strcmp-offset.o
 TEST_BUILTINS_OBJS += test-string-list.o
 TEST_BUILTINS_OBJS += test-submodule-config.o
 TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
+TEST_BUILTINS_OBJS += test-submodule.o
 TEST_BUILTINS_OBJS += test-subprocess.o
 TEST_BUILTINS_OBJS += test-trace2.o
 TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 47ed24c6a60..b2fc732b5d8 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2728,14 +2728,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static int is_active(int argc, const char **argv, const char *prefix)
-{
-	if (argc != 2)
-		die("submodule--helper is-active takes exactly 1 argument");
-
-	return !is_submodule_active(the_repository, argv[1]);
-}
-
 /*
  * Exit non-zero if any of the submodule names given on the command line is
  * invalid. If no names are given, filter stdin to print only valid names
@@ -3313,7 +3305,6 @@ static struct cmd_struct commands[] = {
 	{"summary", module_summary, 0},
 	{"push-check", push_check, 0},
 	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
-	{"is-active", is_active, 0},
 	{"check-name", check_name, 0},
 	{"config", module_config, 0},
 	{"set-url", module_set_url, 0},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
new file mode 100644
index 00000000000..494c6558d9f
--- /dev/null
+++ b/t/helper/test-submodule.c
@@ -0,0 +1,58 @@
+#include "test-tool.h"
+#include "test-tool-utils.h"
+#include "cache.h"
+#include "parse-options.h"
+#include "submodule.h"
+
+#define TEST_TOOL_IS_ACTIVE_USAGE \
+	"test-tool submodule is-active <name>"
+static const char *submodule_is_active_usage[] = {
+	TEST_TOOL_IS_ACTIVE_USAGE,
+	NULL
+};
+
+static const char *submodule_usage[] = {
+	TEST_TOOL_IS_ACTIVE_USAGE,
+	NULL
+};
+
+static int cmd__submodule_is_active(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_is_active_usage, 0);
+	if (argc != 1)
+		usage_with_options(submodule_is_active_usage, options);
+
+	setup_git_directory();
+
+	return !is_submodule_active(the_repository, argv[0]);
+}
+
+static struct test_cmd cmds[] = {
+	{ "is-active", cmd__submodule_is_active },
+};
+
+int cmd__submodule(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	size_t i;
+
+	argc = parse_options(argc, argv, "test-tools", options, submodule_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (argc < 1)
+		usage_with_options(submodule_usage, options);
+
+	for (i = 0; i < ARRAY_SIZE(cmds); i++)
+		if (!strcmp(cmds[i].name, argv[0]))
+			return cmds[i].fn(argc, argv);
+
+	usage_msg_optf("unknown subcommand '%s'", submodule_usage, options,
+		       argv[0]);
+
+	return 0;
+}
diff --git a/t/helper/test-tool-utils.h b/t/helper/test-tool-utils.h
new file mode 100644
index 00000000000..6a0e5e0074f
--- /dev/null
+++ b/t/helper/test-tool-utils.h
@@ -0,0 +1,9 @@
+#ifndef TEST_TOOL_UTILS_H
+#define TEST_TOOL_UTILS_H
+
+struct test_cmd {
+	const char *name;
+	int (*fn)(int argc, const char **argv);
+};
+
+#endif
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 318fdbab0c3..7a6a8b88a91 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "test-tool.h"
+#include "test-tool-utils.h"
 #include "trace2.h"
 #include "parse-options.h"
 
@@ -8,11 +9,6 @@ static const char * const test_tool_usage[] = {
 	NULL
 };
 
-struct test_cmd {
-	const char *name;
-	int (*fn)(int argc, const char **argv);
-};
-
 static struct test_cmd cmds[] = {
 	{ "advise", cmd__advise_if_enabled },
 	{ "bitmap", cmd__bitmap },
@@ -78,6 +74,7 @@ static struct test_cmd cmds[] = {
 	{ "simple-ipc", cmd__simple_ipc },
 	{ "strcmp-offset", cmd__strcmp_offset },
 	{ "string-list", cmd__string_list },
+	{ "submodule", cmd__submodule },
 	{ "submodule-config", cmd__submodule_config },
 	{ "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
 	{ "subprocess", cmd__subprocess },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index bb799271631..5f4f69dee81 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -68,6 +68,7 @@ int cmd__sigchain(int argc, const char **argv);
 int cmd__simple_ipc(int argc, const char **argv);
 int cmd__strcmp_offset(int argc, const char **argv);
 int cmd__string_list(int argc, const char **argv);
+int cmd__submodule(int argc, const char **argv);
 int cmd__submodule_config(int argc, const char **argv);
 int cmd__submodule_nested_repo_config(int argc, const char **argv);
 int cmd__subprocess(int argc, const char **argv);
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index c8e7e983317..ede6f02dbd5 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -1,9 +1,12 @@
 #!/bin/sh
 
-test_description='Test submodule--helper is-active
+test_description='Test with test-tool submodule is-active
 
-This test verifies that `git submodue--helper is-active` correctly identifies
+This test verifies that `test-tool submodule is-active` correctly identifies
 submodules which are "active" and interesting to the user.
+
+This is a unit test of the submodule.c is_submodule_active() function,
+which is also indirectly tested elsewhere.
 '
 
 . ./test-lib.sh
@@ -25,13 +28,13 @@ test_expect_success 'setup' '
 '
 
 test_expect_success 'is-active works with urls' '
-	git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2 &&
+	test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2 &&
 
 	git -C super config --unset submodule.sub1.URL &&
-	test_must_fail git -C super submodule--helper is-active sub1 &&
+	test_must_fail test-tool -C super submodule is-active sub1 &&
 	git -C super config submodule.sub1.URL ../sub &&
-	git -C super submodule--helper is-active sub1
+	test-tool -C super submodule is-active sub1
 '
 
 test_expect_success 'is-active works with submodule.<name>.active config' '
@@ -39,11 +42,11 @@ test_expect_success 'is-active works with submodule.<name>.active config' '
 	test_when_finished "git -C super config submodule.sub1.URL ../sub" &&
 
 	git -C super config --bool submodule.sub1.active "false" &&
-	test_must_fail git -C super submodule--helper is-active sub1 &&
+	test_must_fail test-tool -C super submodule is-active sub1 &&
 
 	git -C super config --bool submodule.sub1.active "true" &&
 	git -C super config --unset submodule.sub1.URL &&
-	git -C super submodule--helper is-active sub1
+	test-tool -C super submodule is-active sub1
 '
 
 test_expect_success 'is-active works with basic submodule.active config' '
@@ -53,17 +56,17 @@ test_expect_success 'is-active works with basic submodule.active config' '
 	git -C super config --add submodule.active "." &&
 	git -C super config --unset submodule.sub1.URL &&
 
-	git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active correctly works with paths that are not submodules' '
 	test_when_finished "git -C super config --unset-all submodule.active" &&
 
-	test_must_fail git -C super submodule--helper is-active not-a-submodule &&
+	test_must_fail test-tool -C super submodule is-active not-a-submodule &&
 
 	git -C super config --add submodule.active "." &&
-	test_must_fail git -C super submodule--helper is-active not-a-submodule
+	test_must_fail test-tool -C super submodule is-active not-a-submodule
 '
 
 test_expect_success 'is-active works with exclusions in submodule.active config' '
@@ -72,8 +75,8 @@ test_expect_success 'is-active works with exclusions in submodule.active config'
 	git -C super config --add submodule.active "." &&
 	git -C super config --add submodule.active ":(exclude)sub1" &&
 
-	test_must_fail git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test_must_fail test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active with submodule.active and submodule.<name>.active' '
@@ -85,8 +88,8 @@ test_expect_success 'is-active with submodule.active and submodule.<name>.active
 	git -C super config --bool submodule.sub1.active "false" &&
 	git -C super config --bool submodule.sub2.active "true" &&
 
-	test_must_fail git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test_must_fail test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active, submodule.active and submodule add' '
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 07/28] submodule--helper: move "check-name" to a test-tool
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (5 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 06/28] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 08/28] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
                     ` (20 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Move the "check-name" helper to a test-tool, since
a6226fd772b (submodule--helper: convert the bulk of cmd_add() to C,
2021-08-10) it has only been used by this test, not git-submodule.sh.

As noted with its introduction in 0383bbb9015 (submodule-config:
verify submodule names as paths, 2018-04-30) the intent of
t7450-bad-git-dotfiles.sh has always been to unit test the
check_submodule_name() function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 24 -------------------
 t/helper/test-submodule.c   | 46 +++++++++++++++++++++++++++++++++++++
 t/t7450-bad-git-dotfiles.sh |  2 +-
 3 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b2fc732b5d8..06307886080 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2728,29 +2728,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-/*
- * Exit non-zero if any of the submodule names given on the command line is
- * invalid. If no names are given, filter stdin to print only valid names
- * (which is primarily intended for testing).
- */
-static int check_name(int argc, const char **argv, const char *prefix)
-{
-	if (argc > 1) {
-		while (*++argv) {
-			if (check_submodule_name(*argv) < 0)
-				return 1;
-		}
-	} else {
-		struct strbuf buf = STRBUF_INIT;
-		while (strbuf_getline(&buf, stdin) != EOF) {
-			if (!check_submodule_name(buf.buf))
-				printf("%s\n", buf.buf);
-		}
-		strbuf_release(&buf);
-	}
-	return 0;
-}
-
 static int module_config(int argc, const char **argv, const char *prefix)
 {
 	enum {
@@ -3305,7 +3282,6 @@ static struct cmd_struct commands[] = {
 	{"summary", module_summary, 0},
 	{"push-check", push_check, 0},
 	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
-	{"check-name", check_name, 0},
 	{"config", module_config, 0},
 	{"set-url", module_set_url, 0},
 	{"set-branch", module_set_branch, 0},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 494c6558d9f..9f0eb440192 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -2,8 +2,16 @@
 #include "test-tool-utils.h"
 #include "cache.h"
 #include "parse-options.h"
+#include "submodule-config.h"
 #include "submodule.h"
 
+#define TEST_TOOL_CHECK_NAME_USAGE \
+	"test-tool submodule check-name <name>"
+static const char *submodule_check_name_usage[] = {
+	TEST_TOOL_CHECK_NAME_USAGE,
+	NULL
+};
+
 #define TEST_TOOL_IS_ACTIVE_USAGE \
 	"test-tool submodule is-active <name>"
 static const char *submodule_is_active_usage[] = {
@@ -12,10 +20,47 @@ static const char *submodule_is_active_usage[] = {
 };
 
 static const char *submodule_usage[] = {
+	TEST_TOOL_CHECK_NAME_USAGE,
 	TEST_TOOL_IS_ACTIVE_USAGE,
 	NULL
 };
 
+/*
+ * Exit non-zero if any of the submodule names given on the command line is
+ * invalid. If no names are given, filter stdin to print only valid names
+ * (which is primarily intended for testing).
+ */
+static int check_name(int argc, const char **argv)
+{
+	if (argc > 1) {
+		while (*++argv) {
+			if (check_submodule_name(*argv) < 0)
+				return 1;
+		}
+	} else {
+		struct strbuf buf = STRBUF_INIT;
+		while (strbuf_getline(&buf, stdin) != EOF) {
+			if (!check_submodule_name(buf.buf))
+				printf("%s\n", buf.buf);
+		}
+		strbuf_release(&buf);
+	}
+	return 0;
+}
+
+static int cmd__submodule_check_name(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_check_name_usage, 0);
+	if (argc)
+		usage_with_options(submodule_check_name_usage, options);
+
+	return check_name(argc, argv);
+}
+
 static int cmd__submodule_is_active(int argc, const char **argv)
 {
 	struct option options[] = {
@@ -32,6 +77,7 @@ static int cmd__submodule_is_active(int argc, const char **argv)
 }
 
 static struct test_cmd cmds[] = {
+	{ "check-name", cmd__submodule_check_name },
 	{ "is-active", cmd__submodule_is_active },
 };
 
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index 41706c1c9ff..2c24f120da3 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -21,7 +21,7 @@ test_expect_success 'check names' '
 	valid/with/paths
 	EOF
 
-	git submodule--helper check-name >actual <<-\EOF &&
+	test-tool submodule check-name >actual <<-\EOF &&
 	valid
 	valid/with/paths
 
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 08/28] submodule--helper: move "resolve-relative-url-test" to a test-tool
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (6 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 07/28] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 22:32     ` Glen Choo
  2022-08-02 15:45   ` [PATCH v2 09/28] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
                     ` (19 subsequent siblings)
  27 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

As its name suggests the "resolve-relative-url-test" has never been
used outside of the test suite, see 63e95beb085 (submodule: port
resolve_relative_url from shell to C, 2016-04-15) for its original
addition.

Perhaps it would make sense to drop this code entirely, as we feel
that we've got enough indirect test coverage, but let's leave that
question to a possible follow-up change. For now let's keep the test
coverage this gives us.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 23 --------------------
 t/helper/test-submodule.c   | 42 +++++++++++++++++++++++++++++++++++++
 t/t0060-path-utils.sh       |  2 +-
 3 files changed, 43 insertions(+), 24 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 06307886080..246457ec2e9 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -96,28 +96,6 @@ static char *resolve_relative_url(const char *rel_url, const char *up_path, int
 	return resolved_url;
 }
 
-static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
-{
-	char *remoteurl, *res;
-	const char *up_path, *url;
-
-	if (argc != 4)
-		die("resolve-relative-url-test only accepts three arguments: <up_path> <remoteurl> <url>");
-
-	up_path = argv[1];
-	remoteurl = xstrdup(argv[2]);
-	url = argv[3];
-
-	if (!strcmp(up_path, "(null)"))
-		up_path = NULL;
-
-	res = relative_url(remoteurl, url, up_path);
-	puts(res);
-	free(res);
-	free(remoteurl);
-	return 0;
-}
-
 /* the result should be freed by the caller. */
 static char *get_submodule_displaypath(const char *path, const char *prefix)
 {
@@ -3273,7 +3251,6 @@ static struct cmd_struct commands[] = {
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
-	{"resolve-relative-url-test", resolve_relative_url_test, 0},
 	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
 	{"init", module_init, 0},
 	{"status", module_status, SUPPORT_SUPER_PREFIX},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 9f0eb440192..e0e0c53d386 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -2,6 +2,7 @@
 #include "test-tool-utils.h"
 #include "cache.h"
 #include "parse-options.h"
+#include "remote.h"
 #include "submodule-config.h"
 #include "submodule.h"
 
@@ -19,9 +20,17 @@ static const char *submodule_is_active_usage[] = {
 	NULL
 };
 
+#define TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE \
+	"test-tool submodule resolve-relative-url <up_path> <remoteurl> <url>"
+static const char *submodule_resolve_relative_url_usage[] = {
+	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
+	NULL,
+};
+
 static const char *submodule_usage[] = {
 	TEST_TOOL_CHECK_NAME_USAGE,
 	TEST_TOOL_IS_ACTIVE_USAGE,
+	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
 	NULL
 };
 
@@ -76,9 +85,42 @@ static int cmd__submodule_is_active(int argc, const char **argv)
 	return !is_submodule_active(the_repository, argv[0]);
 }
 
+static int resolve_relative_url(int argc, const char **argv)
+{
+	char *remoteurl, *res;
+	const char *up_path, *url;
+
+	up_path = argv[0];
+	remoteurl = xstrdup(argv[1]);
+	url = argv[2];
+
+	if (!strcmp(up_path, "(null)"))
+		up_path = NULL;
+
+	res = relative_url(remoteurl, url, up_path);
+	puts(res);
+	free(res);
+	free(remoteurl);
+	return 0;
+}
+
+static int cmd__submodule_resolve_relative_url(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_resolve_relative_url_usage, 0);
+	if (argc != 3)
+		usage_with_options(submodule_resolve_relative_url_usage, options);
+
+	return resolve_relative_url(argc, argv);
+}
+
 static struct test_cmd cmds[] = {
 	{ "check-name", cmd__submodule_check_name },
 	{ "is-active", cmd__submodule_is_active },
+	{ "resolve-relative-url", cmd__submodule_resolve_relative_url},
 };
 
 int cmd__submodule(int argc, const char **argv)
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 1f2007e62b7..68e29c904a6 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -22,7 +22,7 @@ relative_path() {
 
 test_submodule_relative_url() {
 	test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" "
-		actual=\$(git submodule--helper resolve-relative-url-test '$1' '$2' '$3') &&
+		actual=\$(test-tool submodule resolve-relative-url '$1' '$2' '$3') &&
 		test \"\$actual\" = '$4'
 	"
 }
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 09/28] submodule--helper style: don't separate declared variables with \n\n
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (7 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 08/28] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 10/28] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
                     ` (18 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The usual style in the codebase is to separate declared variables with
a single newline, not two, let's adjust this code to conform to
that. This makes the eventual addition of various "int ret" variables
more consistent.

In doing this the comment added in 2964d6e5e1e (submodule: port
subcommand 'set-branch' from shell to C, 2020-06-02) might become
ambiguous to some, although it should be clear what it's referring to,
let's move it above the 'OPT_NOOP_NOARG('q', "quiet")' to make that
clearer.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 33 +++++----------------------------
 1 file changed, 5 insertions(+), 28 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 246457ec2e9..53b9e14767d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -368,14 +368,12 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	struct foreach_cb info = FOREACH_CB_INIT;
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
-
 	struct option module_foreach_options[] = {
 		OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
 		OPT_BOOL(0, "recursive", &info.recursive,
 			 N_("recurse into nested submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
 		NULL
@@ -504,12 +502,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
-
 	struct option module_init_options[] = {
 		OPT__QUIET(&quiet, N_("suppress output for initializing a submodule")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule init [<options>] [<path>]"),
 		NULL
@@ -682,14 +678,12 @@ static int module_status(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
-
 	struct option module_status_options[] = {
 		OPT__QUIET(&quiet, N_("suppress submodule status output")),
 		OPT_BIT(0, "cached", &info.flags, N_("use commit stored in the index instead of the one stored in the submodule HEAD"), OPT_CACHED),
 		OPT_BIT(0, "recursive", &info.flags, N_("recurse into nested submodules"), OPT_RECURSIVE),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
 		NULL
@@ -1082,7 +1076,6 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 	enum diff_cmd diff_cmd = DIFF_INDEX;
 	struct object_id head_oid;
 	int ret;
-
 	struct option module_summary_options[] = {
 		OPT_BOOL(0, "cached", &cached,
 			 N_("use the commit stored in the index instead of the submodule HEAD")),
@@ -1094,7 +1087,6 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 			     N_("limit the summary size")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule summary [<options>] [<commit>] [--] [<path>]"),
 		NULL
@@ -1251,14 +1243,12 @@ static int module_sync(int argc, const char **argv, const char *prefix)
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
 	int recursive = 0;
-
 	struct option module_sync_options[] = {
 		OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
 		OPT_BOOL(0, "recursive", &recursive,
 			N_("recurse into nested submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule sync [--quiet] [--recursive] [<path>]"),
 		NULL
@@ -1390,14 +1380,12 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
 	int quiet = 0;
 	int force = 0;
 	int all = 0;
-
 	struct option module_deinit_options[] = {
 		OPT__QUIET(&quiet, N_("suppress submodule status output")),
 		OPT__FORCE(&force, N_("remove submodule working trees even if they contain local changes"), 0),
 		OPT_BOOL(0, "all", &all, N_("unregister all submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
 		NULL
@@ -1666,7 +1654,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
 	struct list_objects_filter_options filter_options;
-
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1698,7 +1685,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule--helper clone [--prefix=<path>] [--quiet] "
 		   "[--reference <repository>] [--name <name>] [--depth <depth>] "
@@ -2486,7 +2472,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 	struct update_data opt = UPDATE_DATA_INIT;
 	struct list_objects_filter_options filter_options;
 	int ret;
-
 	struct option module_update_options[] = {
 		OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
 		OPT_BOOL(0, "init", &opt.init,
@@ -2530,7 +2515,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule [--quiet] update"
 		" [--init [--filter=<filter-spec>]] [--remote]"
@@ -2679,7 +2663,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
-
 	struct option embed_gitdir_options[] = {
 		OPT_STRING(0, "prefix", &prefix,
 			   N_("path"),
@@ -2688,7 +2671,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 			ABSORB_GITDIR_RECURSE_SUBMODULES),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule absorbgitdirs [<options>] [<path>...]"),
 		NULL
@@ -2712,7 +2694,6 @@ static int module_config(int argc, const char **argv, const char *prefix)
 		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"),
@@ -2758,7 +2739,6 @@ static int module_set_url(int argc, const char **argv, const char *prefix)
 	const char *newurl;
 	const char *path;
 	char *config_name;
-
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("suppress output for setting url of a submodule")),
 		OPT_END()
@@ -2789,13 +2769,13 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
 	const char *opt_branch = NULL;
 	const char *path;
 	char *config_name;
-
-	/*
-	 * We accept the `quiet` option for uniformity across subcommands,
-	 * though there is nothing to make less verbose in this subcommand.
-	 */
 	struct option options[] = {
+		/*
+		 * We accept the `quiet` option for uniformity across subcommands,
+		 * though there is nothing to make less verbose in this subcommand.
+		 */
 		OPT_NOOP_NOARG('q', "quiet"),
+
 		OPT_BOOL('d', "default", &opt_default,
 			N_("set the default tracking branch to master")),
 		OPT_STRING('b', "branch", &opt_branch, N_("branch"),
@@ -2830,7 +2810,6 @@ static int module_create_branch(int argc, const char **argv, const char *prefix)
 {
 	enum branch_track track;
 	int quiet = 0, force = 0, reflog = 0, dry_run = 0;
-
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("print only error messages")),
 		OPT__FORCE(&force, N_("force creation"), 0),
@@ -3129,7 +3108,6 @@ static int module_add(int argc, const char **argv, const char *prefix)
 	int force = 0, quiet = 0, progress = 0, dissociate = 0;
 	struct add_data add_data = ADD_DATA_INIT;
 	char *to_free = NULL;
-
 	struct option options[] = {
 		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
 			   N_("branch of repository to add as submodule")),
@@ -3146,7 +3124,6 @@ static int module_add(int argc, const char **argv, const char *prefix)
 		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
 		OPT_END()
 	};
-
 	const char *const usage[] = {
 		N_("git submodule add [<options>] [--] <repository> [<path>]"),
 		NULL
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 10/28] submodule--helper style: add \n\n after variable declarations
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (8 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 09/28] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 11/28] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
                     ` (17 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Since the preceding commit fixed style issues with \n\n among the
declared variables let's fix the minor stylistic issues with those
variables not being consistently followed by a \n\n.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 53b9e14767d..15bf89910f4 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -167,6 +167,7 @@ static int module_list_compute(int argc, const char **argv,
 {
 	int i, result = 0;
 	char *ps_matched = NULL;
+
 	parse_pathspec(pathspec, 0,
 		       PATHSPEC_PREFER_FULL,
 		       prefix, argv);
@@ -248,6 +249,7 @@ static void for_each_listed_submodule(const struct module_list *list,
 				      each_submodule_fn fn, void *cb_data)
 {
 	int i;
+
 	for (i = 0; i < list->nr; i++)
 		fn(list->entries[i], cb_data);
 }
@@ -267,7 +269,6 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
 	struct foreach_cb *info = cb_data;
 	const char *path = list_item->name;
 	const struct object_id *ce_oid = &list_item->oid;
-
 	const struct submodule *sub;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *displaypath;
@@ -456,6 +457,7 @@ static void init_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(url) ||
 		    starts_with_dot_slash(url)) {
 			char *oldurl = url;
+
 			url = resolve_relative_url(oldurl, NULL, 0);
 			free(oldurl);
 		}
@@ -493,6 +495,7 @@ static void init_submodule(const char *path, const char *prefix,
 static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
 {
 	struct init_cb *info = cb_data;
+
 	init_submodule(list_item->name, info->prefix, info->flags);
 }
 
@@ -562,6 +565,7 @@ static int handle_submodule_head_ref(const char *refname,
 				     void *cb_data)
 {
 	struct object_id *output = cb_data;
+
 	if (oid)
 		oidcpy(output, oid);
 
@@ -668,6 +672,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
 				void *cb_data)
 {
 	struct status_cb *info = cb_data;
+
 	status_submodule(list_item->name, &list_item->oid, list_item->ce_flags,
 			 info->prefix, info->flags);
 }
@@ -820,6 +825,7 @@ static void generate_submodule_summary(struct summary_cb *info,
 	if (!info->cached && oideq(&p->oid_dst, null_oid())) {
 		if (S_ISGITLINK(p->mod_dst)) {
 			struct ref_store *refs = get_submodule_ref_store(p->sm_path);
+
 			if (refs)
 				refs_head_ref(refs, handle_submodule_head_ref, &p->oid_dst);
 		} else if (S_ISLNK(p->mod_dst) || S_ISREG(p->mod_dst)) {
@@ -1158,6 +1164,7 @@ static void sync_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
 			char *up_path = get_up_path(path);
+
 			sub_origin_url = resolve_relative_url(sub->url, up_path, 1);
 			super_config_url = resolve_relative_url(sub->url, NULL, 1);
 			free(up_path);
@@ -1233,6 +1240,7 @@ static void sync_submodule(const char *path, const char *prefix,
 static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data)
 {
 	struct sync_cb *info = cb_data;
+
 	sync_submodule(list_item->name, info->prefix, info->flags);
 }
 
@@ -1312,6 +1320,7 @@ static void deinit_submodule(const char *path, const char *prefix,
 
 		if (!(flags & OPT_FORCE)) {
 			struct child_process cp_rm = CHILD_PROCESS_INIT;
+
 			cp_rm.git_cmd = 1;
 			strvec_pushl(&cp_rm.args, "rm", "-qn",
 				     path, NULL);
@@ -1348,6 +1357,7 @@ static void deinit_submodule(const char *path, const char *prefix,
 	/* remove the .git/config entries (unless the user already did it) */
 	if (!capture_command(&cp_config, &sb_config, 0) && sb_config.len) {
 		char *sub_key = xstrfmt("submodule.%s", sub->name);
+
 		/*
 		 * remove the whole section so we have a clean state when
 		 * the user later decides to init this submodule again
@@ -1585,6 +1595,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
 		if (clone_data->reference.nr) {
 			struct string_list_item *item;
+
 			for_each_string_list_item(item, &clone_data->reference)
 				strvec_pushl(&cp.args, "--reference",
 					     item->string, NULL);
@@ -1935,6 +1946,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	strvec_pushl(&child->args, "--url", url, NULL);
 	if (suc->update_data->references.nr) {
 		struct string_list_item *item;
+
 		for_each_string_list_item(item, &suc->update_data->references)
 			strvec_pushl(&child->args, "--reference", item->string, NULL);
 	}
@@ -1967,6 +1979,7 @@ static int update_clone_get_next_task(struct child_process *child,
 		ce = suc->update_data->list.entries[suc->current];
 		if (prepare_to_clone_next_submodule(ce, child, suc, err)) {
 			int *p = xmalloc(sizeof(*p));
+
 			*p = suc->current;
 			*idx_task_cb = p;
 			suc->current++;
@@ -1982,6 +1995,7 @@ static int update_clone_get_next_task(struct child_process *child,
 	index = suc->current - suc->update_data->list.nr;
 	if (index < suc->failed_clones_nr) {
 		int *p;
+
 		ce = suc->failed_clones[index];
 		if (!prepare_to_clone_next_submodule(ce, child, suc, err)) {
 			suc->current ++;
@@ -2005,6 +2019,7 @@ static int update_clone_start_failure(struct strbuf *err,
 				      void *idx_task_cb)
 {
 	struct submodule_update_clone *suc = suc_cb;
+
 	suc->quickstop = 1;
 	return 1;
 }
@@ -2016,9 +2031,9 @@ static int update_clone_task_finished(int result,
 {
 	const struct cache_entry *ce;
 	struct submodule_update_clone *suc = suc_cb;
-
 	int *idxP = idx_task_cb;
 	int idx = *idxP;
+
 	free(idxP);
 
 	if (!result)
@@ -2051,6 +2066,7 @@ static int git_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;
@@ -2091,6 +2107,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	if (oid) {
 		char *hex = oid_to_hex(oid);
 		char *remote = get_default_remote();
+
 		strvec_pushl(&cp.args, remote, hex, NULL);
 		free(remote);
 	}
@@ -2340,6 +2357,7 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 
 	if (update_data->references.nr) {
 		struct string_list_item *item;
+
 		for_each_string_list_item(item, &update_data->references)
 			strvec_pushl(args, "--reference", item->string, NULL);
 	}
@@ -2872,8 +2890,10 @@ static void append_fetch_remotes(struct strbuf *msg, const char *git_dir_path)
 	if (!capture_command(&cp_remote, &sb_remote_out, 0)) {
 		char *next_line;
 		char *line = sb_remote_out.buf;
+
 		while ((next_line = strchr(line, '\n')) != NULL) {
 			size_t len = next_line - line;
+
 			if (strip_suffix_mem(line, &len, " (fetch)"))
 				strbuf_addf(msg, "  %.*s\n", (int)len, line);
 			line = next_line + 1;
@@ -3180,6 +3200,7 @@ static int module_add(int argc, const char **argv, const char *prefix)
 		int exit_code = -1;
 		struct strbuf sb = STRBUF_INIT;
 		struct child_process cp = CHILD_PROCESS_INIT;
+
 		cp.git_cmd = 1;
 		cp.no_stdout = 1;
 		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 11/28] submodule--helper: replace memset() with { 0 }-initialization
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (9 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 10/28] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 12/28] submodule--helper: use xstrfmt() in clone_submodule() Ævar Arnfjörð Bjarmason
                     ` (16 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Use the less verbose { 0 }-initialization syntax rather than memset()
in builtin/submodule--helper.c, this doesn't make a difference in
terms of behavior, but as we're about to modify adjacent code makes
this more consistent, and lets us avoid worrying about when the
memset() happens v.s. a "goto cleanup".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 15bf89910f4..60165a848a2 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1664,7 +1664,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 {
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
-	struct list_objects_filter_options filter_options;
+	struct list_objects_filter_options filter_options = { 0 };
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1704,7 +1704,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		NULL
 	};
 
-	memset(&filter_options, 0, sizeof(filter_options));
 	argc = parse_options(argc, argv, prefix, module_clone_options,
 			     git_submodule_helper_usage, 0);
 
@@ -2488,7 +2487,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
 {
 	struct pathspec pathspec;
 	struct update_data opt = UPDATE_DATA_INIT;
-	struct list_objects_filter_options filter_options;
+	struct list_objects_filter_options filter_options = { 0 };
 	int ret;
 	struct option module_update_options[] = {
 		OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
@@ -2546,7 +2545,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 	update_clone_config_from_gitmodules(&opt.max_jobs);
 	git_config(git_update_clone_config, &opt.max_jobs);
 
-	memset(&filter_options, 0, sizeof(filter_options));
 	argc = parse_options(argc, argv, prefix, module_update_options,
 			     git_submodule_helper_usage, 0);
 
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 12/28] submodule--helper: use xstrfmt() in clone_submodule()
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (10 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 11/28] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 13/28] submodule--helper: move "sb" in clone_submodule() to its own scope Ævar Arnfjörð Bjarmason
                     ` (15 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Use xstrfmt() in clone_submodule() instead of a "struct strbuf" in two
cases where we weren't getting anything out of using the "struct
strbuf".

This changes code that was was added along with other uses of "struct
strbuf" in this function in ee8838d1577 (submodule: rewrite
`module_clone` shell function in C, 2015-09-08).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 60165a848a2..63008970f1c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1568,12 +1568,11 @@ static int clone_submodule(struct module_clone_data *clone_data)
 	sm_gitdir = absolute_pathdup(sb.buf);
 	strbuf_reset(&sb);
 
-	if (!is_absolute_path(clone_data->path)) {
-		strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
-		clone_data->path = strbuf_detach(&sb, NULL);
-	} else {
+	if (!is_absolute_path(clone_data->path))
+		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
+					   clone_data->path);
+	else
 		clone_data->path = xstrdup(clone_data->path);
-	}
 
 	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
 		die(_("refusing to create/use '%s' in another submodule's "
@@ -1625,14 +1624,16 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			die(_("clone of '%s' into submodule path '%s' failed"),
 			    clone_data->url, clone_data->path);
 	} else {
+		char *path;
+
 		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
 		    !is_empty_dir(clone_data->path))
 			die(_("directory not empty: '%s'"), clone_data->path);
 		if (safe_create_leading_directories_const(clone_data->path) < 0)
 			die(_("could not create directory '%s'"), clone_data->path);
-		strbuf_addf(&sb, "%s/index", sm_gitdir);
-		unlink_or_warn(sb.buf);
-		strbuf_reset(&sb);
+		path = xstrfmt("%s/index", sm_gitdir);
+		unlink_or_warn(path);
+		free(path);
 	}
 
 	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 13/28] submodule--helper: move "sb" in clone_submodule() to its own scope
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (11 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 12/28] submodule--helper: use xstrfmt() in clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 14/28] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
                     ` (14 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Refactor the only remaining use of a "struct strbuf sb" in
clone_submodule() to live in its own scope. This makes the code
clearer by limiting its lifetime.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 63008970f1c..fe32abd45e6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1557,16 +1557,24 @@ static void prepare_possible_alternates(const char *sm_name,
 	free(error_strategy);
 }
 
-static int clone_submodule(struct module_clone_data *clone_data)
+static char *clone_submodule_sm_gitdir(const char *name)
 {
-	char *p, *sm_gitdir;
-	char *sm_alternate = NULL, *error_strategy = NULL;
 	struct strbuf sb = STRBUF_INIT;
-	struct child_process cp = CHILD_PROCESS_INIT;
+	char *sm_gitdir;
 
-	submodule_name_to_gitdir(&sb, the_repository, clone_data->name);
+	submodule_name_to_gitdir(&sb, the_repository, name);
 	sm_gitdir = absolute_pathdup(sb.buf);
-	strbuf_reset(&sb);
+	strbuf_release(&sb);
+
+	return sm_gitdir;
+}
+
+static int clone_submodule(struct module_clone_data *clone_data)
+{
+	char *p;
+	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
+	char *sm_alternate = NULL, *error_strategy = NULL;
+	struct child_process cp = CHILD_PROCESS_INIT;
 
 	if (!is_absolute_path(clone_data->path))
 		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
@@ -1655,7 +1663,6 @@ static int clone_submodule(struct module_clone_data *clone_data)
 	free(sm_alternate);
 	free(error_strategy);
 
-	strbuf_release(&sb);
 	free(sm_gitdir);
 	free(p);
 	return 0;
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 14/28] submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (12 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 13/28] submodule--helper: move "sb" in clone_submodule() to its own scope Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:45   ` [PATCH v2 15/28] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
                     ` (13 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add "const" to the "struct module_clone_data" that we pass to
clone_submodule(), which makes the ownership clear, and stops us from
clobbering the "clone_data->path".

We still need to add to the "reference" member, which is a "struct
string_list". Let's do this by having clone_submodule() create its
own, and copy the contents over, allowing us to pass it as a
separate parameter.

This new "struct string_list" still leaks memory, just as the "struct
module_clone_data" did before. let's not fix that for now, to fix that
we'll need to add some "goto cleanup" to the relevant code. That will
eventually be done in follow-up commits, this change makes it easier
to fix the memory leak.

The scope of the new "reference" variable in add_submodule() could be
narrowed to the "else" block, but as we'll eventually free it with a
"goto cleanup" let's declare it at the start of the function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 49 ++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fe32abd45e6..6b4ee8a31bb 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1434,7 +1434,6 @@ struct module_clone_data {
 	const char *url;
 	const char *depth;
 	struct list_objects_filter_options *filter_options;
-	struct string_list reference;
 	unsigned int quiet: 1;
 	unsigned int progress: 1;
 	unsigned int dissociate: 1;
@@ -1442,7 +1441,6 @@ struct module_clone_data {
 	int single_branch;
 };
 #define MODULE_CLONE_DATA_INIT { \
-	.reference = STRING_LIST_INIT_NODUP, \
 	.single_branch = -1, \
 }
 
@@ -1569,18 +1567,20 @@ static char *clone_submodule_sm_gitdir(const char *name)
 	return sm_gitdir;
 }
 
-static int clone_submodule(struct module_clone_data *clone_data)
+static int clone_submodule(const struct module_clone_data *clone_data,
+			   struct string_list *reference)
 {
 	char *p;
 	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
 	char *sm_alternate = NULL, *error_strategy = NULL;
 	struct child_process cp = CHILD_PROCESS_INIT;
+	const char *clone_data_path;
 
 	if (!is_absolute_path(clone_data->path))
-		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
-					   clone_data->path);
+		clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
+					  clone_data->path);
 	else
-		clone_data->path = xstrdup(clone_data->path);
+		clone_data_path = xstrdup(clone_data->path);
 
 	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
 		die(_("refusing to create/use '%s' in another submodule's "
@@ -1590,7 +1590,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 		if (safe_create_leading_directories_const(sm_gitdir) < 0)
 			die(_("could not create directory '%s'"), sm_gitdir);
 
-		prepare_possible_alternates(clone_data->name, &clone_data->reference);
+		prepare_possible_alternates(clone_data->name, reference);
 
 		strvec_push(&cp.args, "clone");
 		strvec_push(&cp.args, "--no-checkout");
@@ -1600,10 +1600,10 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			strvec_push(&cp.args, "--progress");
 		if (clone_data->depth && *(clone_data->depth))
 			strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
-		if (clone_data->reference.nr) {
+		if (reference->nr) {
 			struct string_list_item *item;
 
-			for_each_string_list_item(item, &clone_data->reference)
+			for_each_string_list_item(item, reference)
 				strvec_pushl(&cp.args, "--reference",
 					     item->string, NULL);
 		}
@@ -1622,7 +1622,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 
 		strvec_push(&cp.args, "--");
 		strvec_push(&cp.args, clone_data->url);
-		strvec_push(&cp.args, clone_data->path);
+		strvec_push(&cp.args, clone_data_path);
 
 		cp.git_cmd = 1;
 		prepare_submodule_repo_env(&cp.env);
@@ -1630,25 +1630,25 @@ static int clone_submodule(struct module_clone_data *clone_data)
 
 		if(run_command(&cp))
 			die(_("clone of '%s' into submodule path '%s' failed"),
-			    clone_data->url, clone_data->path);
+			    clone_data->url, clone_data_path);
 	} else {
 		char *path;
 
-		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
-		    !is_empty_dir(clone_data->path))
-			die(_("directory not empty: '%s'"), clone_data->path);
-		if (safe_create_leading_directories_const(clone_data->path) < 0)
-			die(_("could not create directory '%s'"), clone_data->path);
+		if (clone_data->require_init && !access(clone_data_path, X_OK) &&
+		    !is_empty_dir(clone_data_path))
+			die(_("directory not empty: '%s'"), clone_data_path);
+		if (safe_create_leading_directories_const(clone_data_path) < 0)
+			die(_("could not create directory '%s'"), clone_data_path);
 		path = xstrfmt("%s/index", sm_gitdir);
 		unlink_or_warn(path);
 		free(path);
 	}
 
-	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
+	connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0);
 
-	p = git_pathdup_submodule(clone_data->path, "config");
+	p = git_pathdup_submodule(clone_data_path, "config");
 	if (!p)
-		die(_("could not get submodule directory for '%s'"), clone_data->path);
+		die(_("could not get submodule directory for '%s'"), clone_data_path);
 
 	/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
 	git_config_get_string("submodule.alternateLocation", &sm_alternate);
@@ -1673,6 +1673,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
 	struct list_objects_filter_options filter_options = { 0 };
+	struct string_list reference = STRING_LIST_INIT_NODUP;
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1686,7 +1687,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		OPT_STRING(0, "url", &clone_data.url,
 			   N_("string"),
 			   N_("url where to clone the submodule from")),
-		OPT_STRING_LIST(0, "reference", &clone_data.reference,
+		OPT_STRING_LIST(0, "reference", &reference,
 			   N_("repo"),
 			   N_("reference repository")),
 		OPT_BOOL(0, "dissociate", &dissociate,
@@ -1725,7 +1726,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		usage_with_options(git_submodule_helper_usage,
 				   module_clone_options);
 
-	clone_submodule(&clone_data);
+	clone_submodule(&clone_data, &reference);
 	list_objects_filter_release(&filter_options);
 	return 0;
 }
@@ -2913,6 +2914,7 @@ static int add_submodule(const struct add_data *add_data)
 {
 	char *submod_gitdir_path;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
+	struct string_list reference = STRING_LIST_INIT_NODUP;
 
 	/* perhaps the path already exists and is already a git repo, else clone it */
 	if (is_directory(add_data->sm_path)) {
@@ -2929,6 +2931,7 @@ static int add_submodule(const struct add_data *add_data)
 		free(submod_gitdir_path);
 	} else {
 		struct child_process cp = CHILD_PROCESS_INIT;
+
 		submod_gitdir_path = xstrfmt(".git/modules/%s", add_data->sm_name);
 
 		if (is_directory(submod_gitdir_path)) {
@@ -2968,13 +2971,13 @@ static int add_submodule(const struct add_data *add_data)
 		clone_data.quiet = add_data->quiet;
 		clone_data.progress = add_data->progress;
 		if (add_data->reference_path)
-			string_list_append(&clone_data.reference,
+			string_list_append(&reference,
 					   xstrdup(add_data->reference_path));
 		clone_data.dissociate = add_data->dissociate;
 		if (add_data->depth >= 0)
 			clone_data.depth = xstrfmt("%d", add_data->depth);
 
-		if (clone_submodule(&clone_data))
+		if (clone_submodule(&clone_data, &reference))
 			return -1;
 
 		prepare_submodule_repo_env(&cp.env);
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 15/28] submodule--helper: add "const" to copy of "update_data"
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (13 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 14/28] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:45   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 16/28] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
                     ` (12 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

From: Glen Choo <chooglen@google.com>

Add a "const" to the copy of "struct update_data" that's tracked by
the "struct submodule_update_clone", as it neither owns nor modifies
it.

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6b4ee8a31bb..1391316cde2 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1777,7 +1777,7 @@ struct submodule_update_clone {
 	int current;
 
 	/* configuration parameters which are passed on to the children */
-	struct update_data *update_data;
+	const struct update_data *update_data;
 
 	/* to be consumed by update_submodule() */
 	struct update_clone_data *update_clone;
@@ -1862,7 +1862,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	const char *update_string;
 	enum submodule_update_type update_type;
 	char *key;
-	struct update_data *ud = suc->update_data;
+	const struct update_data *ud = suc->update_data;
 	char *displaypath = get_submodule_displaypath(ce->name, ud->prefix);
 	struct strbuf sb = STRBUF_INIT;
 	int needs_cloning = 0;
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 16/28] submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (14 preceding siblings ...)
  2022-08-02 15:45   ` [PATCH v2 15/28] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 17/28] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
                     ` (11 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

From: Glen Choo <chooglen@google.com>

Refactor code added in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13) so that "errmsg" and
"errmsg_str" are folded into one. The distinction between the empty
string and NULL is something that's tested for by
e.g. "t/t7401-submodule-summary.sh".

This is in preparation for fixing a memory leak the "struct strbuf" in
the pre-image.

Let's also pass a "const char *" to print_submodule_summary(), as it
should not be modifying the "errmsg".

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 1391316cde2..5ea308273f4 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -761,7 +761,7 @@ static char *verify_submodule_committish(const char *sm_path,
 	return strbuf_detach(&result, NULL);
 }
 
-static void print_submodule_summary(struct summary_cb *info, char *errmsg,
+static void print_submodule_summary(struct summary_cb *info, const char *errmsg,
 				    int total_commits, const char *displaypath,
 				    const char *src_abbrev, const char *dst_abbrev,
 				    struct module_cb *p)
@@ -819,7 +819,7 @@ static void generate_submodule_summary(struct summary_cb *info,
 {
 	char *displaypath, *src_abbrev = NULL, *dst_abbrev;
 	int missing_src = 0, missing_dst = 0;
-	char *errmsg = NULL;
+	struct strbuf errmsg = STRBUF_INIT;
 	int total_commits = -1;
 
 	if (!info->cached && oideq(&p->oid_dst, null_oid())) {
@@ -920,23 +920,21 @@ static void generate_submodule_summary(struct summary_cb *info,
 		 * submodule, i.e., deleted or changed to blob
 		 */
 		if (S_ISGITLINK(p->mod_dst)) {
-			struct strbuf errmsg_str = STRBUF_INIT;
 			if (missing_src && missing_dst) {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commits %s and %s\n",
+				strbuf_addf(&errmsg, "  Warn: %s doesn't contain commits %s and %s\n",
 					    displaypath, oid_to_hex(&p->oid_src),
 					    oid_to_hex(&p->oid_dst));
 			} else {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commit %s\n",
+				strbuf_addf(&errmsg, "  Warn: %s doesn't contain commit %s\n",
 					    displaypath, missing_src ?
 					    oid_to_hex(&p->oid_src) :
 					    oid_to_hex(&p->oid_dst));
 			}
-			errmsg = strbuf_detach(&errmsg_str, NULL);
 		}
 	}
 
-	print_submodule_summary(info, errmsg, total_commits,
-				displaypath, src_abbrev,
+	print_submodule_summary(info, errmsg.len ? errmsg.buf : NULL,
+				total_commits, displaypath, src_abbrev,
 				dst_abbrev, p);
 
 	free(displaypath);
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 17/28] submodule--helper: don't redundantly check "else if (res)"
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (15 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 16/28] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 18/28] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
                     ` (10 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The "res" variable must be true at this point in update_submodule(),
as just a few lines above this we've unconditionally:

	if (!res)
		return 0;

So we don't need to guard the "return 1" with an "else if (res)", we
an return unconditionally at this point. See b3c5f5cb048 (submodule:
move core cmd_update() logic to C, 2022-03-15) for the initial
introduction of this code, this check of "res" has always been
redundant.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 5ea308273f4..1a19723f596 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2443,8 +2443,7 @@ static int update_submodule(struct update_data *update_data)
 			    update_data->displaypath);
 		if (res == 128)
 			exit(res);
-		else if (res)
-			return 1;
+		return 1;
 	}
 
 	return 0;
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 18/28] submodule--helper: rename "int res" to "int ret"
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (16 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 17/28] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 19/28] submodule--helper: return "ret", not "1" from update_submodule() Ævar Arnfjörð Bjarmason
                     ` (9 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Rename the "res" variable added in b3c5f5cb048 (submodule: move core
cmd_update() logic to C, 2022-03-15) to "ret", which is the convention
in the rest of this file.

Eventual follow-up commits will change the code in update_submodule()
to a "goto cleanup" pattern, let's have the post image look consistent
with the rest. For update_submodules() let's also use a "ret" for
consistency, that use was also added in b3c5f5cb048. We'll be
modifying that codepath in subsequent commits.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 1a19723f596..29f3e1dd8c8 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2424,7 +2424,7 @@ static int update_submodule(struct update_data *update_data)
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		struct update_data next = *update_data;
-		int res;
+		int ret;
 
 		next.prefix = NULL;
 		oidcpy(&next.oid, null_oid());
@@ -2436,13 +2436,13 @@ static int update_submodule(struct update_data *update_data)
 		update_data_to_args(&next, &cp.args);
 
 		/* die() if child process die()'d */
-		res = run_command(&cp);
-		if (!res)
+		ret = run_command(&cp);
+		if (!ret)
 			return 0;
 		die_message(_("Failed to recurse into submodule path '%s'"),
 			    update_data->displaypath);
-		if (res == 128)
-			exit(res);
+		if (ret == 128)
+			exit(ret);
 		return 1;
 	}
 
@@ -2451,7 +2451,7 @@ static int update_submodule(struct update_data *update_data)
 
 static int update_submodules(struct update_data *update_data)
 {
-	int i, res = 0;
+	int i, ret = 0;
 	struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
 
 	suc.update_data = update_data;
@@ -2469,7 +2469,7 @@ static int update_submodules(struct update_data *update_data)
 	 * - the listener can avoid doing any work if fetching failed.
 	 */
 	if (suc.quickstop) {
-		res = 1;
+		ret = 1;
 		goto cleanup;
 	}
 
@@ -2481,12 +2481,12 @@ static int update_submodules(struct update_data *update_data)
 		update_data->sm_path = ucd.sub->path;
 
 		if (update_submodule(update_data))
-			res = 1;
+			ret = 1;
 	}
 
 cleanup:
 	string_list_clear(&update_data->references, 0);
-	return res;
+	return ret;
 }
 
 static int module_update(int argc, const char **argv, const char *prefix)
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 19/28] submodule--helper: return "ret", not "1" from update_submodule()
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (17 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 18/28] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 20/28] submodule--helper: add missing braces to "else" arm Ævar Arnfjörð Bjarmason
                     ` (8 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Amend the update_submodule() function to return the failing "ret" on
error, instead of overriding it with "1".

This code was added in b3c5f5cb048 (submodule: move core cmd_update()
logic to C, 2022-03-15), and this change ends up not making a
difference as this function is only called in update_submodules(). If
we return non-zero here we'll always in turn return "1" in
module_update().

But if we didn't do that and returned any other non-zero exit code in
update_submodules() we'd fail the test that's being amended
here. We're still testing the status quo here.

This change makes subsequent refactoring of update_submodule() easier,
as we'll no longer need to worry about clobbering the "ret" we get
from the run_command().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 2 +-
 t/t7406-submodule-update.sh | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 29f3e1dd8c8..0fb780a724c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2443,7 +2443,7 @@ static int update_submodule(struct update_data *update_data)
 			    update_data->displaypath);
 		if (ret == 128)
 			exit(ret);
-		return 1;
+		return ret;
 	}
 
 	return 0;
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 6cc07460dd2..c5f5dbe55e0 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -769,7 +769,7 @@ test_expect_success 'submodule update continues after recursive checkout error'
 	   echo "" > file
 	  )
 	 ) &&
-	 test_must_fail git submodule update --recursive &&
+	 test_expect_code 1 git submodule update --recursive &&
 	 (cd submodule2 &&
 	  git rev-parse --verify HEAD >../actual
 	 ) &&
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 20/28] submodule--helper: add missing braces to "else" arm
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (18 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 19/28] submodule--helper: return "ret", not "1" from update_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 21/28] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
                     ` (7 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add missing braces to an "else" arm in init_submodule(), this
stylistic change makes this code conform to the CodingGuidelines, and
makes a subsequent commit smaller.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 0fb780a724c..955deb375ee 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -480,8 +480,9 @@ static void init_submodule(const char *path, const char *prefix,
 			fprintf(stderr, _("warning: command update mode suggested for submodule '%s'\n"),
 				sub->name);
 			upd = xstrdup("none");
-		} else
+		} else {
 			upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy));
+		}
 
 		if (git_config_set_gently(sb.buf, upd))
 			die(_("Failed to register update mode for submodule path '%s'"), displaypath);
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 21/28] submodule--helper: don't call submodule_strategy_to_string() in BUG()
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (19 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 20/28] submodule--helper: add missing braces to "else" arm Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 23:08     ` Glen Choo
  2022-08-02 15:46   ` [PATCH v2 22/28] submodule--helper: move submodule_strategy_to_string() to only user Ævar Arnfjörð Bjarmason
                     ` (6 subsequent siblings)
  27 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Don't call submodule_strategy_to_string() in a BUG() message. These
calls added in c51f8f94e5b (submodule--helper: run update procedures
from C, 2021-08-24) don't need the extra information
submodule_strategy_to_string() gives us, as we'll never reach the
SM_UPDATE_COMMAND case here.

That case is the only one where we'd get any information beyond the
straightforward number-to-string mapping.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 955deb375ee..b49528e1ba9 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2155,8 +2155,8 @@ static int run_update_command(struct update_data *ud, int subforce)
 		must_die_on_failure = 1;
 		break;
 	default:
-		BUG("unexpected update strategy type: %s",
-		    submodule_strategy_to_string(&ud->update_strategy));
+		BUG("unexpected update strategy type: %d",
+		    ud->update_strategy.type);
 	}
 	strvec_push(&cp.args, oid);
 
@@ -2181,8 +2181,8 @@ static int run_update_command(struct update_data *ud, int subforce)
 			    ud->update_strategy.command, oid, ud->displaypath);
 			break;
 		default:
-			BUG("unexpected update strategy type: %s",
-			    submodule_strategy_to_string(&ud->update_strategy));
+			BUG("unexpected update strategy type: %d",
+			    ud->update_strategy.type);
 		}
 		if (must_die_on_failure)
 			exit(128);
@@ -2212,8 +2212,8 @@ static int run_update_command(struct update_data *ud, int subforce)
 		       ud->displaypath, ud->update_strategy.command, oid);
 		break;
 	default:
-		BUG("unexpected update strategy type: %s",
-		    submodule_strategy_to_string(&ud->update_strategy));
+		BUG("unexpected update strategy type: %d",
+		    ud->update_strategy.type);
 	}
 
 	return 0;
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 22/28] submodule--helper: move submodule_strategy_to_string() to only user
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (20 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 21/28] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 23:30     ` Glen Choo
  2022-08-02 15:46   ` [PATCH v2 23/28] submodule--helper: use "code" in run_update_command() Ævar Arnfjörð Bjarmason
                     ` (5 subsequent siblings)
  27 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Move the submodule_strategy_to_string() function added in
3604242f080 (submodule: port init from shell to C, 2016-04-15) to its
only user.

This function would return NULL on SM_UPDATE_UNSPECIFIED, so it wasn't
safe to xstrdup() its return value in the general case, or to use it
in a sprintf() format as the code removed in the preceding commit did.

But its callers would never call it with either SM_UPDATE_UNSPECIFIED
or SM_UPDATE_COMMAND. Let's move it to a "static" helper, and have its
functionality reflect how it's used, and BUG() out on the rest.

By doing this we can also stop needlessly xstrdup()-ing and free()-ing
the memory for the config we're setting. We can instead always use
constant strings. We can also use the *_tmp() variant of
git_config_get_string().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 29 ++++++++++++++++++++++++-----
 submodule.c                 | 21 ---------------------
 submodule.h                 |  1 -
 3 files changed, 24 insertions(+), 27 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b49528e1ba9..d787c0fead4 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -413,12 +413,32 @@ struct init_cb {
 };
 #define INIT_CB_INIT { 0 }
 
+static const char *submodule_strategy_to_string(enum submodule_update_type type)
+{
+	switch (type) {
+	case SM_UPDATE_CHECKOUT:
+		return "checkout";
+	case SM_UPDATE_MERGE:
+		return "merge";
+	case SM_UPDATE_REBASE:
+		return "rebase";
+	case SM_UPDATE_NONE:
+		return "none";
+	case SM_UPDATE_UNSPECIFIED:
+	case SM_UPDATE_COMMAND:
+		BUG("init_submodule() should handle type %d", type);
+	default:
+		BUG("unexpected update strategy type: %d", type);
+	}
+}
+
 static void init_submodule(const char *path, const char *prefix,
 			   unsigned int flags)
 {
 	const struct submodule *sub;
 	struct strbuf sb = STRBUF_INIT;
-	char *upd = NULL, *url = NULL, *displaypath;
+	const char *upd;
+	char *url = NULL, *displaypath;
 
 	displaypath = get_submodule_displaypath(path, prefix);
 
@@ -474,14 +494,14 @@ static void init_submodule(const char *path, const char *prefix,
 
 	/* Copy "update" setting when it is not set yet */
 	strbuf_addf(&sb, "submodule.%s.update", sub->name);
-	if (git_config_get_string(sb.buf, &upd) &&
+	if (git_config_get_string_tmp(sb.buf, &upd) &&
 	    sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
 		if (sub->update_strategy.type == SM_UPDATE_COMMAND) {
 			fprintf(stderr, _("warning: command update mode suggested for submodule '%s'\n"),
 				sub->name);
-			upd = xstrdup("none");
+			upd = "none";
 		} else {
-			upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy));
+			upd = submodule_strategy_to_string(sub->update_strategy.type);
 		}
 
 		if (git_config_set_gently(sb.buf, upd))
@@ -490,7 +510,6 @@ static void init_submodule(const char *path, const char *prefix,
 	strbuf_release(&sb);
 	free(displaypath);
 	free(url);
-	free(upd);
 }
 
 static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
diff --git a/submodule.c b/submodule.c
index 3fa5db3ecdf..e297d94d17f 100644
--- a/submodule.c
+++ b/submodule.c
@@ -415,27 +415,6 @@ int parse_submodule_update_strategy(const char *value,
 	return 0;
 }
 
-const char *submodule_strategy_to_string(const struct submodule_update_strategy *s)
-{
-	struct strbuf sb = STRBUF_INIT;
-	switch (s->type) {
-	case SM_UPDATE_CHECKOUT:
-		return "checkout";
-	case SM_UPDATE_MERGE:
-		return "merge";
-	case SM_UPDATE_REBASE:
-		return "rebase";
-	case SM_UPDATE_NONE:
-		return "none";
-	case SM_UPDATE_UNSPECIFIED:
-		return NULL;
-	case SM_UPDATE_COMMAND:
-		strbuf_addf(&sb, "!%s", s->command);
-		return strbuf_detach(&sb, NULL);
-	}
-	return NULL;
-}
-
 void handle_ignore_submodules_arg(struct diff_options *diffopt,
 				  const char *arg)
 {
diff --git a/submodule.h b/submodule.h
index bfaa9da1868..949f67b8031 100644
--- a/submodule.h
+++ b/submodule.h
@@ -72,7 +72,6 @@ void die_path_inside_submodule(struct index_state *istate,
 enum submodule_update_type parse_submodule_update_type(const char *value);
 int parse_submodule_update_strategy(const char *value,
 				    struct submodule_update_strategy *dst);
-const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);
 void handle_ignore_submodules_arg(struct diff_options *, const char *);
 void show_submodule_diff_summary(struct diff_options *o, const char *path,
 			    struct object_id *one, struct object_id *two,
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 23/28] submodule--helper: use "code" in run_update_command()
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (21 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 22/28] submodule--helper: move submodule_strategy_to_string() to only user Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 24/28] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
                     ` (4 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Apply some DRY principles in run_update_command() and don't have two
"switch" statements over "ud->update_strategy.type" determine the same
thing.

First we were setting "must_die_on_failure = 1" in all cases except
"SM_UPDATE_CHECKOUT" (and we'd BUG(...) out on the rest). This code
was added in c51f8f94e5b (submodule--helper: run update procedures
from C, 2021-08-24).

Then we'd duplicate same "switch" logic when we were using the
"must_die_on_failure" variable.

Let's instead have the "case" branches in that inner "switch"
determine whether or not the "update must continue" by picking an exit
code.

This also mostly avoids hardcoding the "128" exit code, instead we can
make use of the return value of the die_message() function, which
we've been calling here since 55b3f12cb54 (submodule update: use
die_message(), 2022-03-15). We're still hardcoding it to determine if
we "exit()", but subsequent commit(s) will address that.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d787c0fead4..bac45e2bab7 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2145,7 +2145,6 @@ static int run_update_command(struct update_data *ud, int subforce)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
-	int must_die_on_failure = 0;
 
 	switch (ud->update_strategy.type) {
 	case SM_UPDATE_CHECKOUT:
@@ -2159,19 +2158,16 @@ static int run_update_command(struct update_data *ud, int subforce)
 		strvec_push(&cp.args, "rebase");
 		if (ud->quiet)
 			strvec_push(&cp.args, "--quiet");
-		must_die_on_failure = 1;
 		break;
 	case SM_UPDATE_MERGE:
 		cp.git_cmd = 1;
 		strvec_push(&cp.args, "merge");
 		if (ud->quiet)
 			strvec_push(&cp.args, "--quiet");
-		must_die_on_failure = 1;
 		break;
 	case SM_UPDATE_COMMAND:
 		cp.use_shell = 1;
 		strvec_push(&cp.args, ud->update_strategy.command);
-		must_die_on_failure = 1;
 		break;
 	default:
 		BUG("unexpected update strategy type: %d",
@@ -2182,32 +2178,35 @@ static int run_update_command(struct update_data *ud, int subforce)
 	cp.dir = xstrdup(ud->sm_path);
 	prepare_submodule_repo_env(&cp.env);
 	if (run_command(&cp)) {
+		int ret;
+
 		switch (ud->update_strategy.type) {
 		case SM_UPDATE_CHECKOUT:
 			die_message(_("Unable to checkout '%s' in submodule path '%s'"),
 				    oid, ud->displaypath);
+			/* the command failed, but update must continue */
+			ret = 1;
 			break;
 		case SM_UPDATE_REBASE:
-			die_message(_("Unable to rebase '%s' in submodule path '%s'"),
-			    oid, ud->displaypath);
+			ret = die_message(_("Unable to rebase '%s' in submodule path '%s'"),
+					  oid, ud->displaypath);
 			break;
 		case SM_UPDATE_MERGE:
-			die_message(_("Unable to merge '%s' in submodule path '%s'"),
-			    oid, ud->displaypath);
+			ret = die_message(_("Unable to merge '%s' in submodule path '%s'"),
+					  oid, ud->displaypath);
 			break;
 		case SM_UPDATE_COMMAND:
-			die_message(_("Execution of '%s %s' failed in submodule path '%s'"),
-			    ud->update_strategy.command, oid, ud->displaypath);
+			ret = die_message(_("Execution of '%s %s' failed in submodule path '%s'"),
+					  ud->update_strategy.command, oid, ud->displaypath);
 			break;
 		default:
 			BUG("unexpected update strategy type: %d",
 			    ud->update_strategy.type);
 		}
-		if (must_die_on_failure)
-			exit(128);
 
-		/* the command failed, but update must continue */
-		return 1;
+		if (ret == 128)
+			exit(ret);
+		return ret;
 	}
 
 	if (ud->quiet)
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 24/28] submodule--helper: don't exit() on failure, return
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (22 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 23/28] submodule--helper: use "code" in run_update_command() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 25/28] submodule--helper: libify determine_submodule_update_strategy() Ævar Arnfjörð Bjarmason
                     ` (3 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Change code downstream of module_update() to short-circuit and return
to the top-level on failure, rather than calling exit().

To do so we need to diligently check whether we "must_die_on_failure",
which is a pattern started in c51f8f94e5b (submodule--helper: run
update procedures from C, 2021-08-24), but which hadn't been completed
to the point where we could avoid calling exit() here.

This introduces no functional changes, but makes it easier to both
call these routines as a library in the future, and to eventually
avoid leaking memory.

This and similar control flow in submodule--helper.c could be made
simpler by properly "libifying" it, i.e. to have it consistently
return -1 on failures, and to early return on any non-success.

But let's leave that larger project for now, and (mostly) emulate what
were doing with the "exit(128)" before this change.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index bac45e2bab7..8d83f1f99d2 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2141,7 +2141,8 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	return run_command(&cp);
 }
 
-static int run_update_command(struct update_data *ud, int subforce)
+static int run_update_command(struct update_data *ud, int subforce,
+			      int *must_die_on_failure)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
@@ -2205,7 +2206,7 @@ static int run_update_command(struct update_data *ud, int subforce)
 		}
 
 		if (ret == 128)
-			exit(ret);
+			*must_die_on_failure = 1;
 		return ret;
 	}
 
@@ -2237,7 +2238,8 @@ static int run_update_command(struct update_data *ud, int subforce)
 	return 0;
 }
 
-static int run_update_procedure(struct update_data *ud)
+static int run_update_procedure(struct update_data *ud,
+				int *must_die_on_failure)
 {
 	int subforce = is_null_oid(&ud->suboid) || ud->force;
 
@@ -2264,7 +2266,7 @@ static int run_update_procedure(struct update_data *ud)
 			    ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
-	return run_update_command(ud, subforce);
+	return run_update_command(ud, subforce, must_die_on_failure);
 }
 
 static const char *remote_submodule_branch(const char *path)
@@ -2400,7 +2402,8 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 				    "--no-single-branch");
 }
 
-static int update_submodule(struct update_data *update_data)
+static int update_submodule(struct update_data *update_data,
+			    int *must_die_on_failure)
 {
 	ensure_core_worktree(update_data->sm_path);
 
@@ -2436,9 +2439,15 @@ static int update_submodule(struct update_data *update_data)
 		free(remote_ref);
 	}
 
-	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force)
-		if (run_update_procedure(update_data))
+	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
+		int ret;
+
+		ret = run_update_procedure(update_data, must_die_on_failure);
+		if (*must_die_on_failure)
+			return ret;
+		if (ret)
 			return 1;
+	}
 
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
@@ -2461,7 +2470,7 @@ static int update_submodule(struct update_data *update_data)
 		die_message(_("Failed to recurse into submodule path '%s'"),
 			    update_data->displaypath);
 		if (ret == 128)
-			exit(ret);
+			*must_die_on_failure = 1;
 		return ret;
 	}
 
@@ -2494,12 +2503,19 @@ static int update_submodules(struct update_data *update_data)
 
 	for (i = 0; i < suc.update_clone_nr; i++) {
 		struct update_clone_data ucd = suc.update_clone[i];
+		int must_die_on_failure = 0;
+		int code;
 
 		oidcpy(&update_data->oid, &ucd.oid);
 		update_data->just_cloned = ucd.just_cloned;
 		update_data->sm_path = ucd.sub->path;
 
-		if (update_submodule(update_data))
+		code = update_submodule(update_data, &must_die_on_failure);
+		if (code)
+			ret = code;
+		if (must_die_on_failure)
+			goto cleanup;
+		else if (code)
 			ret = 1;
 	}
 
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 25/28] submodule--helper: libify determine_submodule_update_strategy()
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (23 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 24/28] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 26/28] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
                     ` (2 subsequent siblings)
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Libify the determine_submodule_update_strategy() by having it invoke
die_message() rather than die(), and returning the code die_message()
returns on failure.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 39 ++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 8d83f1f99d2..2b78fa7573f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1749,24 +1749,27 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static void determine_submodule_update_strategy(struct repository *r,
-						int just_cloned,
-						const char *path,
-						enum submodule_update_type update,
-						struct submodule_update_strategy *out)
+static int determine_submodule_update_strategy(struct repository *r,
+					       int just_cloned,
+					       const char *path,
+					       enum submodule_update_type update,
+					       struct submodule_update_strategy *out)
 {
 	const struct submodule *sub = submodule_from_path(r, null_oid(), path);
 	char *key;
 	const char *val;
+	int ret;
 
 	key = xstrfmt("submodule.%s.update", sub->name);
 
 	if (update) {
 		out->type = update;
 	} else if (!repo_config_get_string_tmp(r, key, &val)) {
-		if (parse_submodule_update_strategy(val, out) < 0)
-			die(_("Invalid update mode '%s' configured for submodule path '%s'"),
-				val, path);
+		if (parse_submodule_update_strategy(val, out) < 0) {
+			ret = die_message(_("Invalid update mode '%s' configured for submodule path '%s'"),
+					  val, path);
+			goto cleanup;
+		}
 	} else if (sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
 		if (sub->update_strategy.type == SM_UPDATE_COMMAND)
 			BUG("how did we read update = !command from .gitmodules?");
@@ -1781,7 +1784,10 @@ static void determine_submodule_update_strategy(struct repository *r,
 	     out->type == SM_UPDATE_NONE))
 		out->type = SM_UPDATE_CHECKOUT;
 
+	ret = 0;
+cleanup:
 	free(key);
+	return ret;
 }
 
 struct update_clone_data {
@@ -2405,14 +2411,22 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 static int update_submodule(struct update_data *update_data,
 			    int *must_die_on_failure)
 {
+	int ret;
+
 	ensure_core_worktree(update_data->sm_path);
 
 	update_data->displaypath = get_submodule_displaypath(
 		update_data->sm_path, update_data->prefix);
 
-	determine_submodule_update_strategy(the_repository, update_data->just_cloned,
-					    update_data->sm_path, update_data->update_default,
-					    &update_data->update_strategy);
+	ret = determine_submodule_update_strategy(the_repository,
+						  update_data->just_cloned,
+						  update_data->sm_path,
+						  update_data->update_default,
+						  &update_data->update_strategy);
+	if (ret) {
+		*must_die_on_failure = 1;
+		return ret;
+	}
 
 	if (update_data->just_cloned)
 		oidcpy(&update_data->suboid, null_oid());
@@ -2440,8 +2454,6 @@ static int update_submodule(struct update_data *update_data,
 	}
 
 	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
-		int ret;
-
 		ret = run_update_procedure(update_data, must_die_on_failure);
 		if (*must_die_on_failure)
 			return ret;
@@ -2452,7 +2464,6 @@ static int update_submodule(struct update_data *update_data,
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		struct update_data next = *update_data;
-		int ret;
 
 		next.prefix = NULL;
 		oidcpy(&next.oid, null_oid());
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 26/28] submodule--helper: libify "must_die_on_failure" code paths
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (24 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 25/28] submodule--helper: libify determine_submodule_update_strategy() Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-03  4:37     ` Glen Choo
  2022-08-02 15:46   ` [PATCH v2 27/28] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
  2022-08-02 15:46   ` [PATCH v2 28/28] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
  27 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

In preceding commits the codepaths around update_submodules() were
changed from using exit() or die() to ferrying up a
"must_die_on_failure" in the cases where we'd exit(), and in most
cases where we'd die().

We needed to do this this to ensure that we'd early exit or otherwise
abort the update_submodules() processing before it was completed.

Now that those preceding changes have shown that we've converted those
paths, we can remove the remaining "ret == 128" special-cases, leaving
the only such special-case in update_submodules(). I.e. we now know
after having gone through the various codepaths that we were only
returning 128 if we meant to early abort.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 33 +++++++++++----------------------
 1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2b78fa7573f..79a11992d1c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2147,8 +2147,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	return run_command(&cp);
 }
 
-static int run_update_command(struct update_data *ud, int subforce,
-			      int *must_die_on_failure)
+static int run_update_command(struct update_data *ud, int subforce)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
@@ -2211,8 +2210,6 @@ static int run_update_command(struct update_data *ud, int subforce,
 			    ud->update_strategy.type);
 		}
 
-		if (ret == 128)
-			*must_die_on_failure = 1;
 		return ret;
 	}
 
@@ -2244,8 +2241,7 @@ static int run_update_command(struct update_data *ud, int subforce,
 	return 0;
 }
 
-static int run_update_procedure(struct update_data *ud,
-				int *must_die_on_failure)
+static int run_update_procedure(struct update_data *ud)
 {
 	int subforce = is_null_oid(&ud->suboid) || ud->force;
 
@@ -2272,7 +2268,7 @@ static int run_update_procedure(struct update_data *ud,
 			    ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
-	return run_update_command(ud, subforce, must_die_on_failure);
+	return run_update_command(ud, subforce);
 }
 
 static const char *remote_submodule_branch(const char *path)
@@ -2408,8 +2404,7 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 				    "--no-single-branch");
 }
 
-static int update_submodule(struct update_data *update_data,
-			    int *must_die_on_failure)
+static int update_submodule(struct update_data *update_data)
 {
 	int ret;
 
@@ -2454,11 +2449,9 @@ static int update_submodule(struct update_data *update_data,
 	}
 
 	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
-		ret = run_update_procedure(update_data, must_die_on_failure);
-		if (*must_die_on_failure)
-			return ret;
+		ret = run_update_procedure(update_data);
 		if (ret)
-			return 1;
+			return ret;
 	}
 
 	if (update_data->recursive) {
@@ -2476,12 +2469,9 @@ static int update_submodule(struct update_data *update_data,
 
 		/* die() if child process die()'d */
 		ret = run_command(&cp);
-		if (!ret)
-			return 0;
-		die_message(_("Failed to recurse into submodule path '%s'"),
-			    update_data->displaypath);
-		if (ret == 128)
-			*must_die_on_failure = 1;
+		if (ret)
+			die_message(_("Failed to recurse into submodule path '%s'"),
+				    update_data->displaypath);
 		return ret;
 	}
 
@@ -2514,17 +2504,16 @@ static int update_submodules(struct update_data *update_data)
 
 	for (i = 0; i < suc.update_clone_nr; i++) {
 		struct update_clone_data ucd = suc.update_clone[i];
-		int must_die_on_failure = 0;
 		int code;
 
 		oidcpy(&update_data->oid, &ucd.oid);
 		update_data->just_cloned = ucd.just_cloned;
 		update_data->sm_path = ucd.sub->path;
 
-		code = update_submodule(update_data, &must_die_on_failure);
+		code = update_submodule(update_data);
 		if (code)
 			ret = code;
-		if (must_die_on_failure)
+		if (code == 128)
 			goto cleanup;
 		else if (code)
 			ret = 1;
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 27/28] submodule--helper: libify "must_die_on_failure" code paths (for die)
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (25 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 26/28] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  2022-08-03  4:32     ` Glen Choo
  2022-08-02 15:46   ` [PATCH v2 28/28] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
  27 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Continue the libification of codepaths that previously relied on
"must_die_on_failure". In these cases we've always been early aborting
by calling die(), but as we know that these codpaths will properly
handle return codes of 128 to mean an early abort let's have them use
die_message() instead.

This still isn't a complete migration away from die() for these
codepaths, in particular this code in update_submodule() will still call die() in some cases:

	char *remote_name = get_default_remote_submodule(update_data->sm_path);
	const char *branch = remote_submodule_branch(update_data->sm_path);

But as that code is used by other callers than the "update" code let's
leave converting it for now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 79a11992d1c..4f7ece6fb05 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2263,9 +2263,9 @@ static int run_update_procedure(struct update_data *ud)
 		 */
 		if (!is_tip_reachable(ud->sm_path, &ud->oid) &&
 		    fetch_in_submodule(ud->sm_path, ud->depth, ud->quiet, &ud->oid))
-			die(_("Fetched in submodule path '%s', but it did not "
-			      "contain %s. Direct fetching of that commit failed."),
-			    ud->displaypath, oid_to_hex(&ud->oid));
+			return die_message(_("Fetched in submodule path '%s', but it did not "
+					     "contain %s. Direct fetching of that commit failed."),
+					   ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
 	return run_update_command(ud, subforce);
@@ -2309,13 +2309,14 @@ static const char *remote_submodule_branch(const char *path)
 	return branch;
 }
 
-static void ensure_core_worktree(const char *path)
+static int ensure_core_worktree(const char *path)
 {
 	const char *cw;
 	struct repository subrepo;
 
 	if (repo_submodule_init(&subrepo, the_repository, path, null_oid()))
-		die(_("could not get a repository handle for submodule '%s'"), path);
+		return die_message(_("could not get a repository handle for submodule '%s'"),
+				   path);
 
 	if (!repo_config_get_string_tmp(&subrepo, "core.worktree", &cw)) {
 		char *cfg_file, *abs_path;
@@ -2333,6 +2334,8 @@ static void ensure_core_worktree(const char *path)
 		free(abs_path);
 		strbuf_release(&sb);
 	}
+
+	return 0;
 }
 
 static const char *submodule_update_type_to_label(enum submodule_update_type type)
@@ -2408,7 +2411,9 @@ static int update_submodule(struct update_data *update_data)
 {
 	int ret;
 
-	ensure_core_worktree(update_data->sm_path);
+	ret = ensure_core_worktree(update_data->sm_path);
+	if (ret)
+		return ret;
 
 	update_data->displaypath = get_submodule_displaypath(
 		update_data->sm_path, update_data->prefix);
@@ -2418,16 +2423,14 @@ static int update_submodule(struct update_data *update_data)
 						  update_data->sm_path,
 						  update_data->update_default,
 						  &update_data->update_strategy);
-	if (ret) {
-		*must_die_on_failure = 1;
+	if (ret)
 		return ret;
-	}
 
 	if (update_data->just_cloned)
 		oidcpy(&update_data->suboid, null_oid());
 	else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid))
-		die(_("Unable to find current revision in submodule path '%s'"),
-			update_data->displaypath);
+		return die_message(_("Unable to find current revision in submodule path '%s'"),
+				   update_data->displaypath);
 
 	if (update_data->remote) {
 		char *remote_name = get_default_remote_submodule(update_data->sm_path);
@@ -2437,13 +2440,13 @@ static int update_submodule(struct update_data *update_data)
 		if (!update_data->nofetch) {
 			if (fetch_in_submodule(update_data->sm_path, update_data->depth,
 					      0, NULL))
-				die(_("Unable to fetch in submodule path '%s'"),
-				    update_data->sm_path);
+				return die_message(_("Unable to fetch in submodule path '%s'"),
+						   update_data->sm_path);
 		}
 
 		if (resolve_gitlink_ref(update_data->sm_path, remote_ref, &update_data->oid))
-			die(_("Unable to find %s revision in submodule path '%s'"),
-			    remote_ref, update_data->sm_path);
+			return die_message(_("Unable to find %s revision in submodule path '%s'"),
+					   remote_ref, update_data->sm_path);
 
 		free(remote_ref);
 	}
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v2 28/28] submodule--helper: fix bad config API usage
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
                     ` (26 preceding siblings ...)
  2022-08-02 15:46   ` [PATCH v2 27/28] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
@ 2022-08-02 15:46   ` Ævar Arnfjörð Bjarmason
  27 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-02 15:46 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Fix bad config API usage added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06). After
git_config_get_string() returns successfully we know the "char **dest"
will be non-NULL.

A coccinelle patch that transforms this turns up a couple of other
such issues, one in fetch-pack.c, and another in upload-pack.c:

	@@
	identifier F =~ "^(repo|git)_config_get_string(_tmp)?$";
	identifier V;
	@@
	  !F(..., &V)
	- && (V)

But let's focus narrowly on submodule--helper for now, we can fix
those some other time.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 4f7ece6fb05..5bc9cc41369 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3098,7 +3098,7 @@ static void configure_added_submodule(struct add_data *add_data)
 	 * is_submodule_active(), since that function needs to find
 	 * out the value of "submodule.active" again anyway.
 	 */
-	if (!git_config_get_string("submodule.active", &val) && val) {
+	if (!git_config_get_string("submodule.active", &val)) {
 		/*
 		 * If the submodule being added isn't already covered by the
 		 * current configured pathspec, set the submodule's active flag
-- 
2.37.1.1233.ge8b09efaedc


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* Re: [PATCH v2 01/28] submodule tests: test usage behavior
  2022-08-02 15:45   ` [PATCH v2 01/28] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
@ 2022-08-02 22:30     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-02 22:30 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Test what exit code and output we emit on "git submodule -h", how we
> handle "--" when no subcommand is specified, and how the top-level
> "--recursive" option is handled.
>
> For "-h" this doesn't make sense, but let's test for it so that any
> subsequent eventual behavior change will become clear.
>
> For "--" this follows up on 68cabbfda36 (submodule: document default
> behavior, 2019-02-15) and tests that "status" doesn't don't support

s/doesn't don't/doesn't/ I assume ;)

> the "--" delimiter. There's no intrinsically good reason not to
> support that. We behave this way due to edge cases in
> git-submodule.sh's implementation, but as with "-h" let's assert our
> current long-standing behavior for now.
>
> For "--recursive" the exclusion of it from the top-level appears to
> have been an omission in 15fc56a8536 (git submodule foreach: Add
> --recursive to recurse into nested submodules, 2009-08-19), there
> doesn't seem to be a reason not to support it alongside "--quiet" and
> "--cached", but let's likewise assert our existing behavior for now.

I think my original comment isn't directly addressed here:

  I'm not sure about this one. "--recursive" isn't a top level option, and
  15fc56a8536 doesn't seem to suggest that it was meant to be one (but I
  did realize that git-submodule.txt documents all of the options to all
  subcommands, which is very confusing.)

But maybe I'm mistaken and it's somewhere. Do we know whether
"--recursive" was always intended to be top-level?

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  t/t7400-submodule-basic.sh | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
>
> diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
> index e7cec2e457a..b858871a953 100755
> --- a/t/t7400-submodule-basic.sh
> +++ b/t/t7400-submodule-basic.sh
> @@ -14,6 +14,32 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>  
>  . ./test-lib.sh
>  
> +test_expect_success 'submodule usage: -h' '
> +	git submodule -h >out 2>err &&
> +	grep "^usage: git submodule" out &&
> +	test_must_be_empty err
> +'
> +
> +test_expect_success 'submodule usage: --recursive' '
> +	test_expect_code 1 git submodule --recursive >out 2>err &&
> +	grep "^usage: git submodule" err &&
> +	test_must_be_empty out
> +'
> +
> +test_expect_success 'submodule usage: status --' '
> +	test_expect_code 1 git submodule -- &&
> +	test_expect_code 1 git submodule --end-of-options
> +'
> +
> +for opt in '--quiet' '--cached'
> +do
> +	test_expect_success "submodule usage: status $opt" '
> +		git submodule $opt &&
> +		git submodule status $opt &&
> +		git submodule $opt status
> +	'
> +done
> +
>  test_expect_success 'submodule deinit works on empty repository' '
>  	git submodule deinit --all
>  '

The changes themselves look good :)

> -- 
> 2.37.1.1233.ge8b09efaedc

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v2 08/28] submodule--helper: move "resolve-relative-url-test" to a test-tool
  2022-08-02 15:45   ` [PATCH v2 08/28] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
@ 2022-08-02 22:32     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-02 22:32 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> As its name suggests the "resolve-relative-url-test" has never been
> used outside of the test suite, see 63e95beb085 (submodule: port
> resolve_relative_url from shell to C, 2016-04-15) for its original
> addition.
>
> Perhaps it would make sense to drop this code entirely, as we feel
> that we've got enough indirect test coverage, but let's leave that
> question to a possible follow-up change. For now let's keep the test
> coverage this gives us.

Agree with this and the other related messages that describe the intent
behind the test code. Thanks!

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 23 --------------------
>  t/helper/test-submodule.c   | 42 +++++++++++++++++++++++++++++++++++++
>  t/t0060-path-utils.sh       |  2 +-
>  3 files changed, 43 insertions(+), 24 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 06307886080..246457ec2e9 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -96,28 +96,6 @@ static char *resolve_relative_url(const char *rel_url, const char *up_path, int
>  	return resolved_url;
>  }
>  
> -static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
> -{
> -	char *remoteurl, *res;
> -	const char *up_path, *url;
> -
> -	if (argc != 4)
> -		die("resolve-relative-url-test only accepts three arguments: <up_path> <remoteurl> <url>");
> -
> -	up_path = argv[1];
> -	remoteurl = xstrdup(argv[2]);
> -	url = argv[3];
> -
> -	if (!strcmp(up_path, "(null)"))
> -		up_path = NULL;
> -
> -	res = relative_url(remoteurl, url, up_path);
> -	puts(res);
> -	free(res);
> -	free(remoteurl);
> -	return 0;
> -}
> -
>  /* the result should be freed by the caller. */
>  static char *get_submodule_displaypath(const char *path, const char *prefix)
>  {
> @@ -3273,7 +3251,6 @@ static struct cmd_struct commands[] = {
>  	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
>  	{"add", module_add, 0},
>  	{"update", module_update, SUPPORT_SUPER_PREFIX},
> -	{"resolve-relative-url-test", resolve_relative_url_test, 0},
>  	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
>  	{"init", module_init, 0},
>  	{"status", module_status, SUPPORT_SUPER_PREFIX},
> diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
> index 9f0eb440192..e0e0c53d386 100644
> --- a/t/helper/test-submodule.c
> +++ b/t/helper/test-submodule.c
> @@ -2,6 +2,7 @@
>  #include "test-tool-utils.h"
>  #include "cache.h"
>  #include "parse-options.h"
> +#include "remote.h"
>  #include "submodule-config.h"
>  #include "submodule.h"
>  
> @@ -19,9 +20,17 @@ static const char *submodule_is_active_usage[] = {
>  	NULL
>  };
>  
> +#define TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE \
> +	"test-tool submodule resolve-relative-url <up_path> <remoteurl> <url>"
> +static const char *submodule_resolve_relative_url_usage[] = {
> +	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
> +	NULL,
> +};
> +
>  static const char *submodule_usage[] = {
>  	TEST_TOOL_CHECK_NAME_USAGE,
>  	TEST_TOOL_IS_ACTIVE_USAGE,
> +	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
>  	NULL
>  };
>  
> @@ -76,9 +85,42 @@ static int cmd__submodule_is_active(int argc, const char **argv)
>  	return !is_submodule_active(the_repository, argv[0]);
>  }
>  
> +static int resolve_relative_url(int argc, const char **argv)
> +{
> +	char *remoteurl, *res;
> +	const char *up_path, *url;
> +
> +	up_path = argv[0];
> +	remoteurl = xstrdup(argv[1]);
> +	url = argv[2];
> +
> +	if (!strcmp(up_path, "(null)"))
> +		up_path = NULL;
> +
> +	res = relative_url(remoteurl, url, up_path);
> +	puts(res);
> +	free(res);
> +	free(remoteurl);
> +	return 0;
> +}
> +
> +static int cmd__submodule_resolve_relative_url(int argc, const char **argv)
> +{
> +	struct option options[] = {
> +		OPT_END()
> +	};
> +	argc = parse_options(argc, argv, "test-tools", options,
> +			     submodule_resolve_relative_url_usage, 0);
> +	if (argc != 3)
> +		usage_with_options(submodule_resolve_relative_url_usage, options);
> +
> +	return resolve_relative_url(argc, argv);
> +}
> +
>  static struct test_cmd cmds[] = {
>  	{ "check-name", cmd__submodule_check_name },
>  	{ "is-active", cmd__submodule_is_active },
> +	{ "resolve-relative-url", cmd__submodule_resolve_relative_url},
>  };
>  
>  int cmd__submodule(int argc, const char **argv)
> diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
> index 1f2007e62b7..68e29c904a6 100755
> --- a/t/t0060-path-utils.sh
> +++ b/t/t0060-path-utils.sh
> @@ -22,7 +22,7 @@ relative_path() {
>  
>  test_submodule_relative_url() {
>  	test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" "
> -		actual=\$(git submodule--helper resolve-relative-url-test '$1' '$2' '$3') &&
> +		actual=\$(test-tool submodule resolve-relative-url '$1' '$2' '$3') &&
>  		test \"\$actual\" = '$4'
>  	"
>  }
> -- 
> 2.37.1.1233.ge8b09efaedc

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v2 21/28] submodule--helper: don't call submodule_strategy_to_string() in BUG()
  2022-08-02 15:46   ` [PATCH v2 21/28] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
@ 2022-08-02 23:08     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-02 23:08 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Don't call submodule_strategy_to_string() in a BUG() message. These
> calls added in c51f8f94e5b (submodule--helper: run update procedures
> from C, 2021-08-24) don't need the extra information
> submodule_strategy_to_string() gives us, as we'll never reach the
> SM_UPDATE_COMMAND case here.
>
> That case is the only one where we'd get any information beyond the
> straightforward number-to-string mapping.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 955deb375ee..b49528e1ba9 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2155,8 +2155,8 @@ static int run_update_command(struct update_data *ud, int subforce)
>  		must_die_on_failure = 1;
>  		break;
>  	default:
> -		BUG("unexpected update strategy type: %s",
> -		    submodule_strategy_to_string(&ud->update_strategy));
> +		BUG("unexpected update strategy type: %d",
> +		    ud->update_strategy.type);
>  	}

At first I worried that we would be losing readability by printing the
raw int value instead of a string, but then I remembered that we
probably wouldn't print anything sensible for an unknown value anyway :x

What makes this change obviously good is that we're switching on
ud->update_strategy.type, so it makes the most sense to print that value
(instead of ud->update_strategy). Unfortunately we can't see that from
the context lines though.

>  	strvec_push(&cp.args, oid);
>  
> @@ -2181,8 +2181,8 @@ static int run_update_command(struct update_data *ud, int subforce)
>  			    ud->update_strategy.command, oid, ud->displaypath);
>  			break;
>  		default:
> -			BUG("unexpected update strategy type: %s",
> -			    submodule_strategy_to_string(&ud->update_strategy));
> +			BUG("unexpected update strategy type: %d",
> +			    ud->update_strategy.type);
>  		}
>  		if (must_die_on_failure)
>  			exit(128);
> @@ -2212,8 +2212,8 @@ static int run_update_command(struct update_data *ud, int subforce)
>  		       ud->displaypath, ud->update_strategy.command, oid);
>  		break;
>  	default:
> -		BUG("unexpected update strategy type: %s",
> -		    submodule_strategy_to_string(&ud->update_strategy));
> +		BUG("unexpected update strategy type: %d",
> +		    ud->update_strategy.type);
>  	}
>  
>  	return 0;
> -- 
> 2.37.1.1233.ge8b09efaedc

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v2 22/28] submodule--helper: move submodule_strategy_to_string() to only user
  2022-08-02 15:46   ` [PATCH v2 22/28] submodule--helper: move submodule_strategy_to_string() to only user Ævar Arnfjörð Bjarmason
@ 2022-08-02 23:30     ` Glen Choo
  2022-08-03 13:06       ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 142+ messages in thread
From: Glen Choo @ 2022-08-02 23:30 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Move the submodule_strategy_to_string() function added in
> 3604242f080 (submodule: port init from shell to C, 2016-04-15) to its
> only user.
>
> This function would return NULL on SM_UPDATE_UNSPECIFIED, so it wasn't
> safe to xstrdup() its return value in the general case, or to use it
> in a sprintf() format as the code removed in the preceding commit did.
>
> But its callers would never call it with either SM_UPDATE_UNSPECIFIED
> or SM_UPDATE_COMMAND. Let's move it to a "static" helper, and have its
> functionality reflect how it's used, and BUG() out on the rest.
>
> By doing this we can also stop needlessly xstrdup()-ing and free()-ing
> the memory for the config we're setting. We can instead always use
> constant strings. We can also use the *_tmp() variant of
> git_config_get_string().
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 29 ++++++++++++++++++++++++-----
>  submodule.c                 | 21 ---------------------
>  submodule.h                 |  1 -
>  3 files changed, 24 insertions(+), 27 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index b49528e1ba9..d787c0fead4 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -413,12 +413,32 @@ struct init_cb {
>  };
>  #define INIT_CB_INIT { 0 }
>  
> +static const char *submodule_strategy_to_string(enum submodule_update_type type)
> +{
> +	switch (type) {
> +	case SM_UPDATE_CHECKOUT:
> +		return "checkout";
> +	case SM_UPDATE_MERGE:
> +		return "merge";
> +	case SM_UPDATE_REBASE:
> +		return "rebase";
> +	case SM_UPDATE_NONE:
> +		return "none";
> +	case SM_UPDATE_UNSPECIFIED:
> +	case SM_UPDATE_COMMAND:
> +		BUG("init_submodule() should handle type %d", type);
> +	default:
> +		BUG("unexpected update strategy type: %d", type);
> +	}
> +}
> +

This function is meant to convert from an update strategy back to the
string that the user actually provided in their gitconfig.

The change in behavior makes this function BUG() out on types that
aren't "magic" tokens, i.e. "UNSPECIFIED" (which is obviously not
expressible) and "COMMAND" (which allows users to specify an arbitrary
command using "!", like "!cat"). It shouldn't be difficult to teach
callers to handle "COMMAND", so this seems like an ok change, though I
think we should probably amend the function name to
submodule_update_type_to_string() and change the UNSPECIFIED and COMMAND
arms to something like BUG("type %d has no corresponding string").

I'm not so convinced that this function should be static, though. I
think it's more natural for submodule_update_type_to_string() to have
the same visibility as enum submodule_update_type. Today, we only have
one other caller who uses this enum, and it doesn't even need this
_to_string() fn (fsck.c calls parse_submodule_update_type() and doesn't
need _to_string() because it has the raw config values). But it feels a
bit inevitable that this will get moved back to submodule.h.

>  static void init_submodule(const char *path, const char *prefix,
>  			   unsigned int flags)
>  {
>  	const struct submodule *sub;
>  	struct strbuf sb = STRBUF_INIT;
> -	char *upd = NULL, *url = NULL, *displaypath;
> +	const char *upd;
> +	char *url = NULL, *displaypath;
>  
>  	displaypath = get_submodule_displaypath(path, prefix);
>  
> @@ -474,14 +494,14 @@ static void init_submodule(const char *path, const char *prefix,
>  
>  	/* Copy "update" setting when it is not set yet */
>  	strbuf_addf(&sb, "submodule.%s.update", sub->name);
> -	if (git_config_get_string(sb.buf, &upd) &&
> +	if (git_config_get_string_tmp(sb.buf, &upd) &&
>  	    sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
>  		if (sub->update_strategy.type == SM_UPDATE_COMMAND) {
>  			fprintf(stderr, _("warning: command update mode suggested for submodule '%s'\n"),
>  				sub->name);
> -			upd = xstrdup("none");
> +			upd = "none";
>  		} else {
> -			upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy));
> +			upd = submodule_strategy_to_string(sub->update_strategy.type);
>  		}
>  
>  		if (git_config_set_gently(sb.buf, upd))
> @@ -490,7 +510,6 @@ static void init_submodule(const char *path, const char *prefix,
>  	strbuf_release(&sb);
>  	free(displaypath);
>  	free(url);
> -	free(upd);
>  }
>  
>  static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
> diff --git a/submodule.c b/submodule.c
> index 3fa5db3ecdf..e297d94d17f 100644
> --- a/submodule.c
> +++ b/submodule.c
> @@ -415,27 +415,6 @@ int parse_submodule_update_strategy(const char *value,
>  	return 0;
>  }
>  
> -const char *submodule_strategy_to_string(const struct submodule_update_strategy *s)
> -{
> -	struct strbuf sb = STRBUF_INIT;
> -	switch (s->type) {
> -	case SM_UPDATE_CHECKOUT:
> -		return "checkout";
> -	case SM_UPDATE_MERGE:
> -		return "merge";
> -	case SM_UPDATE_REBASE:
> -		return "rebase";
> -	case SM_UPDATE_NONE:
> -		return "none";
> -	case SM_UPDATE_UNSPECIFIED:
> -		return NULL;
> -	case SM_UPDATE_COMMAND:
> -		strbuf_addf(&sb, "!%s", s->command);
> -		return strbuf_detach(&sb, NULL);
> -	}
> -	return NULL;
> -}
> -

The rest of the changes look good. An alternative would be to _always_
return a non-const char * (e.g. return xstrdup("none")) and expect the
caller to free it, but that feels like bending over backwards to
accomodate xstrfmt("!%s").

>  void handle_ignore_submodules_arg(struct diff_options *diffopt,
>  				  const char *arg)
>  {
> diff --git a/submodule.h b/submodule.h
> index bfaa9da1868..949f67b8031 100644
> --- a/submodule.h
> +++ b/submodule.h
> @@ -72,7 +72,6 @@ void die_path_inside_submodule(struct index_state *istate,
>  enum submodule_update_type parse_submodule_update_type(const char *value);
>  int parse_submodule_update_strategy(const char *value,
>  				    struct submodule_update_strategy *dst);
> -const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);
>  void handle_ignore_submodules_arg(struct diff_options *, const char *);
>  void show_submodule_diff_summary(struct diff_options *o, const char *path,
>  			    struct object_id *one, struct object_id *two,
> -- 
> 2.37.1.1233.ge8b09efaedc

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v2 27/28] submodule--helper: libify "must_die_on_failure" code paths (for die)
  2022-08-02 15:46   ` [PATCH v2 27/28] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
@ 2022-08-03  4:32     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-03  4:32 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason


Patches 19-20 and 22-27 are pretty much "show your work" for the same
libification, so I'll comment on them together.

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Continue the libification of codepaths that previously relied on
> "must_die_on_failure". In these cases we've always been early aborting
> by calling die(), but as we know that these codpaths will properly
> handle return codes of 128 to mean an early abort let's have them use
> die_message() instead.
>
> This still isn't a complete migration away from die() for these
> codepaths, in particular this code in update_submodule() will still call die() in some cases:
>
> 	char *remote_name = get_default_remote_submodule(update_data->sm_path);
> 	const char *branch = remote_submodule_branch(update_data->sm_path);
>
> But as that code is used by other callers than the "update" code let's
> leave converting it for now.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 33 ++++++++++++++++++---------------
>  1 file changed, 18 insertions(+), 15 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 79a11992d1c..4f7ece6fb05 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2263,9 +2263,9 @@ static int run_update_procedure(struct update_data *ud)
>  		 */
>  		if (!is_tip_reachable(ud->sm_path, &ud->oid) &&
>  		    fetch_in_submodule(ud->sm_path, ud->depth, ud->quiet, &ud->oid))
> -			die(_("Fetched in submodule path '%s', but it did not "
> -			      "contain %s. Direct fetching of that commit failed."),
> -			    ud->displaypath, oid_to_hex(&ud->oid));
> +			return die_message(_("Fetched in submodule path '%s', but it did not "
> +					     "contain %s. Direct fetching of that commit failed."),
> +					   ud->displaypath, oid_to_hex(&ud->oid));

Two things I really like about these changes:

- The intermediate return values are opaque, and we always return on
  error. As a result, the code looks quite uniform (instead of e.g.
  mixing return and exit()).
- The "return die_message()" pattern is pretty elegant and it's used
  often enough that there's no doubt that it's pretty clear that
  intermediate functions can and will return 128 to signify that we want
  the process to die.

So these look great to me :)

>  	}
>  
>  	return run_update_command(ud, subforce);
> @@ -2309,13 +2309,14 @@ static const char *remote_submodule_branch(const char *path)
>  	return branch;
>  }
>  
> -static void ensure_core_worktree(const char *path)
> +static int ensure_core_worktree(const char *path)
>  {
>  	const char *cw;
>  	struct repository subrepo;
>  
>  	if (repo_submodule_init(&subrepo, the_repository, path, null_oid()))
> -		die(_("could not get a repository handle for submodule '%s'"), path);
> +		return die_message(_("could not get a repository handle for submodule '%s'"),
> +				   path);
>  
>  	if (!repo_config_get_string_tmp(&subrepo, "core.worktree", &cw)) {
>  		char *cfg_file, *abs_path;
> @@ -2333,6 +2334,8 @@ static void ensure_core_worktree(const char *path)
>  		free(abs_path);
>  		strbuf_release(&sb);
>  	}
> +
> +	return 0;
>  }
>  
>  static const char *submodule_update_type_to_label(enum submodule_update_type type)
> @@ -2408,7 +2411,9 @@ static int update_submodule(struct update_data *update_data)
>  {
>  	int ret;
>  
> -	ensure_core_worktree(update_data->sm_path);
> +	ret = ensure_core_worktree(update_data->sm_path);
> +	if (ret)
> +		return ret;
>  
>  	update_data->displaypath = get_submodule_displaypath(
>  		update_data->sm_path, update_data->prefix);
> @@ -2418,16 +2423,14 @@ static int update_submodule(struct update_data *update_data)
>  						  update_data->sm_path,
>  						  update_data->update_default,
>  						  &update_data->update_strategy);
> -	if (ret) {
> -		*must_die_on_failure = 1;
> +	if (ret)
>  		return ret;
> -	}
>  
>  	if (update_data->just_cloned)
>  		oidcpy(&update_data->suboid, null_oid());
>  	else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid))
> -		die(_("Unable to find current revision in submodule path '%s'"),
> -			update_data->displaypath);
> +		return die_message(_("Unable to find current revision in submodule path '%s'"),
> +				   update_data->displaypath);
>  
>  	if (update_data->remote) {
>  		char *remote_name = get_default_remote_submodule(update_data->sm_path);
> @@ -2437,13 +2440,13 @@ static int update_submodule(struct update_data *update_data)
>  		if (!update_data->nofetch) {
>  			if (fetch_in_submodule(update_data->sm_path, update_data->depth,
>  					      0, NULL))
> -				die(_("Unable to fetch in submodule path '%s'"),
> -				    update_data->sm_path);
> +				return die_message(_("Unable to fetch in submodule path '%s'"),
> +						   update_data->sm_path);
>  		}
>  
>  		if (resolve_gitlink_ref(update_data->sm_path, remote_ref, &update_data->oid))
> -			die(_("Unable to find %s revision in submodule path '%s'"),
> -			    remote_ref, update_data->sm_path);
> +			return die_message(_("Unable to find %s revision in submodule path '%s'"),
> +					   remote_ref, update_data->sm_path);
>  
>  		free(remote_ref);
>  	}
> -- 
> 2.37.1.1233.ge8b09efaedc

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v2 26/28] submodule--helper: libify "must_die_on_failure" code paths
  2022-08-02 15:46   ` [PATCH v2 26/28] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
@ 2022-08-03  4:37     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-03  4:37 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> In preceding commits the codepaths around update_submodules() were
> changed from using exit() or die() to ferrying up a
> "must_die_on_failure" in the cases where we'd exit(), and in most
> cases where we'd die().
>
> We needed to do this this to ensure that we'd early exit or otherwise
> abort the update_submodules() processing before it was completed.
>
> Now that those preceding changes have shown that we've converted those
> paths, we can remove the remaining "ret == 128" special-cases, leaving
> the only such special-case in update_submodules(). I.e. we now know
> after having gone through the various codepaths that we were only
> returning 128 if we meant to early abort.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 33 +++++++++++----------------------
>  1 file changed, 11 insertions(+), 22 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 2b78fa7573f..79a11992d1c 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2147,8 +2147,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
>  	return run_command(&cp);
>  }
>  
> -static int run_update_command(struct update_data *ud, int subforce,
> -			      int *must_die_on_failure)
> +static int run_update_command(struct update_data *ud, int subforce)
>  {
>  	struct child_process cp = CHILD_PROCESS_INIT;
>  	char *oid = oid_to_hex(&ud->oid);
> @@ -2211,8 +2210,6 @@ static int run_update_command(struct update_data *ud, int subforce,
>  			    ud->update_strategy.type);
>  		}
>  
> -		if (ret == 128)
> -			*must_die_on_failure = 1;
>  		return ret;
>  	}
>  
> @@ -2244,8 +2241,7 @@ static int run_update_command(struct update_data *ud, int subforce,
>  	return 0;
>  }
>  
> -static int run_update_procedure(struct update_data *ud,
> -				int *must_die_on_failure)
> +static int run_update_procedure(struct update_data *ud)
>  {
>  	int subforce = is_null_oid(&ud->suboid) || ud->force;
>  
> @@ -2272,7 +2268,7 @@ static int run_update_procedure(struct update_data *ud,
>  			    ud->displaypath, oid_to_hex(&ud->oid));
>  	}
>  
> -	return run_update_command(ud, subforce, must_die_on_failure);
> +	return run_update_command(ud, subforce);
>  }
>  
>  static const char *remote_submodule_branch(const char *path)
> @@ -2408,8 +2404,7 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
>  				    "--no-single-branch");
>  }
>  
> -static int update_submodule(struct update_data *update_data,
> -			    int *must_die_on_failure)
> +static int update_submodule(struct update_data *update_data)
>  {
>  	int ret;
>  
> @@ -2454,11 +2449,9 @@ static int update_submodule(struct update_data *update_data,
>  	}
>  
>  	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
> -		ret = run_update_procedure(update_data, must_die_on_failure);
> -		if (*must_die_on_failure)
> -			return ret;
> +		ret = run_update_procedure(update_data);
>  		if (ret)
> -			return 1;
> +			return ret;
>  	}
>  
>  	if (update_data->recursive) {
> @@ -2476,12 +2469,9 @@ static int update_submodule(struct update_data *update_data,
>  
>  		/* die() if child process die()'d */
>  		ret = run_command(&cp);
> -		if (!ret)
> -			return 0;
> -		die_message(_("Failed to recurse into submodule path '%s'"),
> -			    update_data->displaypath);
> -		if (ret == 128)
> -			*must_die_on_failure = 1;
> +		if (ret)
> +			die_message(_("Failed to recurse into submodule path '%s'"),
> +				    update_data->displaypath);
>  		return ret;
>  	}
>  
> @@ -2514,17 +2504,16 @@ static int update_submodules(struct update_data *update_data)
>  
>  	for (i = 0; i < suc.update_clone_nr; i++) {
>  		struct update_clone_data ucd = suc.update_clone[i];
> -		int must_die_on_failure = 0;
>  		int code;
>  
>  		oidcpy(&update_data->oid, &ucd.oid);
>  		update_data->just_cloned = ucd.just_cloned;
>  		update_data->sm_path = ucd.sub->path;
>  
> -		code = update_submodule(update_data, &must_die_on_failure);
> +		code = update_submodule(update_data);
>  		if (code)
>  			ret = code;
> -		if (must_die_on_failure)
> +		if (code == 128)
>  			goto cleanup;
>  		else if (code)
>  			ret = 1;

This hunk makes sense in the context of this patch, but

		if (code)
			ret = code;
		if (code == 128)
			goto cleanup;
		else if (code)
			ret = 1;

reads a bit awkwardly. Maybe we could drop "code" altogether and just
have:

		if (ret == 128)
			goto cleanup;
		else if (ret)
			ret = 1;

But I don't feel strongly either way.

> -- 
> 2.37.1.1233.ge8b09efaedc

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v2 22/28] submodule--helper: move submodule_strategy_to_string() to only user
  2022-08-02 23:30     ` Glen Choo
@ 2022-08-03 13:06       ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-03 13:06 UTC (permalink / raw)
  To: Glen Choo; +Cc: git, Junio C Hamano, Atharva Raykar, Prathamesh Chavan


On Tue, Aug 02 2022, Glen Choo wrote:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> Move the submodule_strategy_to_string() function added in
>> 3604242f080 (submodule: port init from shell to C, 2016-04-15) to its
>> only user.
>>
>> This function would return NULL on SM_UPDATE_UNSPECIFIED, so it wasn't
>> safe to xstrdup() its return value in the general case, or to use it
>> in a sprintf() format as the code removed in the preceding commit did.
>>
>> But its callers would never call it with either SM_UPDATE_UNSPECIFIED
>> or SM_UPDATE_COMMAND. Let's move it to a "static" helper, and have its
>> functionality reflect how it's used, and BUG() out on the rest.
>>
>> By doing this we can also stop needlessly xstrdup()-ing and free()-ing
>> the memory for the config we're setting. We can instead always use
>> constant strings. We can also use the *_tmp() variant of
>> git_config_get_string().
>>
>> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>> ---
>>  builtin/submodule--helper.c | 29 ++++++++++++++++++++++++-----
>>  submodule.c                 | 21 ---------------------
>>  submodule.h                 |  1 -
>>  3 files changed, 24 insertions(+), 27 deletions(-)
>>
>> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
>> index b49528e1ba9..d787c0fead4 100644
>> --- a/builtin/submodule--helper.c
>> +++ b/builtin/submodule--helper.c
>> @@ -413,12 +413,32 @@ struct init_cb {
>>  };
>>  #define INIT_CB_INIT { 0 }
>>  
>> +static const char *submodule_strategy_to_string(enum submodule_update_type type)
>> +{
>> +	switch (type) {
>> +	case SM_UPDATE_CHECKOUT:
>> +		return "checkout";
>> +	case SM_UPDATE_MERGE:
>> +		return "merge";
>> +	case SM_UPDATE_REBASE:
>> +		return "rebase";
>> +	case SM_UPDATE_NONE:
>> +		return "none";
>> +	case SM_UPDATE_UNSPECIFIED:
>> +	case SM_UPDATE_COMMAND:
>> +		BUG("init_submodule() should handle type %d", type);
>> +	default:
>> +		BUG("unexpected update strategy type: %d", type);
>> +	}
>> +}
>> +
>
> This function is meant to convert from an update strategy back to the
> string that the user actually provided in their gitconfig.
>
> The change in behavior makes this function BUG() out on types that
> aren't "magic" tokens, i.e. "UNSPECIFIED" (which is obviously not
> expressible) and "COMMAND" (which allows users to specify an arbitrary
> command using "!", like "!cat"). It shouldn't be difficult to teach
> callers to handle "COMMAND", so this seems like an ok change, though I
> think we should probably amend the function name to
> submodule_update_type_to_string() and change the UNSPECIFIED and COMMAND
> arms to something like BUG("type %d has no corresponding string").

Makes sense, will rename it.

> I'm not so convinced that this function should be static, though. I
> think it's more natural for submodule_update_type_to_string() to have
> the same visibility as enum submodule_update_type. Today, we only have
> one other caller who uses this enum, and it doesn't even need this
> _to_string() fn (fsck.c calls parse_submodule_update_type() and doesn't
> need _to_string() because it has the raw config values). But it feels a
> bit inevitable that this will get moved back to submodule.h.

I'll re-roll & leave it in submodule.[ch].

^ permalink raw reply	[flat|nested] 142+ messages in thread

* [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep
  2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                   ` (21 preceding siblings ...)
  2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57 ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 01/32] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
                     ` (32 more replies)
  22 siblings, 33 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

This series is a "prep" series for the meaty leak fixes for
submodule--helper, see [1] (which will be re-rolled on top of this
v3). The v6 re-roll will be at [2].

Changes since v2:

 * Clarified 1/* commit message.
 * 22/*: keep the "to string" API function in submodule.[ch], as
   suggested by Glen.
 * 24/*: Minor change to existing comment obsoleted by the code change.
 * 26-31/*: Do the full libification suggested by Glen, instead of
   leaving it for later. As a result we don't need to pass up the
   "must_die_on_failure", and some parts of the soon-to-be-rerolled
   "leak" series[1] will be better as a result.

1. https://lore.kernel.org/git/cover-v5-00.17-00000000000-20220802T155002Z-avarab@gmail.com/
2. https://lore.kernel.org/git/cover-v6-00.17-00000000000-20220821T130415Z-avarab@gmail.com

Glen Choo (2):
  submodule--helper: add "const" to copy of "update_data"
  submodule--helper: refactor "errmsg_str" to be a "struct strbuf"

Ævar Arnfjörð Bjarmason (30):
  submodule tests: test usage behavior
  submodule tests: test for "add <repository> <abs-path>"
  submodule--helper: remove unused "name" helper
  submodule--helper: remove unused "list" helper
  test-tool submodule-config: remove unused "--url" handling
  submodule--helper: move "is-active" to a test-tool
  submodule--helper: move "check-name" to a test-tool
  submodule--helper: move "resolve-relative-url-test" to a test-tool
  submodule--helper style: don't separate declared variables with \n\n
  submodule--helper style: add \n\n after variable declarations
  submodule--helper: replace memset() with { 0 }-initialization
  submodule--helper: use xstrfmt() in clone_submodule()
  submodule--helper: move "sb" in clone_submodule() to its own scope
  submodule--helper: add "const" to passed "module_clone_data"
  submodule--helper: don't redundantly check "else if (res)"
  submodule--helper: rename "int res" to "int ret"
  submodule--helper: return "ret", not "1" from update_submodule()
  submodule--helper: add missing braces to "else" arm
  submodule--helper: don't call submodule_strategy_to_string() in BUG()
  submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string()
  submodule--helper: use "code" in run_update_command()
  submodule--helper: don't exit() on failure, return
  submodule--helper: libify determine_submodule_update_strategy()
  submodule--helper: libify "must_die_on_failure" code paths
  submodule--helper update: don't override 'checkout' exit code
  submodule--helper: libify "must_die_on_failure" code paths (for die)
  submodule--helper: check repo{_submodule,}_init() return values
  submodule--helper: libify more "die" paths for module_update()
  submodule--helper: libify even more "die" paths for module_update()
  submodule--helper: fix bad config API usage

 Makefile                         |   1 +
 builtin/submodule--helper.c      | 534 ++++++++++++++-----------------
 git-compat-util.h                |   3 +
 repository.h                     |   3 +
 submodule.c                      |  12 +-
 submodule.h                      |   2 +-
 t/helper/test-submodule-config.c |  11 +-
 t/helper/test-submodule.c        | 146 +++++++++
 t/helper/test-tool-utils.h       |   9 +
 t/helper/test-tool.c             |   7 +-
 t/helper/test-tool.h             |   1 +
 t/t0060-path-utils.sh            |   2 +-
 t/t7400-submodule-basic.sh       |  56 ++--
 t/t7406-submodule-update.sh      |   2 +-
 t/t7413-submodule-is-active.sh   |  35 +-
 t/t7450-bad-git-dotfiles.sh      |   2 +-
 16 files changed, 460 insertions(+), 366 deletions(-)
 create mode 100644 t/helper/test-submodule.c
 create mode 100644 t/helper/test-tool-utils.h

Range-diff against v2:
 1:  daa5d3f9962 !  1:  77586985ab3 submodule tests: test usage behavior
    @@ Commit message
         subsequent eventual behavior change will become clear.
     
         For "--" this follows up on 68cabbfda36 (submodule: document default
    -    behavior, 2019-02-15) and tests that "status" doesn't don't support
    +    behavior, 2019-02-15) and tests that "status" doesn't support
         the "--" delimiter. There's no intrinsically good reason not to
         support that. We behave this way due to edge cases in
         git-submodule.sh's implementation, but as with "-h" let's assert our
    @@ Commit message
         doesn't seem to be a reason not to support it alongside "--quiet" and
         "--cached", but let's likewise assert our existing behavior for now.
     
    +    I.e. as long as "status" is optional it would make sense to support
    +    all of its options when it's omitted, but we only do that with
    +    "--quiet" and "--cached", and curiously omit "--recursive".
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## t/t7400-submodule-basic.sh ##
 2:  9d920326df3 =  2:  7425f0025da submodule tests: test for "add <repository> <abs-path>"
 3:  d981db49fa1 =  3:  1be48c0b22f submodule--helper: remove unused "name" helper
 4:  6f78f9c9274 =  4:  10189ba3da7 submodule--helper: remove unused "list" helper
 5:  43902201701 =  5:  ef66dfcd45f test-tool submodule-config: remove unused "--url" handling
 6:  e2a8bb0a28e =  6:  4727fbb4b64 submodule--helper: move "is-active" to a test-tool
 7:  b209532eb17 =  7:  9c644460b1d submodule--helper: move "check-name" to a test-tool
 8:  de49f31dab0 =  8:  03c8383b8e7 submodule--helper: move "resolve-relative-url-test" to a test-tool
 9:  b0238f699ce =  9:  b1eaa6a796b submodule--helper style: don't separate declared variables with \n\n
10:  5f5e68a868b = 10:  fd7fbe08536 submodule--helper style: add \n\n after variable declarations
11:  72dcf19e1c4 = 11:  356f07db436 submodule--helper: replace memset() with { 0 }-initialization
12:  e5e267dccd5 = 12:  241ac5c7eee submodule--helper: use xstrfmt() in clone_submodule()
13:  91558745e2e = 13:  f2f412f50c1 submodule--helper: move "sb" in clone_submodule() to its own scope
14:  866b8397a59 ! 14:  ad7848067a9 submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    submodule--helper: pass a "const struct module_clone_data" to clone_submodule()
    +    submodule--helper: add "const" to passed "module_clone_data"
     
         Add "const" to the "struct module_clone_data" that we pass to
         clone_submodule(), which makes the ownership clear, and stops us from
15:  1ff380ec7b5 = 15:  ab283479b92 submodule--helper: add "const" to copy of "update_data"
16:  d3a7e646adc = 16:  ab0fd2c60f0 submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
17:  23eb07176d9 = 17:  fa2417c7a17 submodule--helper: don't redundantly check "else if (res)"
18:  78f74df6d5e = 18:  be1ffbf2e26 submodule--helper: rename "int res" to "int ret"
19:  f0258e37ebe = 19:  92e17c37839 submodule--helper: return "ret", not "1" from update_submodule()
20:  70f030cca4e = 20:  55e3ea5f9dd submodule--helper: add missing braces to "else" arm
21:  bce1a014a2f = 21:  2bb45302392 submodule--helper: don't call submodule_strategy_to_string() in BUG()
22:  98c3e562c82 ! 22:  0131c197427 submodule--helper: move submodule_strategy_to_string() to only user
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    submodule--helper: move submodule_strategy_to_string() to only user
    +    submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string()
     
    -    Move the submodule_strategy_to_string() function added in
    -    3604242f080 (submodule: port init from shell to C, 2016-04-15) to its
    -    only user.
    +    Change the submodule_strategy_to_string() function added in
    +    3604242f080 (submodule: port init from shell to C, 2016-04-15) to
    +    really return a "const char *". In the "SM_UPDATE_COMMAND" case it
    +    would return a strbuf_detach().
     
    -    This function would return NULL on SM_UPDATE_UNSPECIFIED, so it wasn't
    -    safe to xstrdup() its return value in the general case, or to use it
    -    in a sprintf() format as the code removed in the preceding commit did.
    +    Furthermore, this function would return NULL on SM_UPDATE_UNSPECIFIED,
    +    so it wasn't safe to xstrdup() its return value in the general case,
    +    or to use it in a sprintf() format as the code removed in the
    +    preceding commit did.
     
         But its callers would never call it with either SM_UPDATE_UNSPECIFIED
    -    or SM_UPDATE_COMMAND. Let's move it to a "static" helper, and have its
    -    functionality reflect how it's used, and BUG() out on the rest.
    +    or SM_UPDATE_COMMAND. Let's have its behavior reflect how its only
    +    user expects it to behave, and BUG() out on the rest.
     
         By doing this we can also stop needlessly xstrdup()-ing and free()-ing
         the memory for the config we're setting. We can instead always use
         constant strings. We can also use the *_tmp() variant of
         git_config_get_string().
     
    +    Let's also rename this submodule_strategy_to_string() function to
    +    submodule_update_type_to_string(). Now that it's only tasked with
    +    returning a string version of the "enum submodule_update_type type".
    +    Before it would look at the "command" field in "struct
    +    submodule_update_strategy".
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    -@@ builtin/submodule--helper.c: struct init_cb {
    - };
    - #define INIT_CB_INIT { 0 }
    - 
    -+static const char *submodule_strategy_to_string(enum submodule_update_type type)
    -+{
    -+	switch (type) {
    -+	case SM_UPDATE_CHECKOUT:
    -+		return "checkout";
    -+	case SM_UPDATE_MERGE:
    -+		return "merge";
    -+	case SM_UPDATE_REBASE:
    -+		return "rebase";
    -+	case SM_UPDATE_NONE:
    -+		return "none";
    -+	case SM_UPDATE_UNSPECIFIED:
    -+	case SM_UPDATE_COMMAND:
    -+		BUG("init_submodule() should handle type %d", type);
    -+	default:
    -+		BUG("unexpected update strategy type: %d", type);
    -+	}
    -+}
    -+
    - static void init_submodule(const char *path, const char *prefix,
    - 			   unsigned int flags)
    +@@ builtin/submodule--helper.c: static void init_submodule(const char *path, const char *prefix,
      {
      	const struct submodule *sub;
      	struct strbuf sb = STRBUF_INIT;
    @@ builtin/submodule--helper.c: static void init_submodule(const char *path, const
     +			upd = "none";
      		} else {
     -			upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy));
    -+			upd = submodule_strategy_to_string(sub->update_strategy.type);
    ++			upd = submodule_update_type_to_string(sub->update_strategy.type);
      		}
      
      		if (git_config_set_gently(sb.buf, upd))
    @@ submodule.c: int parse_submodule_update_strategy(const char *value,
      }
      
     -const char *submodule_strategy_to_string(const struct submodule_update_strategy *s)
    --{
    ++const char *submodule_update_type_to_string(enum submodule_update_type type)
    + {
     -	struct strbuf sb = STRBUF_INIT;
     -	switch (s->type) {
    --	case SM_UPDATE_CHECKOUT:
    --		return "checkout";
    --	case SM_UPDATE_MERGE:
    --		return "merge";
    --	case SM_UPDATE_REBASE:
    --		return "rebase";
    --	case SM_UPDATE_NONE:
    --		return "none";
    --	case SM_UPDATE_UNSPECIFIED:
    ++	switch (type) {
    + 	case SM_UPDATE_CHECKOUT:
    + 		return "checkout";
    + 	case SM_UPDATE_MERGE:
    +@@ submodule.c: const char *submodule_strategy_to_string(const struct submodule_update_strategy
    + 	case SM_UPDATE_NONE:
    + 		return "none";
    + 	case SM_UPDATE_UNSPECIFIED:
     -		return NULL;
    --	case SM_UPDATE_COMMAND:
    + 	case SM_UPDATE_COMMAND:
     -		strbuf_addf(&sb, "!%s", s->command);
     -		return strbuf_detach(&sb, NULL);
    --	}
    ++		BUG("init_submodule() should handle type %d", type);
    ++	default:
    ++		BUG("unexpected update strategy type: %d", type);
    + 	}
     -	return NULL;
    --}
    --
    + }
    + 
      void handle_ignore_submodules_arg(struct diff_options *diffopt,
    - 				  const char *arg)
    - {
     
      ## submodule.h ##
     @@ submodule.h: void die_path_inside_submodule(struct index_state *istate,
    @@ submodule.h: void die_path_inside_submodule(struct index_state *istate,
      int parse_submodule_update_strategy(const char *value,
      				    struct submodule_update_strategy *dst);
     -const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);
    ++const char *submodule_update_type_to_string(enum submodule_update_type type);
      void handle_ignore_submodules_arg(struct diff_options *, const char *);
      void show_submodule_diff_summary(struct diff_options *o, const char *path,
      			    struct object_id *one, struct object_id *two,
23:  db2d2fb5a21 = 23:  6cac6cb2fa6 submodule--helper: use "code" in run_update_command()
24:  d33260487bd ! 24:  6d56f671c7a submodule--helper: don't exit() on failure, return
    @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *upd
      	if (update_data->recursive) {
      		struct child_process cp = CHILD_PROCESS_INIT;
     @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
    + 		prepare_submodule_repo_env(&cp.env);
    + 		update_data_to_args(&next, &cp.args);
    + 
    +-		/* die() if child process die()'d */
    + 		ret = run_command(&cp);
    + 		if (!ret)
    + 			return 0;
      		die_message(_("Failed to recurse into submodule path '%s'"),
      			    update_data->displaypath);
      		if (ret == 128)
25:  9981a75d7e8 = 25:  dfd5c8bcd61 submodule--helper: libify determine_submodule_update_strategy()
26:  b48705c6cc0 ! 26:  da1a07afd25 submodule--helper: libify "must_die_on_failure" code paths
    @@ Commit message
         after having gone through the various codepaths that we were only
         returning 128 if we meant to early abort.
     
    +    In update_submodules() we'll for now set any non-zero non-128 exit
    +    codes to "1", but will start ferrying up the exit code as-is in a
    +    subsequent commit.
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    @@ builtin/submodule--helper.c: static void update_data_to_args(struct update_data
      {
      	int ret;
      
    +@@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data,
    + 						  update_data->sm_path,
    + 						  update_data->update_default,
    + 						  &update_data->update_strategy);
    +-	if (ret) {
    +-		*must_die_on_failure = 1;
    ++	if (ret)
    + 		return ret;
    +-	}
    + 
    + 	if (update_data->just_cloned)
    + 		oidcpy(&update_data->suboid, null_oid());
     @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data,
      	}
      
    @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *upd
      
      	if (update_data->recursive) {
     @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data,
    + 		update_data_to_args(&next, &cp.args);
      
    - 		/* die() if child process die()'d */
      		ret = run_command(&cp);
     -		if (!ret)
     -			return 0;
    @@ builtin/submodule--helper.c: static int update_submodules(struct update_data *up
      		update_data->sm_path = ucd.sub->path;
      
     -		code = update_submodule(update_data, &must_die_on_failure);
    -+		code = update_submodule(update_data);
    - 		if (code)
    - 			ret = code;
    +-		if (code)
    +-			ret = code;
     -		if (must_die_on_failure)
    -+		if (code == 128)
    ++		code = update_submodule(update_data);
    ++		if (!code)
    ++			continue;
    ++		ret = code;
    ++		if (ret == 128)
      			goto cleanup;
    - 		else if (code)
    - 			ret = 1;
    +-		else if (code)
    +-			ret = 1;
    ++		ret = 1;
    + 	}
    + 
    + cleanup:
 -:  ----------- > 27:  2795a3738c8 submodule--helper update: don't override 'checkout' exit code
27:  93cd1ccde54 ! 28:  6d9bccb34c3 submodule--helper: libify "must_die_on_failure" code paths (for die)
    @@ Commit message
                 const char *branch = remote_submodule_branch(update_data->sm_path);
     
         But as that code is used by other callers than the "update" code let's
    -    leave converting it for now.
    +    leave converting it for a subsequent commit.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *upd
      	update_data->displaypath = get_submodule_displaypath(
      		update_data->sm_path, update_data->prefix);
     @@ builtin/submodule--helper.c: static int update_submodule(struct update_data *update_data)
    - 						  update_data->sm_path,
    - 						  update_data->update_default,
    - 						  &update_data->update_strategy);
    --	if (ret) {
    --		*must_die_on_failure = 1;
    -+	if (ret)
    - 		return ret;
    --	}
    - 
      	if (update_data->just_cloned)
      		oidcpy(&update_data->suboid, null_oid());
      	else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid))
 -:  ----------- > 29:  d4b55f07a30 submodule--helper: check repo{_submodule,}_init() return values
 -:  ----------- > 30:  15c2490a978 submodule--helper: libify more "die" paths for module_update()
 -:  ----------- > 31:  1694ccfe882 submodule--helper: libify even more "die" paths for module_update()
28:  6160a1ab250 = 32:  d133402462f submodule--helper: fix bad config API usage
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply	[flat|nested] 142+ messages in thread

* [PATCH v3 01/32] submodule tests: test usage behavior
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-23 22:42     ` Glen Choo
  2022-08-21 13:57   ` [PATCH v3 02/32] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
                     ` (31 subsequent siblings)
  32 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Test what exit code and output we emit on "git submodule -h", how we
handle "--" when no subcommand is specified, and how the top-level
"--recursive" option is handled.

For "-h" this doesn't make sense, but let's test for it so that any
subsequent eventual behavior change will become clear.

For "--" this follows up on 68cabbfda36 (submodule: document default
behavior, 2019-02-15) and tests that "status" doesn't support
the "--" delimiter. There's no intrinsically good reason not to
support that. We behave this way due to edge cases in
git-submodule.sh's implementation, but as with "-h" let's assert our
current long-standing behavior for now.

For "--recursive" the exclusion of it from the top-level appears to
have been an omission in 15fc56a8536 (git submodule foreach: Add
--recursive to recurse into nested submodules, 2009-08-19), there
doesn't seem to be a reason not to support it alongside "--quiet" and
"--cached", but let's likewise assert our existing behavior for now.

I.e. as long as "status" is optional it would make sense to support
all of its options when it's omitted, but we only do that with
"--quiet" and "--cached", and curiously omit "--recursive".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t7400-submodule-basic.sh | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index e7cec2e457a..b858871a953 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -14,6 +14,32 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./test-lib.sh
 
+test_expect_success 'submodule usage: -h' '
+	git submodule -h >out 2>err &&
+	grep "^usage: git submodule" out &&
+	test_must_be_empty err
+'
+
+test_expect_success 'submodule usage: --recursive' '
+	test_expect_code 1 git submodule --recursive >out 2>err &&
+	grep "^usage: git submodule" err &&
+	test_must_be_empty out
+'
+
+test_expect_success 'submodule usage: status --' '
+	test_expect_code 1 git submodule -- &&
+	test_expect_code 1 git submodule --end-of-options
+'
+
+for opt in '--quiet' '--cached'
+do
+	test_expect_success "submodule usage: status $opt" '
+		git submodule $opt &&
+		git submodule status $opt &&
+		git submodule $opt status
+	'
+done
+
 test_expect_success 'submodule deinit works on empty repository' '
 	git submodule deinit --all
 '
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 02/32] submodule tests: test for "add <repository> <abs-path>"
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 01/32] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 03/32] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
                     ` (30 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add a missing test for ""add <repository> <path>" where "<path>" is an
absolute path. This tests code added in [1] and later turned into an
"else" branch in clone_submodule() in [2] that's never been tested.

This needs to be skipped on WINDOWS because all of $PWD, $(pwd) and
the "$(pwd -P)" we get via "$submodurl" would fail in CI with e.g.:

	fatal: could not create directory 'D:/a/git/git/t/trash
	directory.t7400-submodule-basic/.git/modules/D:/a/git/git/t/trash
	directory.t7400-submodule-basic/add-abs'

I.e. we can't handle these sorts of paths in this context on that
platform.

I'm not sure where we run into the edges of "$PWD" behavior on
Windows (see [1] for a previous loose end on the topic), but for the
purposes of this test it's sufficient that we test this on other
platforms.

1. ee8838d1577 (submodule: rewrite `module_clone` shell function in C,
   2015-09-08)
2. f8eaa0ba98b (submodule--helper, module_clone: always operate on
   absolute paths, 2016-03-31)

1. https://lore.kernel.org/git/220630.86edz6c75c.gmgdl@evledraar.gmail.com/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t7400-submodule-basic.sh | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index b858871a953..6a77d817a82 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -178,6 +178,11 @@ test_expect_success 'submodule add' '
 	test_must_be_empty untracked
 '
 
+test_expect_success !WINDOWS 'submodule add (absolute path)' '
+	test_when_finished "git reset --hard" &&
+	git submodule add "$submodurl" "$submodurl/add-abs"
+'
+
 test_expect_success 'setup parent and one repository' '
 	test_create_repo parent &&
 	test_commit -C parent one
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 03/32] submodule--helper: remove unused "name" helper
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 01/32] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 02/32] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 04/32] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
                     ` (29 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The "name" helper has not been used since e83e3333b57 (submodule: port
submodule subcommand 'summary' from shell to C, 2020-08-13).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b63f420ecef..fc4d2779da6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -771,24 +771,6 @@ static int module_status(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static int module_name(int argc, const char **argv, const char *prefix)
-{
-	const struct submodule *sub;
-
-	if (argc != 2)
-		usage(_("git submodule--helper name <path>"));
-
-	sub = submodule_from_path(the_repository, null_oid(), argv[1]);
-
-	if (!sub)
-		die(_("no submodule mapping found in .gitmodules for path '%s'"),
-		    argv[1]);
-
-	printf("%s\n", sub->name);
-
-	return 0;
-}
-
 struct module_cb {
 	unsigned int mod_src;
 	unsigned int mod_dst;
@@ -3362,7 +3344,6 @@ struct cmd_struct {
 
 static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
-	{"name", module_name, 0},
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 04/32] submodule--helper: remove unused "list" helper
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (2 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 03/32] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 05/32] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
                     ` (28 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Remove the "submodule--helper list" sub-command, which hasn't been
used by git-submodule.sh since 2964d6e5e1e (submodule: port subcommand
'set-branch' from shell to C, 2020-06-02).

There was a test added in 2b56bb7a87a (submodule helper list: respect
correct path prefix, 2016-02-24) which relied on it, but the right
thing to do here is to delete that test as well.

That test was regression testing the "list" subcommand itself. We're
not getting anything useful from the "list | cut -f2" invocation that
we couldn't get from "foreach 'echo $sm_path'".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 40 -------------------------------------
 t/t7400-submodule-basic.sh  | 25 -----------------------
 2 files changed, 65 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fc4d2779da6..24a305151d1 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -266,45 +266,6 @@ static char *get_up_path(const char *path)
 	return strbuf_detach(&sb, NULL);
 }
 
-static int module_list(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-
-	struct option module_list_options[] = {
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper list [--prefix=<path>] [<path>...]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_list_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	for (i = 0; i < list.nr; i++) {
-		const struct cache_entry *ce = list.entries[i];
-
-		if (ce_stage(ce))
-			printf("%06o %s U\t", ce->ce_mode,
-			       oid_to_hex(null_oid()));
-		else
-			printf("%06o %s %d\t", ce->ce_mode,
-			       oid_to_hex(&ce->oid), ce_stage(ce));
-
-		fprintf(stdout, "%s\n", ce->name);
-	}
-	return 0;
-}
-
 static void for_each_listed_submodule(const struct module_list *list,
 				      each_submodule_fn fn, void *cb_data)
 {
@@ -3343,7 +3304,6 @@ struct cmd_struct {
 };
 
 static struct cmd_struct commands[] = {
-	{"list", module_list, 0},
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 6a77d817a82..b50db3f1031 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -1255,31 +1255,6 @@ test_expect_success 'submodule add clone shallow submodule' '
 	)
 '
 
-test_expect_success 'submodule helper list is not confused by common prefixes' '
-	mkdir -p dir1/b &&
-	(
-		cd dir1/b &&
-		git init &&
-		echo hi >testfile2 &&
-		git add . &&
-		git commit -m "test1"
-	) &&
-	mkdir -p dir2/b &&
-	(
-		cd dir2/b &&
-		git init &&
-		echo hello >testfile1 &&
-		git add .  &&
-		git commit -m "test2"
-	) &&
-	git submodule add /dir1/b dir1/b &&
-	git submodule add /dir2/b dir2/b &&
-	git commit -m "first submodule commit" &&
-	git submodule--helper list dir1/b | cut -f 2 >actual &&
-	echo "dir1/b" >expect &&
-	test_cmp expect actual
-'
-
 test_expect_success 'setup superproject with submodules' '
 	git init sub1 &&
 	test_commit -C sub1 test &&
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 05/32] test-tool submodule-config: remove unused "--url" handling
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (3 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 04/32] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 06/32] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
                     ` (27 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

No test has used this "--url" parameter since the test code that made
use of it was removed in 32bc548329d (submodule-config: remove support
for overlaying repository config, 2017-08-03).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/helper/test-submodule-config.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index e2692746dfd..22a41c40926 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -15,14 +15,11 @@ int cmd__submodule_config(int argc, const char **argv)
 {
 	const char **arg = argv;
 	int my_argc = argc;
-	int output_url = 0;
 	int lookup_name = 0;
 
 	arg++;
 	my_argc--;
 	while (arg[0] && starts_with(arg[0], "--")) {
-		if (!strcmp(arg[0], "--url"))
-			output_url = 1;
 		if (!strcmp(arg[0], "--name"))
 			lookup_name = 1;
 		arg++;
@@ -57,12 +54,8 @@ int cmd__submodule_config(int argc, const char **argv)
 		if (!submodule)
 			die_usage(argc, argv, "Submodule not found.");
 
-		if (output_url)
-			printf("Submodule url: '%s' for path '%s'\n",
-					submodule->url, submodule->path);
-		else
-			printf("Submodule name: '%s' for path '%s'\n",
-					submodule->name, submodule->path);
+		printf("Submodule name: '%s' for path '%s'\n", submodule->name,
+		       submodule->path);
 
 		arg += 2;
 	}
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 06/32] submodule--helper: move "is-active" to a test-tool
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (4 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 05/32] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 07/32] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
                     ` (26 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Create a new "test-tool submodule" and move the "is-active" subcommand
over to it. It was added in 5c2bd8b77ae (submodule--helper: add
is-active subcommand, 2017-03-16), since
a452128a36c (submodule--helper: introduce add-config subcommand,
2021-08-06) it hasn't been used by git-submodule.sh.

Since we're creating a command dispatch similar to test-tool.c itself
let's split out the "struct test_cmd" into a new test-tool-utils.h,
which both this new code and test-tool.c itself can use.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Makefile                       |  1 +
 builtin/submodule--helper.c    |  9 ------
 t/helper/test-submodule.c      | 58 ++++++++++++++++++++++++++++++++++
 t/helper/test-tool-utils.h     |  9 ++++++
 t/helper/test-tool.c           |  7 ++--
 t/helper/test-tool.h           |  1 +
 t/t7413-submodule-is-active.sh | 35 ++++++++++----------
 7 files changed, 90 insertions(+), 30 deletions(-)
 create mode 100644 t/helper/test-submodule.c
 create mode 100644 t/helper/test-tool-utils.h

diff --git a/Makefile b/Makefile
index e8adeb09f1c..b6acd560e75 100644
--- a/Makefile
+++ b/Makefile
@@ -785,6 +785,7 @@ TEST_BUILTINS_OBJS += test-strcmp-offset.o
 TEST_BUILTINS_OBJS += test-string-list.o
 TEST_BUILTINS_OBJS += test-submodule-config.o
 TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
+TEST_BUILTINS_OBJS += test-submodule.o
 TEST_BUILTINS_OBJS += test-subprocess.o
 TEST_BUILTINS_OBJS += test-trace2.o
 TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 24a305151d1..e10c3ac7550 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2731,14 +2731,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static int is_active(int argc, const char **argv, const char *prefix)
-{
-	if (argc != 2)
-		die("submodule--helper is-active takes exactly 1 argument");
-
-	return !is_submodule_active(the_repository, argv[1]);
-}
-
 /*
  * Exit non-zero if any of the submodule names given on the command line is
  * invalid. If no names are given, filter stdin to print only valid names
@@ -3316,7 +3308,6 @@ static struct cmd_struct commands[] = {
 	{"summary", module_summary, 0},
 	{"push-check", push_check, 0},
 	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
-	{"is-active", is_active, 0},
 	{"check-name", check_name, 0},
 	{"config", module_config, 0},
 	{"set-url", module_set_url, 0},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
new file mode 100644
index 00000000000..494c6558d9f
--- /dev/null
+++ b/t/helper/test-submodule.c
@@ -0,0 +1,58 @@
+#include "test-tool.h"
+#include "test-tool-utils.h"
+#include "cache.h"
+#include "parse-options.h"
+#include "submodule.h"
+
+#define TEST_TOOL_IS_ACTIVE_USAGE \
+	"test-tool submodule is-active <name>"
+static const char *submodule_is_active_usage[] = {
+	TEST_TOOL_IS_ACTIVE_USAGE,
+	NULL
+};
+
+static const char *submodule_usage[] = {
+	TEST_TOOL_IS_ACTIVE_USAGE,
+	NULL
+};
+
+static int cmd__submodule_is_active(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_is_active_usage, 0);
+	if (argc != 1)
+		usage_with_options(submodule_is_active_usage, options);
+
+	setup_git_directory();
+
+	return !is_submodule_active(the_repository, argv[0]);
+}
+
+static struct test_cmd cmds[] = {
+	{ "is-active", cmd__submodule_is_active },
+};
+
+int cmd__submodule(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	size_t i;
+
+	argc = parse_options(argc, argv, "test-tools", options, submodule_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (argc < 1)
+		usage_with_options(submodule_usage, options);
+
+	for (i = 0; i < ARRAY_SIZE(cmds); i++)
+		if (!strcmp(cmds[i].name, argv[0]))
+			return cmds[i].fn(argc, argv);
+
+	usage_msg_optf("unknown subcommand '%s'", submodule_usage, options,
+		       argv[0]);
+
+	return 0;
+}
diff --git a/t/helper/test-tool-utils.h b/t/helper/test-tool-utils.h
new file mode 100644
index 00000000000..6a0e5e0074f
--- /dev/null
+++ b/t/helper/test-tool-utils.h
@@ -0,0 +1,9 @@
+#ifndef TEST_TOOL_UTILS_H
+#define TEST_TOOL_UTILS_H
+
+struct test_cmd {
+	const char *name;
+	int (*fn)(int argc, const char **argv);
+};
+
+#endif
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 318fdbab0c3..7a6a8b88a91 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "test-tool.h"
+#include "test-tool-utils.h"
 #include "trace2.h"
 #include "parse-options.h"
 
@@ -8,11 +9,6 @@ static const char * const test_tool_usage[] = {
 	NULL
 };
 
-struct test_cmd {
-	const char *name;
-	int (*fn)(int argc, const char **argv);
-};
-
 static struct test_cmd cmds[] = {
 	{ "advise", cmd__advise_if_enabled },
 	{ "bitmap", cmd__bitmap },
@@ -78,6 +74,7 @@ static struct test_cmd cmds[] = {
 	{ "simple-ipc", cmd__simple_ipc },
 	{ "strcmp-offset", cmd__strcmp_offset },
 	{ "string-list", cmd__string_list },
+	{ "submodule", cmd__submodule },
 	{ "submodule-config", cmd__submodule_config },
 	{ "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
 	{ "subprocess", cmd__subprocess },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index bb799271631..5f4f69dee81 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -68,6 +68,7 @@ int cmd__sigchain(int argc, const char **argv);
 int cmd__simple_ipc(int argc, const char **argv);
 int cmd__strcmp_offset(int argc, const char **argv);
 int cmd__string_list(int argc, const char **argv);
+int cmd__submodule(int argc, const char **argv);
 int cmd__submodule_config(int argc, const char **argv);
 int cmd__submodule_nested_repo_config(int argc, const char **argv);
 int cmd__subprocess(int argc, const char **argv);
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index c8e7e983317..ede6f02dbd5 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -1,9 +1,12 @@
 #!/bin/sh
 
-test_description='Test submodule--helper is-active
+test_description='Test with test-tool submodule is-active
 
-This test verifies that `git submodue--helper is-active` correctly identifies
+This test verifies that `test-tool submodule is-active` correctly identifies
 submodules which are "active" and interesting to the user.
+
+This is a unit test of the submodule.c is_submodule_active() function,
+which is also indirectly tested elsewhere.
 '
 
 . ./test-lib.sh
@@ -25,13 +28,13 @@ test_expect_success 'setup' '
 '
 
 test_expect_success 'is-active works with urls' '
-	git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2 &&
+	test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2 &&
 
 	git -C super config --unset submodule.sub1.URL &&
-	test_must_fail git -C super submodule--helper is-active sub1 &&
+	test_must_fail test-tool -C super submodule is-active sub1 &&
 	git -C super config submodule.sub1.URL ../sub &&
-	git -C super submodule--helper is-active sub1
+	test-tool -C super submodule is-active sub1
 '
 
 test_expect_success 'is-active works with submodule.<name>.active config' '
@@ -39,11 +42,11 @@ test_expect_success 'is-active works with submodule.<name>.active config' '
 	test_when_finished "git -C super config submodule.sub1.URL ../sub" &&
 
 	git -C super config --bool submodule.sub1.active "false" &&
-	test_must_fail git -C super submodule--helper is-active sub1 &&
+	test_must_fail test-tool -C super submodule is-active sub1 &&
 
 	git -C super config --bool submodule.sub1.active "true" &&
 	git -C super config --unset submodule.sub1.URL &&
-	git -C super submodule--helper is-active sub1
+	test-tool -C super submodule is-active sub1
 '
 
 test_expect_success 'is-active works with basic submodule.active config' '
@@ -53,17 +56,17 @@ test_expect_success 'is-active works with basic submodule.active config' '
 	git -C super config --add submodule.active "." &&
 	git -C super config --unset submodule.sub1.URL &&
 
-	git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active correctly works with paths that are not submodules' '
 	test_when_finished "git -C super config --unset-all submodule.active" &&
 
-	test_must_fail git -C super submodule--helper is-active not-a-submodule &&
+	test_must_fail test-tool -C super submodule is-active not-a-submodule &&
 
 	git -C super config --add submodule.active "." &&
-	test_must_fail git -C super submodule--helper is-active not-a-submodule
+	test_must_fail test-tool -C super submodule is-active not-a-submodule
 '
 
 test_expect_success 'is-active works with exclusions in submodule.active config' '
@@ -72,8 +75,8 @@ test_expect_success 'is-active works with exclusions in submodule.active config'
 	git -C super config --add submodule.active "." &&
 	git -C super config --add submodule.active ":(exclude)sub1" &&
 
-	test_must_fail git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test_must_fail test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active with submodule.active and submodule.<name>.active' '
@@ -85,8 +88,8 @@ test_expect_success 'is-active with submodule.active and submodule.<name>.active
 	git -C super config --bool submodule.sub1.active "false" &&
 	git -C super config --bool submodule.sub2.active "true" &&
 
-	test_must_fail git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test_must_fail test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active, submodule.active and submodule add' '
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 07/32] submodule--helper: move "check-name" to a test-tool
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (5 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 06/32] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 08/32] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
                     ` (25 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Move the "check-name" helper to a test-tool, since
a6226fd772b (submodule--helper: convert the bulk of cmd_add() to C,
2021-08-10) it has only been used by this test, not git-submodule.sh.

As noted with its introduction in 0383bbb9015 (submodule-config:
verify submodule names as paths, 2018-04-30) the intent of
t7450-bad-git-dotfiles.sh has always been to unit test the
check_submodule_name() function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 24 -------------------
 t/helper/test-submodule.c   | 46 +++++++++++++++++++++++++++++++++++++
 t/t7450-bad-git-dotfiles.sh |  2 +-
 3 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e10c3ac7550..e8458567976 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2731,29 +2731,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-/*
- * Exit non-zero if any of the submodule names given on the command line is
- * invalid. If no names are given, filter stdin to print only valid names
- * (which is primarily intended for testing).
- */
-static int check_name(int argc, const char **argv, const char *prefix)
-{
-	if (argc > 1) {
-		while (*++argv) {
-			if (check_submodule_name(*argv) < 0)
-				return 1;
-		}
-	} else {
-		struct strbuf buf = STRBUF_INIT;
-		while (strbuf_getline(&buf, stdin) != EOF) {
-			if (!check_submodule_name(buf.buf))
-				printf("%s\n", buf.buf);
-		}
-		strbuf_release(&buf);
-	}
-	return 0;
-}
-
 static int module_config(int argc, const char **argv, const char *prefix)
 {
 	enum {
@@ -3308,7 +3285,6 @@ static struct cmd_struct commands[] = {
 	{"summary", module_summary, 0},
 	{"push-check", push_check, 0},
 	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
-	{"check-name", check_name, 0},
 	{"config", module_config, 0},
 	{"set-url", module_set_url, 0},
 	{"set-branch", module_set_branch, 0},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 494c6558d9f..9f0eb440192 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -2,8 +2,16 @@
 #include "test-tool-utils.h"
 #include "cache.h"
 #include "parse-options.h"
+#include "submodule-config.h"
 #include "submodule.h"
 
+#define TEST_TOOL_CHECK_NAME_USAGE \
+	"test-tool submodule check-name <name>"
+static const char *submodule_check_name_usage[] = {
+	TEST_TOOL_CHECK_NAME_USAGE,
+	NULL
+};
+
 #define TEST_TOOL_IS_ACTIVE_USAGE \
 	"test-tool submodule is-active <name>"
 static const char *submodule_is_active_usage[] = {
@@ -12,10 +20,47 @@ static const char *submodule_is_active_usage[] = {
 };
 
 static const char *submodule_usage[] = {
+	TEST_TOOL_CHECK_NAME_USAGE,
 	TEST_TOOL_IS_ACTIVE_USAGE,
 	NULL
 };
 
+/*
+ * Exit non-zero if any of the submodule names given on the command line is
+ * invalid. If no names are given, filter stdin to print only valid names
+ * (which is primarily intended for testing).
+ */
+static int check_name(int argc, const char **argv)
+{
+	if (argc > 1) {
+		while (*++argv) {
+			if (check_submodule_name(*argv) < 0)
+				return 1;
+		}
+	} else {
+		struct strbuf buf = STRBUF_INIT;
+		while (strbuf_getline(&buf, stdin) != EOF) {
+			if (!check_submodule_name(buf.buf))
+				printf("%s\n", buf.buf);
+		}
+		strbuf_release(&buf);
+	}
+	return 0;
+}
+
+static int cmd__submodule_check_name(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_check_name_usage, 0);
+	if (argc)
+		usage_with_options(submodule_check_name_usage, options);
+
+	return check_name(argc, argv);
+}
+
 static int cmd__submodule_is_active(int argc, const char **argv)
 {
 	struct option options[] = {
@@ -32,6 +77,7 @@ static int cmd__submodule_is_active(int argc, const char **argv)
 }
 
 static struct test_cmd cmds[] = {
+	{ "check-name", cmd__submodule_check_name },
 	{ "is-active", cmd__submodule_is_active },
 };
 
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index 41706c1c9ff..2c24f120da3 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -21,7 +21,7 @@ test_expect_success 'check names' '
 	valid/with/paths
 	EOF
 
-	git submodule--helper check-name >actual <<-\EOF &&
+	test-tool submodule check-name >actual <<-\EOF &&
 	valid
 	valid/with/paths
 
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 08/32] submodule--helper: move "resolve-relative-url-test" to a test-tool
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (6 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 07/32] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 09/32] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
                     ` (24 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

As its name suggests the "resolve-relative-url-test" has never been
used outside of the test suite, see 63e95beb085 (submodule: port
resolve_relative_url from shell to C, 2016-04-15) for its original
addition.

Perhaps it would make sense to drop this code entirely, as we feel
that we've got enough indirect test coverage, but let's leave that
question to a possible follow-up change. For now let's keep the test
coverage this gives us.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 23 --------------------
 t/helper/test-submodule.c   | 42 +++++++++++++++++++++++++++++++++++++
 t/t0060-path-utils.sh       |  2 +-
 3 files changed, 43 insertions(+), 24 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e8458567976..7e2986902dd 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -96,28 +96,6 @@ static char *resolve_relative_url(const char *rel_url, const char *up_path, int
 	return resolved_url;
 }
 
-static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
-{
-	char *remoteurl, *res;
-	const char *up_path, *url;
-
-	if (argc != 4)
-		die("resolve-relative-url-test only accepts three arguments: <up_path> <remoteurl> <url>");
-
-	up_path = argv[1];
-	remoteurl = xstrdup(argv[2]);
-	url = argv[3];
-
-	if (!strcmp(up_path, "(null)"))
-		up_path = NULL;
-
-	res = relative_url(remoteurl, url, up_path);
-	puts(res);
-	free(res);
-	free(remoteurl);
-	return 0;
-}
-
 /* the result should be freed by the caller. */
 static char *get_submodule_displaypath(const char *path, const char *prefix)
 {
@@ -3276,7 +3254,6 @@ static struct cmd_struct commands[] = {
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
-	{"resolve-relative-url-test", resolve_relative_url_test, 0},
 	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
 	{"init", module_init, 0},
 	{"status", module_status, SUPPORT_SUPER_PREFIX},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 9f0eb440192..e0e0c53d386 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -2,6 +2,7 @@
 #include "test-tool-utils.h"
 #include "cache.h"
 #include "parse-options.h"
+#include "remote.h"
 #include "submodule-config.h"
 #include "submodule.h"
 
@@ -19,9 +20,17 @@ static const char *submodule_is_active_usage[] = {
 	NULL
 };
 
+#define TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE \
+	"test-tool submodule resolve-relative-url <up_path> <remoteurl> <url>"
+static const char *submodule_resolve_relative_url_usage[] = {
+	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
+	NULL,
+};
+
 static const char *submodule_usage[] = {
 	TEST_TOOL_CHECK_NAME_USAGE,
 	TEST_TOOL_IS_ACTIVE_USAGE,
+	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
 	NULL
 };
 
@@ -76,9 +85,42 @@ static int cmd__submodule_is_active(int argc, const char **argv)
 	return !is_submodule_active(the_repository, argv[0]);
 }
 
+static int resolve_relative_url(int argc, const char **argv)
+{
+	char *remoteurl, *res;
+	const char *up_path, *url;
+
+	up_path = argv[0];
+	remoteurl = xstrdup(argv[1]);
+	url = argv[2];
+
+	if (!strcmp(up_path, "(null)"))
+		up_path = NULL;
+
+	res = relative_url(remoteurl, url, up_path);
+	puts(res);
+	free(res);
+	free(remoteurl);
+	return 0;
+}
+
+static int cmd__submodule_resolve_relative_url(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_resolve_relative_url_usage, 0);
+	if (argc != 3)
+		usage_with_options(submodule_resolve_relative_url_usage, options);
+
+	return resolve_relative_url(argc, argv);
+}
+
 static struct test_cmd cmds[] = {
 	{ "check-name", cmd__submodule_check_name },
 	{ "is-active", cmd__submodule_is_active },
+	{ "resolve-relative-url", cmd__submodule_resolve_relative_url},
 };
 
 int cmd__submodule(int argc, const char **argv)
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 1f2007e62b7..68e29c904a6 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -22,7 +22,7 @@ relative_path() {
 
 test_submodule_relative_url() {
 	test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" "
-		actual=\$(git submodule--helper resolve-relative-url-test '$1' '$2' '$3') &&
+		actual=\$(test-tool submodule resolve-relative-url '$1' '$2' '$3') &&
 		test \"\$actual\" = '$4'
 	"
 }
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 09/32] submodule--helper style: don't separate declared variables with \n\n
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (7 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 08/32] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 10/32] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
                     ` (23 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The usual style in the codebase is to separate declared variables with
a single newline, not two, let's adjust this code to conform to
that. This makes the eventual addition of various "int ret" variables
more consistent.

In doing this the comment added in 2964d6e5e1e (submodule: port
subcommand 'set-branch' from shell to C, 2020-06-02) might become
ambiguous to some, although it should be clear what it's referring to,
let's move it above the 'OPT_NOOP_NOARG('q', "quiet")' to make that
clearer.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 33 +++++----------------------------
 1 file changed, 5 insertions(+), 28 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 7e2986902dd..02552410679 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -368,14 +368,12 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	struct foreach_cb info = FOREACH_CB_INIT;
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
-
 	struct option module_foreach_options[] = {
 		OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
 		OPT_BOOL(0, "recursive", &info.recursive,
 			 N_("recurse into nested submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
 		NULL
@@ -504,12 +502,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
-
 	struct option module_init_options[] = {
 		OPT__QUIET(&quiet, N_("suppress output for initializing a submodule")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule init [<options>] [<path>]"),
 		NULL
@@ -682,14 +678,12 @@ static int module_status(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
-
 	struct option module_status_options[] = {
 		OPT__QUIET(&quiet, N_("suppress submodule status output")),
 		OPT_BIT(0, "cached", &info.flags, N_("use commit stored in the index instead of the one stored in the submodule HEAD"), OPT_CACHED),
 		OPT_BIT(0, "recursive", &info.flags, N_("recurse into nested submodules"), OPT_RECURSIVE),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
 		NULL
@@ -1085,7 +1079,6 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 	enum diff_cmd diff_cmd = DIFF_INDEX;
 	struct object_id head_oid;
 	int ret;
-
 	struct option module_summary_options[] = {
 		OPT_BOOL(0, "cached", &cached,
 			 N_("use the commit stored in the index instead of the submodule HEAD")),
@@ -1097,7 +1090,6 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 			     N_("limit the summary size")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule summary [<options>] [<commit>] [--] [<path>]"),
 		NULL
@@ -1254,14 +1246,12 @@ static int module_sync(int argc, const char **argv, const char *prefix)
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
 	int recursive = 0;
-
 	struct option module_sync_options[] = {
 		OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
 		OPT_BOOL(0, "recursive", &recursive,
 			N_("recurse into nested submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule sync [--quiet] [--recursive] [<path>]"),
 		NULL
@@ -1393,14 +1383,12 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
 	int quiet = 0;
 	int force = 0;
 	int all = 0;
-
 	struct option module_deinit_options[] = {
 		OPT__QUIET(&quiet, N_("suppress submodule status output")),
 		OPT__FORCE(&force, N_("remove submodule working trees even if they contain local changes"), 0),
 		OPT_BOOL(0, "all", &all, N_("unregister all submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
 		NULL
@@ -1669,7 +1657,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
 	struct list_objects_filter_options filter_options;
-
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1701,7 +1688,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule--helper clone [--prefix=<path>] [--quiet] "
 		   "[--reference <repository>] [--name <name>] [--depth <depth>] "
@@ -2489,7 +2475,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 	struct update_data opt = UPDATE_DATA_INIT;
 	struct list_objects_filter_options filter_options;
 	int ret;
-
 	struct option module_update_options[] = {
 		OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
 		OPT_BOOL(0, "init", &opt.init,
@@ -2533,7 +2518,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule [--quiet] update"
 		" [--init [--filter=<filter-spec>]] [--remote]"
@@ -2682,7 +2666,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
-
 	struct option embed_gitdir_options[] = {
 		OPT_STRING(0, "prefix", &prefix,
 			   N_("path"),
@@ -2691,7 +2674,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 			ABSORB_GITDIR_RECURSE_SUBMODULES),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule absorbgitdirs [<options>] [<path>...]"),
 		NULL
@@ -2715,7 +2697,6 @@ static int module_config(int argc, const char **argv, const char *prefix)
 		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"),
@@ -2761,7 +2742,6 @@ static int module_set_url(int argc, const char **argv, const char *prefix)
 	const char *newurl;
 	const char *path;
 	char *config_name;
-
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("suppress output for setting url of a submodule")),
 		OPT_END()
@@ -2792,13 +2772,13 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
 	const char *opt_branch = NULL;
 	const char *path;
 	char *config_name;
-
-	/*
-	 * We accept the `quiet` option for uniformity across subcommands,
-	 * though there is nothing to make less verbose in this subcommand.
-	 */
 	struct option options[] = {
+		/*
+		 * We accept the `quiet` option for uniformity across subcommands,
+		 * though there is nothing to make less verbose in this subcommand.
+		 */
 		OPT_NOOP_NOARG('q', "quiet"),
+
 		OPT_BOOL('d', "default", &opt_default,
 			N_("set the default tracking branch to master")),
 		OPT_STRING('b', "branch", &opt_branch, N_("branch"),
@@ -2833,7 +2813,6 @@ static int module_create_branch(int argc, const char **argv, const char *prefix)
 {
 	enum branch_track track;
 	int quiet = 0, force = 0, reflog = 0, dry_run = 0;
-
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("print only error messages")),
 		OPT__FORCE(&force, N_("force creation"), 0),
@@ -3132,7 +3111,6 @@ static int module_add(int argc, const char **argv, const char *prefix)
 	int force = 0, quiet = 0, progress = 0, dissociate = 0;
 	struct add_data add_data = ADD_DATA_INIT;
 	char *to_free = NULL;
-
 	struct option options[] = {
 		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
 			   N_("branch of repository to add as submodule")),
@@ -3149,7 +3127,6 @@ static int module_add(int argc, const char **argv, const char *prefix)
 		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
 		OPT_END()
 	};
-
 	const char *const usage[] = {
 		N_("git submodule add [<options>] [--] <repository> [<path>]"),
 		NULL
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 10/32] submodule--helper style: add \n\n after variable declarations
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (8 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 09/32] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 11/32] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
                     ` (22 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Since the preceding commit fixed style issues with \n\n among the
declared variables let's fix the minor stylistic issues with those
variables not being consistently followed by a \n\n.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 02552410679..a492ea3cfed 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -167,6 +167,7 @@ static int module_list_compute(int argc, const char **argv,
 {
 	int i, result = 0;
 	char *ps_matched = NULL;
+
 	parse_pathspec(pathspec, 0,
 		       PATHSPEC_PREFER_FULL,
 		       prefix, argv);
@@ -248,6 +249,7 @@ static void for_each_listed_submodule(const struct module_list *list,
 				      each_submodule_fn fn, void *cb_data)
 {
 	int i;
+
 	for (i = 0; i < list->nr; i++)
 		fn(list->entries[i], cb_data);
 }
@@ -267,7 +269,6 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
 	struct foreach_cb *info = cb_data;
 	const char *path = list_item->name;
 	const struct object_id *ce_oid = &list_item->oid;
-
 	const struct submodule *sub;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *displaypath;
@@ -456,6 +457,7 @@ static void init_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(url) ||
 		    starts_with_dot_slash(url)) {
 			char *oldurl = url;
+
 			url = resolve_relative_url(oldurl, NULL, 0);
 			free(oldurl);
 		}
@@ -493,6 +495,7 @@ static void init_submodule(const char *path, const char *prefix,
 static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
 {
 	struct init_cb *info = cb_data;
+
 	init_submodule(list_item->name, info->prefix, info->flags);
 }
 
@@ -562,6 +565,7 @@ static int handle_submodule_head_ref(const char *refname,
 				     void *cb_data)
 {
 	struct object_id *output = cb_data;
+
 	if (oid)
 		oidcpy(output, oid);
 
@@ -668,6 +672,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
 				void *cb_data)
 {
 	struct status_cb *info = cb_data;
+
 	status_submodule(list_item->name, &list_item->oid, list_item->ce_flags,
 			 info->prefix, info->flags);
 }
@@ -820,6 +825,7 @@ static void generate_submodule_summary(struct summary_cb *info,
 	if (!info->cached && oideq(&p->oid_dst, null_oid())) {
 		if (S_ISGITLINK(p->mod_dst)) {
 			struct ref_store *refs = get_submodule_ref_store(p->sm_path);
+
 			if (refs)
 				refs_head_ref(refs, handle_submodule_head_ref, &p->oid_dst);
 		} else if (S_ISLNK(p->mod_dst) || S_ISREG(p->mod_dst)) {
@@ -1161,6 +1167,7 @@ static void sync_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
 			char *up_path = get_up_path(path);
+
 			sub_origin_url = resolve_relative_url(sub->url, up_path, 1);
 			super_config_url = resolve_relative_url(sub->url, NULL, 1);
 			free(up_path);
@@ -1236,6 +1243,7 @@ static void sync_submodule(const char *path, const char *prefix,
 static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data)
 {
 	struct sync_cb *info = cb_data;
+
 	sync_submodule(list_item->name, info->prefix, info->flags);
 }
 
@@ -1315,6 +1323,7 @@ static void deinit_submodule(const char *path, const char *prefix,
 
 		if (!(flags & OPT_FORCE)) {
 			struct child_process cp_rm = CHILD_PROCESS_INIT;
+
 			cp_rm.git_cmd = 1;
 			strvec_pushl(&cp_rm.args, "rm", "-qn",
 				     path, NULL);
@@ -1351,6 +1360,7 @@ static void deinit_submodule(const char *path, const char *prefix,
 	/* remove the .git/config entries (unless the user already did it) */
 	if (!capture_command(&cp_config, &sb_config, 0) && sb_config.len) {
 		char *sub_key = xstrfmt("submodule.%s", sub->name);
+
 		/*
 		 * remove the whole section so we have a clean state when
 		 * the user later decides to init this submodule again
@@ -1588,6 +1598,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
 		if (clone_data->reference.nr) {
 			struct string_list_item *item;
+
 			for_each_string_list_item(item, &clone_data->reference)
 				strvec_pushl(&cp.args, "--reference",
 					     item->string, NULL);
@@ -1938,6 +1949,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	strvec_pushl(&child->args, "--url", url, NULL);
 	if (suc->update_data->references.nr) {
 		struct string_list_item *item;
+
 		for_each_string_list_item(item, &suc->update_data->references)
 			strvec_pushl(&child->args, "--reference", item->string, NULL);
 	}
@@ -1970,6 +1982,7 @@ static int update_clone_get_next_task(struct child_process *child,
 		ce = suc->update_data->list.entries[suc->current];
 		if (prepare_to_clone_next_submodule(ce, child, suc, err)) {
 			int *p = xmalloc(sizeof(*p));
+
 			*p = suc->current;
 			*idx_task_cb = p;
 			suc->current++;
@@ -1985,6 +1998,7 @@ static int update_clone_get_next_task(struct child_process *child,
 	index = suc->current - suc->update_data->list.nr;
 	if (index < suc->failed_clones_nr) {
 		int *p;
+
 		ce = suc->failed_clones[index];
 		if (!prepare_to_clone_next_submodule(ce, child, suc, err)) {
 			suc->current ++;
@@ -2008,6 +2022,7 @@ static int update_clone_start_failure(struct strbuf *err,
 				      void *idx_task_cb)
 {
 	struct submodule_update_clone *suc = suc_cb;
+
 	suc->quickstop = 1;
 	return 1;
 }
@@ -2019,9 +2034,9 @@ static int update_clone_task_finished(int result,
 {
 	const struct cache_entry *ce;
 	struct submodule_update_clone *suc = suc_cb;
-
 	int *idxP = idx_task_cb;
 	int idx = *idxP;
+
 	free(idxP);
 
 	if (!result)
@@ -2054,6 +2069,7 @@ static int git_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;
@@ -2094,6 +2110,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	if (oid) {
 		char *hex = oid_to_hex(oid);
 		char *remote = get_default_remote();
+
 		strvec_pushl(&cp.args, remote, hex, NULL);
 		free(remote);
 	}
@@ -2343,6 +2360,7 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 
 	if (update_data->references.nr) {
 		struct string_list_item *item;
+
 		for_each_string_list_item(item, &update_data->references)
 			strvec_pushl(args, "--reference", item->string, NULL);
 	}
@@ -2875,8 +2893,10 @@ static void append_fetch_remotes(struct strbuf *msg, const char *git_dir_path)
 	if (!capture_command(&cp_remote, &sb_remote_out, 0)) {
 		char *next_line;
 		char *line = sb_remote_out.buf;
+
 		while ((next_line = strchr(line, '\n')) != NULL) {
 			size_t len = next_line - line;
+
 			if (strip_suffix_mem(line, &len, " (fetch)"))
 				strbuf_addf(msg, "  %.*s\n", (int)len, line);
 			line = next_line + 1;
@@ -3183,6 +3203,7 @@ static int module_add(int argc, const char **argv, const char *prefix)
 		int exit_code = -1;
 		struct strbuf sb = STRBUF_INIT;
 		struct child_process cp = CHILD_PROCESS_INIT;
+
 		cp.git_cmd = 1;
 		cp.no_stdout = 1;
 		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 11/32] submodule--helper: replace memset() with { 0 }-initialization
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (9 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 10/32] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 12/32] submodule--helper: use xstrfmt() in clone_submodule() Ævar Arnfjörð Bjarmason
                     ` (21 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Use the less verbose { 0 }-initialization syntax rather than memset()
in builtin/submodule--helper.c, this doesn't make a difference in
terms of behavior, but as we're about to modify adjacent code makes
this more consistent, and lets us avoid worrying about when the
memset() happens v.s. a "goto cleanup".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a492ea3cfed..7eb9fb2f00f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1667,7 +1667,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 {
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
-	struct list_objects_filter_options filter_options;
+	struct list_objects_filter_options filter_options = { 0 };
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1707,7 +1707,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		NULL
 	};
 
-	memset(&filter_options, 0, sizeof(filter_options));
 	argc = parse_options(argc, argv, prefix, module_clone_options,
 			     git_submodule_helper_usage, 0);
 
@@ -2491,7 +2490,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
 {
 	struct pathspec pathspec;
 	struct update_data opt = UPDATE_DATA_INIT;
-	struct list_objects_filter_options filter_options;
+	struct list_objects_filter_options filter_options = { 0 };
 	int ret;
 	struct option module_update_options[] = {
 		OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
@@ -2549,7 +2548,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 	update_clone_config_from_gitmodules(&opt.max_jobs);
 	git_config(git_update_clone_config, &opt.max_jobs);
 
-	memset(&filter_options, 0, sizeof(filter_options));
 	argc = parse_options(argc, argv, prefix, module_update_options,
 			     git_submodule_helper_usage, 0);
 
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 12/32] submodule--helper: use xstrfmt() in clone_submodule()
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (10 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 11/32] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 13/32] submodule--helper: move "sb" in clone_submodule() to its own scope Ævar Arnfjörð Bjarmason
                     ` (20 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Use xstrfmt() in clone_submodule() instead of a "struct strbuf" in two
cases where we weren't getting anything out of using the "struct
strbuf".

This changes code that was was added along with other uses of "struct
strbuf" in this function in ee8838d1577 (submodule: rewrite
`module_clone` shell function in C, 2015-09-08).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 7eb9fb2f00f..c7833bae81e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1571,12 +1571,11 @@ static int clone_submodule(struct module_clone_data *clone_data)
 	sm_gitdir = absolute_pathdup(sb.buf);
 	strbuf_reset(&sb);
 
-	if (!is_absolute_path(clone_data->path)) {
-		strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
-		clone_data->path = strbuf_detach(&sb, NULL);
-	} else {
+	if (!is_absolute_path(clone_data->path))
+		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
+					   clone_data->path);
+	else
 		clone_data->path = xstrdup(clone_data->path);
-	}
 
 	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
 		die(_("refusing to create/use '%s' in another submodule's "
@@ -1628,14 +1627,16 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			die(_("clone of '%s' into submodule path '%s' failed"),
 			    clone_data->url, clone_data->path);
 	} else {
+		char *path;
+
 		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
 		    !is_empty_dir(clone_data->path))
 			die(_("directory not empty: '%s'"), clone_data->path);
 		if (safe_create_leading_directories_const(clone_data->path) < 0)
 			die(_("could not create directory '%s'"), clone_data->path);
-		strbuf_addf(&sb, "%s/index", sm_gitdir);
-		unlink_or_warn(sb.buf);
-		strbuf_reset(&sb);
+		path = xstrfmt("%s/index", sm_gitdir);
+		unlink_or_warn(path);
+		free(path);
 	}
 
 	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 13/32] submodule--helper: move "sb" in clone_submodule() to its own scope
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (11 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 12/32] submodule--helper: use xstrfmt() in clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 14/32] submodule--helper: add "const" to passed "module_clone_data" Ævar Arnfjörð Bjarmason
                     ` (19 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Refactor the only remaining use of a "struct strbuf sb" in
clone_submodule() to live in its own scope. This makes the code
clearer by limiting its lifetime.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index c7833bae81e..2f1f0e1bf34 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1560,16 +1560,24 @@ static void prepare_possible_alternates(const char *sm_name,
 	free(error_strategy);
 }
 
-static int clone_submodule(struct module_clone_data *clone_data)
+static char *clone_submodule_sm_gitdir(const char *name)
 {
-	char *p, *sm_gitdir;
-	char *sm_alternate = NULL, *error_strategy = NULL;
 	struct strbuf sb = STRBUF_INIT;
-	struct child_process cp = CHILD_PROCESS_INIT;
+	char *sm_gitdir;
 
-	submodule_name_to_gitdir(&sb, the_repository, clone_data->name);
+	submodule_name_to_gitdir(&sb, the_repository, name);
 	sm_gitdir = absolute_pathdup(sb.buf);
-	strbuf_reset(&sb);
+	strbuf_release(&sb);
+
+	return sm_gitdir;
+}
+
+static int clone_submodule(struct module_clone_data *clone_data)
+{
+	char *p;
+	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
+	char *sm_alternate = NULL, *error_strategy = NULL;
+	struct child_process cp = CHILD_PROCESS_INIT;
 
 	if (!is_absolute_path(clone_data->path))
 		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
@@ -1658,7 +1666,6 @@ static int clone_submodule(struct module_clone_data *clone_data)
 	free(sm_alternate);
 	free(error_strategy);
 
-	strbuf_release(&sb);
 	free(sm_gitdir);
 	free(p);
 	return 0;
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 14/32] submodule--helper: add "const" to passed "module_clone_data"
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (12 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 13/32] submodule--helper: move "sb" in clone_submodule() to its own scope Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 15/32] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
                     ` (18 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add "const" to the "struct module_clone_data" that we pass to
clone_submodule(), which makes the ownership clear, and stops us from
clobbering the "clone_data->path".

We still need to add to the "reference" member, which is a "struct
string_list". Let's do this by having clone_submodule() create its
own, and copy the contents over, allowing us to pass it as a
separate parameter.

This new "struct string_list" still leaks memory, just as the "struct
module_clone_data" did before. let's not fix that for now, to fix that
we'll need to add some "goto cleanup" to the relevant code. That will
eventually be done in follow-up commits, this change makes it easier
to fix the memory leak.

The scope of the new "reference" variable in add_submodule() could be
narrowed to the "else" block, but as we'll eventually free it with a
"goto cleanup" let's declare it at the start of the function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 49 ++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2f1f0e1bf34..d243c3ddfd3 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1437,7 +1437,6 @@ struct module_clone_data {
 	const char *url;
 	const char *depth;
 	struct list_objects_filter_options *filter_options;
-	struct string_list reference;
 	unsigned int quiet: 1;
 	unsigned int progress: 1;
 	unsigned int dissociate: 1;
@@ -1445,7 +1444,6 @@ struct module_clone_data {
 	int single_branch;
 };
 #define MODULE_CLONE_DATA_INIT { \
-	.reference = STRING_LIST_INIT_NODUP, \
 	.single_branch = -1, \
 }
 
@@ -1572,18 +1570,20 @@ static char *clone_submodule_sm_gitdir(const char *name)
 	return sm_gitdir;
 }
 
-static int clone_submodule(struct module_clone_data *clone_data)
+static int clone_submodule(const struct module_clone_data *clone_data,
+			   struct string_list *reference)
 {
 	char *p;
 	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
 	char *sm_alternate = NULL, *error_strategy = NULL;
 	struct child_process cp = CHILD_PROCESS_INIT;
+	const char *clone_data_path;
 
 	if (!is_absolute_path(clone_data->path))
-		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
-					   clone_data->path);
+		clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
+					  clone_data->path);
 	else
-		clone_data->path = xstrdup(clone_data->path);
+		clone_data_path = xstrdup(clone_data->path);
 
 	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
 		die(_("refusing to create/use '%s' in another submodule's "
@@ -1593,7 +1593,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 		if (safe_create_leading_directories_const(sm_gitdir) < 0)
 			die(_("could not create directory '%s'"), sm_gitdir);
 
-		prepare_possible_alternates(clone_data->name, &clone_data->reference);
+		prepare_possible_alternates(clone_data->name, reference);
 
 		strvec_push(&cp.args, "clone");
 		strvec_push(&cp.args, "--no-checkout");
@@ -1603,10 +1603,10 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			strvec_push(&cp.args, "--progress");
 		if (clone_data->depth && *(clone_data->depth))
 			strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
-		if (clone_data->reference.nr) {
+		if (reference->nr) {
 			struct string_list_item *item;
 
-			for_each_string_list_item(item, &clone_data->reference)
+			for_each_string_list_item(item, reference)
 				strvec_pushl(&cp.args, "--reference",
 					     item->string, NULL);
 		}
@@ -1625,7 +1625,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 
 		strvec_push(&cp.args, "--");
 		strvec_push(&cp.args, clone_data->url);
-		strvec_push(&cp.args, clone_data->path);
+		strvec_push(&cp.args, clone_data_path);
 
 		cp.git_cmd = 1;
 		prepare_submodule_repo_env(&cp.env);
@@ -1633,25 +1633,25 @@ static int clone_submodule(struct module_clone_data *clone_data)
 
 		if(run_command(&cp))
 			die(_("clone of '%s' into submodule path '%s' failed"),
-			    clone_data->url, clone_data->path);
+			    clone_data->url, clone_data_path);
 	} else {
 		char *path;
 
-		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
-		    !is_empty_dir(clone_data->path))
-			die(_("directory not empty: '%s'"), clone_data->path);
-		if (safe_create_leading_directories_const(clone_data->path) < 0)
-			die(_("could not create directory '%s'"), clone_data->path);
+		if (clone_data->require_init && !access(clone_data_path, X_OK) &&
+		    !is_empty_dir(clone_data_path))
+			die(_("directory not empty: '%s'"), clone_data_path);
+		if (safe_create_leading_directories_const(clone_data_path) < 0)
+			die(_("could not create directory '%s'"), clone_data_path);
 		path = xstrfmt("%s/index", sm_gitdir);
 		unlink_or_warn(path);
 		free(path);
 	}
 
-	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
+	connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0);
 
-	p = git_pathdup_submodule(clone_data->path, "config");
+	p = git_pathdup_submodule(clone_data_path, "config");
 	if (!p)
-		die(_("could not get submodule directory for '%s'"), clone_data->path);
+		die(_("could not get submodule directory for '%s'"), clone_data_path);
 
 	/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
 	git_config_get_string("submodule.alternateLocation", &sm_alternate);
@@ -1676,6 +1676,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
 	struct list_objects_filter_options filter_options = { 0 };
+	struct string_list reference = STRING_LIST_INIT_NODUP;
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1689,7 +1690,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		OPT_STRING(0, "url", &clone_data.url,
 			   N_("string"),
 			   N_("url where to clone the submodule from")),
-		OPT_STRING_LIST(0, "reference", &clone_data.reference,
+		OPT_STRING_LIST(0, "reference", &reference,
 			   N_("repo"),
 			   N_("reference repository")),
 		OPT_BOOL(0, "dissociate", &dissociate,
@@ -1728,7 +1729,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		usage_with_options(git_submodule_helper_usage,
 				   module_clone_options);
 
-	clone_submodule(&clone_data);
+	clone_submodule(&clone_data, &reference);
 	list_objects_filter_release(&filter_options);
 	return 0;
 }
@@ -2916,6 +2917,7 @@ static int add_submodule(const struct add_data *add_data)
 {
 	char *submod_gitdir_path;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
+	struct string_list reference = STRING_LIST_INIT_NODUP;
 
 	/* perhaps the path already exists and is already a git repo, else clone it */
 	if (is_directory(add_data->sm_path)) {
@@ -2932,6 +2934,7 @@ static int add_submodule(const struct add_data *add_data)
 		free(submod_gitdir_path);
 	} else {
 		struct child_process cp = CHILD_PROCESS_INIT;
+
 		submod_gitdir_path = xstrfmt(".git/modules/%s", add_data->sm_name);
 
 		if (is_directory(submod_gitdir_path)) {
@@ -2971,13 +2974,13 @@ static int add_submodule(const struct add_data *add_data)
 		clone_data.quiet = add_data->quiet;
 		clone_data.progress = add_data->progress;
 		if (add_data->reference_path)
-			string_list_append(&clone_data.reference,
+			string_list_append(&reference,
 					   xstrdup(add_data->reference_path));
 		clone_data.dissociate = add_data->dissociate;
 		if (add_data->depth >= 0)
 			clone_data.depth = xstrfmt("%d", add_data->depth);
 
-		if (clone_submodule(&clone_data))
+		if (clone_submodule(&clone_data, &reference))
 			return -1;
 
 		prepare_submodule_repo_env(&cp.env);
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 15/32] submodule--helper: add "const" to copy of "update_data"
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (13 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 14/32] submodule--helper: add "const" to passed "module_clone_data" Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 16/32] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
                     ` (17 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

From: Glen Choo <chooglen@google.com>

Add a "const" to the copy of "struct update_data" that's tracked by
the "struct submodule_update_clone", as it neither owns nor modifies
it.

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d243c3ddfd3..829a57ce8a9 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1780,7 +1780,7 @@ struct submodule_update_clone {
 	int current;
 
 	/* configuration parameters which are passed on to the children */
-	struct update_data *update_data;
+	const struct update_data *update_data;
 
 	/* to be consumed by update_submodule() */
 	struct update_clone_data *update_clone;
@@ -1865,7 +1865,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	const char *update_string;
 	enum submodule_update_type update_type;
 	char *key;
-	struct update_data *ud = suc->update_data;
+	const struct update_data *ud = suc->update_data;
 	char *displaypath = get_submodule_displaypath(ce->name, ud->prefix);
 	struct strbuf sb = STRBUF_INIT;
 	int needs_cloning = 0;
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 16/32] submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (14 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 15/32] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 17/32] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
                     ` (16 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

From: Glen Choo <chooglen@google.com>

Refactor code added in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13) so that "errmsg" and
"errmsg_str" are folded into one. The distinction between the empty
string and NULL is something that's tested for by
e.g. "t/t7401-submodule-summary.sh".

This is in preparation for fixing a memory leak the "struct strbuf" in
the pre-image.

Let's also pass a "const char *" to print_submodule_summary(), as it
should not be modifying the "errmsg".

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 829a57ce8a9..a694b18b55e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -761,7 +761,7 @@ static char *verify_submodule_committish(const char *sm_path,
 	return strbuf_detach(&result, NULL);
 }
 
-static void print_submodule_summary(struct summary_cb *info, char *errmsg,
+static void print_submodule_summary(struct summary_cb *info, const char *errmsg,
 				    int total_commits, const char *displaypath,
 				    const char *src_abbrev, const char *dst_abbrev,
 				    struct module_cb *p)
@@ -819,7 +819,7 @@ static void generate_submodule_summary(struct summary_cb *info,
 {
 	char *displaypath, *src_abbrev = NULL, *dst_abbrev;
 	int missing_src = 0, missing_dst = 0;
-	char *errmsg = NULL;
+	struct strbuf errmsg = STRBUF_INIT;
 	int total_commits = -1;
 
 	if (!info->cached && oideq(&p->oid_dst, null_oid())) {
@@ -920,23 +920,21 @@ static void generate_submodule_summary(struct summary_cb *info,
 		 * submodule, i.e., deleted or changed to blob
 		 */
 		if (S_ISGITLINK(p->mod_dst)) {
-			struct strbuf errmsg_str = STRBUF_INIT;
 			if (missing_src && missing_dst) {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commits %s and %s\n",
+				strbuf_addf(&errmsg, "  Warn: %s doesn't contain commits %s and %s\n",
 					    displaypath, oid_to_hex(&p->oid_src),
 					    oid_to_hex(&p->oid_dst));
 			} else {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commit %s\n",
+				strbuf_addf(&errmsg, "  Warn: %s doesn't contain commit %s\n",
 					    displaypath, missing_src ?
 					    oid_to_hex(&p->oid_src) :
 					    oid_to_hex(&p->oid_dst));
 			}
-			errmsg = strbuf_detach(&errmsg_str, NULL);
 		}
 	}
 
-	print_submodule_summary(info, errmsg, total_commits,
-				displaypath, src_abbrev,
+	print_submodule_summary(info, errmsg.len ? errmsg.buf : NULL,
+				total_commits, displaypath, src_abbrev,
 				dst_abbrev, p);
 
 	free(displaypath);
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 17/32] submodule--helper: don't redundantly check "else if (res)"
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (15 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 16/32] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 16:12     ` Eric Sunshine
  2022-08-21 13:57   ` [PATCH v3 18/32] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
                     ` (15 subsequent siblings)
  32 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The "res" variable must be true at this point in update_submodule(),
as just a few lines above this we've unconditionally:

	if (!res)
		return 0;

So we don't need to guard the "return 1" with an "else if (res)", we
an return unconditionally at this point. See b3c5f5cb048 (submodule:
move core cmd_update() logic to C, 2022-03-15) for the initial
introduction of this code, this check of "res" has always been
redundant.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a694b18b55e..a9808224f01 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2446,8 +2446,7 @@ static int update_submodule(struct update_data *update_data)
 			    update_data->displaypath);
 		if (res == 128)
 			exit(res);
-		else if (res)
-			return 1;
+		return 1;
 	}
 
 	return 0;
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 18/32] submodule--helper: rename "int res" to "int ret"
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (16 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 17/32] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 19/32] submodule--helper: return "ret", not "1" from update_submodule() Ævar Arnfjörð Bjarmason
                     ` (14 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Rename the "res" variable added in b3c5f5cb048 (submodule: move core
cmd_update() logic to C, 2022-03-15) to "ret", which is the convention
in the rest of this file.

Eventual follow-up commits will change the code in update_submodule()
to a "goto cleanup" pattern, let's have the post image look consistent
with the rest. For update_submodules() let's also use a "ret" for
consistency, that use was also added in b3c5f5cb048. We'll be
modifying that codepath in subsequent commits.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a9808224f01..fed92585a02 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2427,7 +2427,7 @@ static int update_submodule(struct update_data *update_data)
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		struct update_data next = *update_data;
-		int res;
+		int ret;
 
 		next.prefix = NULL;
 		oidcpy(&next.oid, null_oid());
@@ -2439,13 +2439,13 @@ static int update_submodule(struct update_data *update_data)
 		update_data_to_args(&next, &cp.args);
 
 		/* die() if child process die()'d */
-		res = run_command(&cp);
-		if (!res)
+		ret = run_command(&cp);
+		if (!ret)
 			return 0;
 		die_message(_("Failed to recurse into submodule path '%s'"),
 			    update_data->displaypath);
-		if (res == 128)
-			exit(res);
+		if (ret == 128)
+			exit(ret);
 		return 1;
 	}
 
@@ -2454,7 +2454,7 @@ static int update_submodule(struct update_data *update_data)
 
 static int update_submodules(struct update_data *update_data)
 {
-	int i, res = 0;
+	int i, ret = 0;
 	struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
 
 	suc.update_data = update_data;
@@ -2472,7 +2472,7 @@ static int update_submodules(struct update_data *update_data)
 	 * - the listener can avoid doing any work if fetching failed.
 	 */
 	if (suc.quickstop) {
-		res = 1;
+		ret = 1;
 		goto cleanup;
 	}
 
@@ -2484,12 +2484,12 @@ static int update_submodules(struct update_data *update_data)
 		update_data->sm_path = ucd.sub->path;
 
 		if (update_submodule(update_data))
-			res = 1;
+			ret = 1;
 	}
 
 cleanup:
 	string_list_clear(&update_data->references, 0);
-	return res;
+	return ret;
 }
 
 static int module_update(int argc, const char **argv, const char *prefix)
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 19/32] submodule--helper: return "ret", not "1" from update_submodule()
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (17 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 18/32] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 20/32] submodule--helper: add missing braces to "else" arm Ævar Arnfjörð Bjarmason
                     ` (13 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Amend the update_submodule() function to return the failing "ret" on
error, instead of overriding it with "1".

This code was added in b3c5f5cb048 (submodule: move core cmd_update()
logic to C, 2022-03-15), and this change ends up not making a
difference as this function is only called in update_submodules(). If
we return non-zero here we'll always in turn return "1" in
module_update().

But if we didn't do that and returned any other non-zero exit code in
update_submodules() we'd fail the test that's being amended
here. We're still testing the status quo here.

This change makes subsequent refactoring of update_submodule() easier,
as we'll no longer need to worry about clobbering the "ret" we get
from the run_command().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 2 +-
 t/t7406-submodule-update.sh | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fed92585a02..61468237af2 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2446,7 +2446,7 @@ static int update_submodule(struct update_data *update_data)
 			    update_data->displaypath);
 		if (ret == 128)
 			exit(ret);
-		return 1;
+		return ret;
 	}
 
 	return 0;
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 6cc07460dd2..c5f5dbe55e0 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -769,7 +769,7 @@ test_expect_success 'submodule update continues after recursive checkout error'
 	   echo "" > file
 	  )
 	 ) &&
-	 test_must_fail git submodule update --recursive &&
+	 test_expect_code 1 git submodule update --recursive &&
 	 (cd submodule2 &&
 	  git rev-parse --verify HEAD >../actual
 	 ) &&
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 20/32] submodule--helper: add missing braces to "else" arm
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (18 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 19/32] submodule--helper: return "ret", not "1" from update_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 21/32] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
                     ` (12 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add missing braces to an "else" arm in init_submodule(), this
stylistic change makes this code conform to the CodingGuidelines, and
makes a subsequent commit smaller.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 61468237af2..ebd3e118eb7 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -480,8 +480,9 @@ static void init_submodule(const char *path, const char *prefix,
 			fprintf(stderr, _("warning: command update mode suggested for submodule '%s'\n"),
 				sub->name);
 			upd = xstrdup("none");
-		} else
+		} else {
 			upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy));
+		}
 
 		if (git_config_set_gently(sb.buf, upd))
 			die(_("Failed to register update mode for submodule path '%s'"), displaypath);
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 21/32] submodule--helper: don't call submodule_strategy_to_string() in BUG()
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (19 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 20/32] submodule--helper: add missing braces to "else" arm Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 22/32] submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string() Ævar Arnfjörð Bjarmason
                     ` (11 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Don't call submodule_strategy_to_string() in a BUG() message. These
calls added in c51f8f94e5b (submodule--helper: run update procedures
from C, 2021-08-24) don't need the extra information
submodule_strategy_to_string() gives us, as we'll never reach the
SM_UPDATE_COMMAND case here.

That case is the only one where we'd get any information beyond the
straightforward number-to-string mapping.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index ebd3e118eb7..75bba8621b2 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2158,8 +2158,8 @@ static int run_update_command(struct update_data *ud, int subforce)
 		must_die_on_failure = 1;
 		break;
 	default:
-		BUG("unexpected update strategy type: %s",
-		    submodule_strategy_to_string(&ud->update_strategy));
+		BUG("unexpected update strategy type: %d",
+		    ud->update_strategy.type);
 	}
 	strvec_push(&cp.args, oid);
 
@@ -2184,8 +2184,8 @@ static int run_update_command(struct update_data *ud, int subforce)
 			    ud->update_strategy.command, oid, ud->displaypath);
 			break;
 		default:
-			BUG("unexpected update strategy type: %s",
-			    submodule_strategy_to_string(&ud->update_strategy));
+			BUG("unexpected update strategy type: %d",
+			    ud->update_strategy.type);
 		}
 		if (must_die_on_failure)
 			exit(128);
@@ -2215,8 +2215,8 @@ static int run_update_command(struct update_data *ud, int subforce)
 		       ud->displaypath, ud->update_strategy.command, oid);
 		break;
 	default:
-		BUG("unexpected update strategy type: %s",
-		    submodule_strategy_to_string(&ud->update_strategy));
+		BUG("unexpected update strategy type: %d",
+		    ud->update_strategy.type);
 	}
 
 	return 0;
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 22/32] submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string()
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (20 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 21/32] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 23/32] submodule--helper: use "code" in run_update_command() Ævar Arnfjörð Bjarmason
                     ` (10 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Change the submodule_strategy_to_string() function added in
3604242f080 (submodule: port init from shell to C, 2016-04-15) to
really return a "const char *". In the "SM_UPDATE_COMMAND" case it
would return a strbuf_detach().

Furthermore, this function would return NULL on SM_UPDATE_UNSPECIFIED,
so it wasn't safe to xstrdup() its return value in the general case,
or to use it in a sprintf() format as the code removed in the
preceding commit did.

But its callers would never call it with either SM_UPDATE_UNSPECIFIED
or SM_UPDATE_COMMAND. Let's have its behavior reflect how its only
user expects it to behave, and BUG() out on the rest.

By doing this we can also stop needlessly xstrdup()-ing and free()-ing
the memory for the config we're setting. We can instead always use
constant strings. We can also use the *_tmp() variant of
git_config_get_string().

Let's also rename this submodule_strategy_to_string() function to
submodule_update_type_to_string(). Now that it's only tasked with
returning a string version of the "enum submodule_update_type type".
Before it would look at the "command" field in "struct
submodule_update_strategy".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 10 +++++-----
 submodule.c                 | 12 +++++-------
 submodule.h                 |  2 +-
 3 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 75bba8621b2..c83b0897740 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -418,7 +418,8 @@ static void init_submodule(const char *path, const char *prefix,
 {
 	const struct submodule *sub;
 	struct strbuf sb = STRBUF_INIT;
-	char *upd = NULL, *url = NULL, *displaypath;
+	const char *upd;
+	char *url = NULL, *displaypath;
 
 	displaypath = get_submodule_displaypath(path, prefix);
 
@@ -474,14 +475,14 @@ static void init_submodule(const char *path, const char *prefix,
 
 	/* Copy "update" setting when it is not set yet */
 	strbuf_addf(&sb, "submodule.%s.update", sub->name);
-	if (git_config_get_string(sb.buf, &upd) &&
+	if (git_config_get_string_tmp(sb.buf, &upd) &&
 	    sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
 		if (sub->update_strategy.type == SM_UPDATE_COMMAND) {
 			fprintf(stderr, _("warning: command update mode suggested for submodule '%s'\n"),
 				sub->name);
-			upd = xstrdup("none");
+			upd = "none";
 		} else {
-			upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy));
+			upd = submodule_update_type_to_string(sub->update_strategy.type);
 		}
 
 		if (git_config_set_gently(sb.buf, upd))
@@ -490,7 +491,6 @@ static void init_submodule(const char *path, const char *prefix,
 	strbuf_release(&sb);
 	free(displaypath);
 	free(url);
-	free(upd);
 }
 
 static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
diff --git a/submodule.c b/submodule.c
index 3fa5db3ecdf..1ebda30c506 100644
--- a/submodule.c
+++ b/submodule.c
@@ -415,10 +415,9 @@ int parse_submodule_update_strategy(const char *value,
 	return 0;
 }
 
-const char *submodule_strategy_to_string(const struct submodule_update_strategy *s)
+const char *submodule_update_type_to_string(enum submodule_update_type type)
 {
-	struct strbuf sb = STRBUF_INIT;
-	switch (s->type) {
+	switch (type) {
 	case SM_UPDATE_CHECKOUT:
 		return "checkout";
 	case SM_UPDATE_MERGE:
@@ -428,12 +427,11 @@ const char *submodule_strategy_to_string(const struct submodule_update_strategy
 	case SM_UPDATE_NONE:
 		return "none";
 	case SM_UPDATE_UNSPECIFIED:
-		return NULL;
 	case SM_UPDATE_COMMAND:
-		strbuf_addf(&sb, "!%s", s->command);
-		return strbuf_detach(&sb, NULL);
+		BUG("init_submodule() should handle type %d", type);
+	default:
+		BUG("unexpected update strategy type: %d", type);
 	}
-	return NULL;
 }
 
 void handle_ignore_submodules_arg(struct diff_options *diffopt,
diff --git a/submodule.h b/submodule.h
index bfaa9da1868..6a9fec6de11 100644
--- a/submodule.h
+++ b/submodule.h
@@ -72,7 +72,7 @@ void die_path_inside_submodule(struct index_state *istate,
 enum submodule_update_type parse_submodule_update_type(const char *value);
 int parse_submodule_update_strategy(const char *value,
 				    struct submodule_update_strategy *dst);
-const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);
+const char *submodule_update_type_to_string(enum submodule_update_type type);
 void handle_ignore_submodules_arg(struct diff_options *, const char *);
 void show_submodule_diff_summary(struct diff_options *o, const char *path,
 			    struct object_id *one, struct object_id *two,
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 23/32] submodule--helper: use "code" in run_update_command()
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (21 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 22/32] submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 24/32] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
                     ` (9 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Apply some DRY principles in run_update_command() and don't have two
"switch" statements over "ud->update_strategy.type" determine the same
thing.

First we were setting "must_die_on_failure = 1" in all cases except
"SM_UPDATE_CHECKOUT" (and we'd BUG(...) out on the rest). This code
was added in c51f8f94e5b (submodule--helper: run update procedures
from C, 2021-08-24).

Then we'd duplicate same "switch" logic when we were using the
"must_die_on_failure" variable.

Let's instead have the "case" branches in that inner "switch"
determine whether or not the "update must continue" by picking an exit
code.

This also mostly avoids hardcoding the "128" exit code, instead we can
make use of the return value of the die_message() function, which
we've been calling here since 55b3f12cb54 (submodule update: use
die_message(), 2022-03-15). We're still hardcoding it to determine if
we "exit()", but subsequent commit(s) will address that.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index c83b0897740..44b08a01c54 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2129,7 +2129,6 @@ static int run_update_command(struct update_data *ud, int subforce)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
-	int must_die_on_failure = 0;
 
 	switch (ud->update_strategy.type) {
 	case SM_UPDATE_CHECKOUT:
@@ -2143,19 +2142,16 @@ static int run_update_command(struct update_data *ud, int subforce)
 		strvec_push(&cp.args, "rebase");
 		if (ud->quiet)
 			strvec_push(&cp.args, "--quiet");
-		must_die_on_failure = 1;
 		break;
 	case SM_UPDATE_MERGE:
 		cp.git_cmd = 1;
 		strvec_push(&cp.args, "merge");
 		if (ud->quiet)
 			strvec_push(&cp.args, "--quiet");
-		must_die_on_failure = 1;
 		break;
 	case SM_UPDATE_COMMAND:
 		cp.use_shell = 1;
 		strvec_push(&cp.args, ud->update_strategy.command);
-		must_die_on_failure = 1;
 		break;
 	default:
 		BUG("unexpected update strategy type: %d",
@@ -2166,32 +2162,35 @@ static int run_update_command(struct update_data *ud, int subforce)
 	cp.dir = xstrdup(ud->sm_path);
 	prepare_submodule_repo_env(&cp.env);
 	if (run_command(&cp)) {
+		int ret;
+
 		switch (ud->update_strategy.type) {
 		case SM_UPDATE_CHECKOUT:
 			die_message(_("Unable to checkout '%s' in submodule path '%s'"),
 				    oid, ud->displaypath);
+			/* the command failed, but update must continue */
+			ret = 1;
 			break;
 		case SM_UPDATE_REBASE:
-			die_message(_("Unable to rebase '%s' in submodule path '%s'"),
-			    oid, ud->displaypath);
+			ret = die_message(_("Unable to rebase '%s' in submodule path '%s'"),
+					  oid, ud->displaypath);
 			break;
 		case SM_UPDATE_MERGE:
-			die_message(_("Unable to merge '%s' in submodule path '%s'"),
-			    oid, ud->displaypath);
+			ret = die_message(_("Unable to merge '%s' in submodule path '%s'"),
+					  oid, ud->displaypath);
 			break;
 		case SM_UPDATE_COMMAND:
-			die_message(_("Execution of '%s %s' failed in submodule path '%s'"),
-			    ud->update_strategy.command, oid, ud->displaypath);
+			ret = die_message(_("Execution of '%s %s' failed in submodule path '%s'"),
+					  ud->update_strategy.command, oid, ud->displaypath);
 			break;
 		default:
 			BUG("unexpected update strategy type: %d",
 			    ud->update_strategy.type);
 		}
-		if (must_die_on_failure)
-			exit(128);
 
-		/* the command failed, but update must continue */
-		return 1;
+		if (ret == 128)
+			exit(ret);
+		return ret;
 	}
 
 	if (ud->quiet)
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 24/32] submodule--helper: don't exit() on failure, return
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (22 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 23/32] submodule--helper: use "code" in run_update_command() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 25/32] submodule--helper: libify determine_submodule_update_strategy() Ævar Arnfjörð Bjarmason
                     ` (8 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Change code downstream of module_update() to short-circuit and return
to the top-level on failure, rather than calling exit().

To do so we need to diligently check whether we "must_die_on_failure",
which is a pattern started in c51f8f94e5b (submodule--helper: run
update procedures from C, 2021-08-24), but which hadn't been completed
to the point where we could avoid calling exit() here.

This introduces no functional changes, but makes it easier to both
call these routines as a library in the future, and to eventually
avoid leaking memory.

This and similar control flow in submodule--helper.c could be made
simpler by properly "libifying" it, i.e. to have it consistently
return -1 on failures, and to early return on any non-success.

But let's leave that larger project for now, and (mostly) emulate what
were doing with the "exit(128)" before this change.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 44b08a01c54..84e5e3beeb5 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2125,7 +2125,8 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	return run_command(&cp);
 }
 
-static int run_update_command(struct update_data *ud, int subforce)
+static int run_update_command(struct update_data *ud, int subforce,
+			      int *must_die_on_failure)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
@@ -2189,7 +2190,7 @@ static int run_update_command(struct update_data *ud, int subforce)
 		}
 
 		if (ret == 128)
-			exit(ret);
+			*must_die_on_failure = 1;
 		return ret;
 	}
 
@@ -2221,7 +2222,8 @@ static int run_update_command(struct update_data *ud, int subforce)
 	return 0;
 }
 
-static int run_update_procedure(struct update_data *ud)
+static int run_update_procedure(struct update_data *ud,
+				int *must_die_on_failure)
 {
 	int subforce = is_null_oid(&ud->suboid) || ud->force;
 
@@ -2248,7 +2250,7 @@ static int run_update_procedure(struct update_data *ud)
 			    ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
-	return run_update_command(ud, subforce);
+	return run_update_command(ud, subforce, must_die_on_failure);
 }
 
 static const char *remote_submodule_branch(const char *path)
@@ -2384,7 +2386,8 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 				    "--no-single-branch");
 }
 
-static int update_submodule(struct update_data *update_data)
+static int update_submodule(struct update_data *update_data,
+			    int *must_die_on_failure)
 {
 	ensure_core_worktree(update_data->sm_path);
 
@@ -2420,9 +2423,15 @@ static int update_submodule(struct update_data *update_data)
 		free(remote_ref);
 	}
 
-	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force)
-		if (run_update_procedure(update_data))
+	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
+		int ret;
+
+		ret = run_update_procedure(update_data, must_die_on_failure);
+		if (*must_die_on_failure)
+			return ret;
+		if (ret)
 			return 1;
+	}
 
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
@@ -2438,14 +2447,13 @@ static int update_submodule(struct update_data *update_data)
 		prepare_submodule_repo_env(&cp.env);
 		update_data_to_args(&next, &cp.args);
 
-		/* die() if child process die()'d */
 		ret = run_command(&cp);
 		if (!ret)
 			return 0;
 		die_message(_("Failed to recurse into submodule path '%s'"),
 			    update_data->displaypath);
 		if (ret == 128)
-			exit(ret);
+			*must_die_on_failure = 1;
 		return ret;
 	}
 
@@ -2478,12 +2486,19 @@ static int update_submodules(struct update_data *update_data)
 
 	for (i = 0; i < suc.update_clone_nr; i++) {
 		struct update_clone_data ucd = suc.update_clone[i];
+		int must_die_on_failure = 0;
+		int code;
 
 		oidcpy(&update_data->oid, &ucd.oid);
 		update_data->just_cloned = ucd.just_cloned;
 		update_data->sm_path = ucd.sub->path;
 
-		if (update_submodule(update_data))
+		code = update_submodule(update_data, &must_die_on_failure);
+		if (code)
+			ret = code;
+		if (must_die_on_failure)
+			goto cleanup;
+		else if (code)
 			ret = 1;
 	}
 
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 25/32] submodule--helper: libify determine_submodule_update_strategy()
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (23 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 24/32] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 26/32] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
                     ` (7 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Libify the determine_submodule_update_strategy() by having it invoke
die_message() rather than die(), and returning the code die_message()
returns on failure.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 39 ++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 84e5e3beeb5..4d102f2b32e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1733,24 +1733,27 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static void determine_submodule_update_strategy(struct repository *r,
-						int just_cloned,
-						const char *path,
-						enum submodule_update_type update,
-						struct submodule_update_strategy *out)
+static int determine_submodule_update_strategy(struct repository *r,
+					       int just_cloned,
+					       const char *path,
+					       enum submodule_update_type update,
+					       struct submodule_update_strategy *out)
 {
 	const struct submodule *sub = submodule_from_path(r, null_oid(), path);
 	char *key;
 	const char *val;
+	int ret;
 
 	key = xstrfmt("submodule.%s.update", sub->name);
 
 	if (update) {
 		out->type = update;
 	} else if (!repo_config_get_string_tmp(r, key, &val)) {
-		if (parse_submodule_update_strategy(val, out) < 0)
-			die(_("Invalid update mode '%s' configured for submodule path '%s'"),
-				val, path);
+		if (parse_submodule_update_strategy(val, out) < 0) {
+			ret = die_message(_("Invalid update mode '%s' configured for submodule path '%s'"),
+					  val, path);
+			goto cleanup;
+		}
 	} else if (sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
 		if (sub->update_strategy.type == SM_UPDATE_COMMAND)
 			BUG("how did we read update = !command from .gitmodules?");
@@ -1765,7 +1768,10 @@ static void determine_submodule_update_strategy(struct repository *r,
 	     out->type == SM_UPDATE_NONE))
 		out->type = SM_UPDATE_CHECKOUT;
 
+	ret = 0;
+cleanup:
 	free(key);
+	return ret;
 }
 
 struct update_clone_data {
@@ -2389,14 +2395,22 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 static int update_submodule(struct update_data *update_data,
 			    int *must_die_on_failure)
 {
+	int ret;
+
 	ensure_core_worktree(update_data->sm_path);
 
 	update_data->displaypath = get_submodule_displaypath(
 		update_data->sm_path, update_data->prefix);
 
-	determine_submodule_update_strategy(the_repository, update_data->just_cloned,
-					    update_data->sm_path, update_data->update_default,
-					    &update_data->update_strategy);
+	ret = determine_submodule_update_strategy(the_repository,
+						  update_data->just_cloned,
+						  update_data->sm_path,
+						  update_data->update_default,
+						  &update_data->update_strategy);
+	if (ret) {
+		*must_die_on_failure = 1;
+		return ret;
+	}
 
 	if (update_data->just_cloned)
 		oidcpy(&update_data->suboid, null_oid());
@@ -2424,8 +2438,6 @@ static int update_submodule(struct update_data *update_data,
 	}
 
 	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
-		int ret;
-
 		ret = run_update_procedure(update_data, must_die_on_failure);
 		if (*must_die_on_failure)
 			return ret;
@@ -2436,7 +2448,6 @@ static int update_submodule(struct update_data *update_data,
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		struct update_data next = *update_data;
-		int ret;
 
 		next.prefix = NULL;
 		oidcpy(&next.oid, null_oid());
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 26/32] submodule--helper: libify "must_die_on_failure" code paths
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (24 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 25/32] submodule--helper: libify determine_submodule_update_strategy() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 27/32] submodule--helper update: don't override 'checkout' exit code Ævar Arnfjörð Bjarmason
                     ` (6 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

In preceding commits the codepaths around update_submodules() were
changed from using exit() or die() to ferrying up a
"must_die_on_failure" in the cases where we'd exit(), and in most
cases where we'd die().

We needed to do this this to ensure that we'd early exit or otherwise
abort the update_submodules() processing before it was completed.

Now that those preceding changes have shown that we've converted those
paths, we can remove the remaining "ret == 128" special-cases, leaving
the only such special-case in update_submodules(). I.e. we now know
after having gone through the various codepaths that we were only
returning 128 if we meant to early abort.

In update_submodules() we'll for now set any non-zero non-128 exit
codes to "1", but will start ferrying up the exit code as-is in a
subsequent commit.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 45 +++++++++++++------------------------
 1 file changed, 16 insertions(+), 29 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 4d102f2b32e..9e9d4fe0261 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2131,8 +2131,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	return run_command(&cp);
 }
 
-static int run_update_command(struct update_data *ud, int subforce,
-			      int *must_die_on_failure)
+static int run_update_command(struct update_data *ud, int subforce)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
@@ -2195,8 +2194,6 @@ static int run_update_command(struct update_data *ud, int subforce,
 			    ud->update_strategy.type);
 		}
 
-		if (ret == 128)
-			*must_die_on_failure = 1;
 		return ret;
 	}
 
@@ -2228,8 +2225,7 @@ static int run_update_command(struct update_data *ud, int subforce,
 	return 0;
 }
 
-static int run_update_procedure(struct update_data *ud,
-				int *must_die_on_failure)
+static int run_update_procedure(struct update_data *ud)
 {
 	int subforce = is_null_oid(&ud->suboid) || ud->force;
 
@@ -2256,7 +2252,7 @@ static int run_update_procedure(struct update_data *ud,
 			    ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
-	return run_update_command(ud, subforce, must_die_on_failure);
+	return run_update_command(ud, subforce);
 }
 
 static const char *remote_submodule_branch(const char *path)
@@ -2392,8 +2388,7 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 				    "--no-single-branch");
 }
 
-static int update_submodule(struct update_data *update_data,
-			    int *must_die_on_failure)
+static int update_submodule(struct update_data *update_data)
 {
 	int ret;
 
@@ -2407,10 +2402,8 @@ static int update_submodule(struct update_data *update_data,
 						  update_data->sm_path,
 						  update_data->update_default,
 						  &update_data->update_strategy);
-	if (ret) {
-		*must_die_on_failure = 1;
+	if (ret)
 		return ret;
-	}
 
 	if (update_data->just_cloned)
 		oidcpy(&update_data->suboid, null_oid());
@@ -2438,11 +2431,9 @@ static int update_submodule(struct update_data *update_data,
 	}
 
 	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
-		ret = run_update_procedure(update_data, must_die_on_failure);
-		if (*must_die_on_failure)
-			return ret;
+		ret = run_update_procedure(update_data);
 		if (ret)
-			return 1;
+			return ret;
 	}
 
 	if (update_data->recursive) {
@@ -2459,12 +2450,9 @@ static int update_submodule(struct update_data *update_data,
 		update_data_to_args(&next, &cp.args);
 
 		ret = run_command(&cp);
-		if (!ret)
-			return 0;
-		die_message(_("Failed to recurse into submodule path '%s'"),
-			    update_data->displaypath);
-		if (ret == 128)
-			*must_die_on_failure = 1;
+		if (ret)
+			die_message(_("Failed to recurse into submodule path '%s'"),
+				    update_data->displaypath);
 		return ret;
 	}
 
@@ -2497,20 +2485,19 @@ static int update_submodules(struct update_data *update_data)
 
 	for (i = 0; i < suc.update_clone_nr; i++) {
 		struct update_clone_data ucd = suc.update_clone[i];
-		int must_die_on_failure = 0;
 		int code;
 
 		oidcpy(&update_data->oid, &ucd.oid);
 		update_data->just_cloned = ucd.just_cloned;
 		update_data->sm_path = ucd.sub->path;
 
-		code = update_submodule(update_data, &must_die_on_failure);
-		if (code)
-			ret = code;
-		if (must_die_on_failure)
+		code = update_submodule(update_data);
+		if (!code)
+			continue;
+		ret = code;
+		if (ret == 128)
 			goto cleanup;
-		else if (code)
-			ret = 1;
+		ret = 1;
 	}
 
 cleanup:
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 27/32] submodule--helper update: don't override 'checkout' exit code
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (25 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 26/32] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-21 13:57   ` [PATCH v3 28/32] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
                     ` (5 subsequent siblings)
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

When "git submodule update" runs it might call "checkout", "merge",
"rebase", or a custom command. Ever since run_update_command() was
added in c51f8f94e5b (submodule--helper: run update procedures from C,
2021-08-24) we'd either exit immediately if the
"submodule.<name>.update" method failed, or in the case of "checkout"
continue trying to update other submodules.

This code used to use the magical "2" return code, but in
55b3f12cb54 (submodule update: use die_message(), 2022-03-15) it was
made to exit(128), which in preceding commits has been changed to
return that 128 code to the top-level.

Let's "libify" this code even more by not having it arbitrarily
override the return code. In practice this doesn't change anything as
the code "git checkout" would return on any normal failure is "1", but
we'll now in principle properly abort the operation if "git checkout"
were to exit with 128.

It would make sense to follow-up this change with a change to allow
the "submodule.<name>.update = !..." (SM_UPDATE_COMMAND) method the
same liberties as "checkout", and perhaps to do the same with a failed
"merge" or "rebase". But let's leave that for now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9e9d4fe0261..851000ae30e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2135,6 +2135,7 @@ static int run_update_command(struct update_data *ud, int subforce)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
+	int ret;
 
 	switch (ud->update_strategy.type) {
 	case SM_UPDATE_CHECKOUT:
@@ -2167,15 +2168,12 @@ static int run_update_command(struct update_data *ud, int subforce)
 
 	cp.dir = xstrdup(ud->sm_path);
 	prepare_submodule_repo_env(&cp.env);
-	if (run_command(&cp)) {
-		int ret;
-
+	if ((ret = run_command(&cp))) {
 		switch (ud->update_strategy.type) {
 		case SM_UPDATE_CHECKOUT:
 			die_message(_("Unable to checkout '%s' in submodule path '%s'"),
 				    oid, ud->displaypath);
-			/* the command failed, but update must continue */
-			ret = 1;
+			/* No "ret" assignment, use "git checkout"'s */
 			break;
 		case SM_UPDATE_REBASE:
 			ret = die_message(_("Unable to rebase '%s' in submodule path '%s'"),
@@ -2497,7 +2495,6 @@ static int update_submodules(struct update_data *update_data)
 		ret = code;
 		if (ret == 128)
 			goto cleanup;
-		ret = 1;
 	}
 
 cleanup:
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 28/32] submodule--helper: libify "must_die_on_failure" code paths (for die)
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (26 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 27/32] submodule--helper update: don't override 'checkout' exit code Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-23 23:27     ` Glen Choo
  2022-08-21 13:57   ` [PATCH v3 29/32] submodule--helper: check repo{_submodule,}_init() return values Ævar Arnfjörð Bjarmason
                     ` (4 subsequent siblings)
  32 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Continue the libification of codepaths that previously relied on
"must_die_on_failure". In these cases we've always been early aborting
by calling die(), but as we know that these codpaths will properly
handle return codes of 128 to mean an early abort let's have them use
die_message() instead.

This still isn't a complete migration away from die() for these
codepaths, in particular this code in update_submodule() will still call die() in some cases:

	char *remote_name = get_default_remote_submodule(update_data->sm_path);
	const char *branch = remote_submodule_branch(update_data->sm_path);

But as that code is used by other callers than the "update" code let's
leave converting it for a subsequent commit.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 851000ae30e..5f109d422ea 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2245,9 +2245,9 @@ static int run_update_procedure(struct update_data *ud)
 		 */
 		if (!is_tip_reachable(ud->sm_path, &ud->oid) &&
 		    fetch_in_submodule(ud->sm_path, ud->depth, ud->quiet, &ud->oid))
-			die(_("Fetched in submodule path '%s', but it did not "
-			      "contain %s. Direct fetching of that commit failed."),
-			    ud->displaypath, oid_to_hex(&ud->oid));
+			return die_message(_("Fetched in submodule path '%s', but it did not "
+					     "contain %s. Direct fetching of that commit failed."),
+					   ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
 	return run_update_command(ud, subforce);
@@ -2291,13 +2291,14 @@ static const char *remote_submodule_branch(const char *path)
 	return branch;
 }
 
-static void ensure_core_worktree(const char *path)
+static int ensure_core_worktree(const char *path)
 {
 	const char *cw;
 	struct repository subrepo;
 
 	if (repo_submodule_init(&subrepo, the_repository, path, null_oid()))
-		die(_("could not get a repository handle for submodule '%s'"), path);
+		return die_message(_("could not get a repository handle for submodule '%s'"),
+				   path);
 
 	if (!repo_config_get_string_tmp(&subrepo, "core.worktree", &cw)) {
 		char *cfg_file, *abs_path;
@@ -2315,6 +2316,8 @@ static void ensure_core_worktree(const char *path)
 		free(abs_path);
 		strbuf_release(&sb);
 	}
+
+	return 0;
 }
 
 static const char *submodule_update_type_to_label(enum submodule_update_type type)
@@ -2390,7 +2393,9 @@ static int update_submodule(struct update_data *update_data)
 {
 	int ret;
 
-	ensure_core_worktree(update_data->sm_path);
+	ret = ensure_core_worktree(update_data->sm_path);
+	if (ret)
+		return ret;
 
 	update_data->displaypath = get_submodule_displaypath(
 		update_data->sm_path, update_data->prefix);
@@ -2406,8 +2411,8 @@ static int update_submodule(struct update_data *update_data)
 	if (update_data->just_cloned)
 		oidcpy(&update_data->suboid, null_oid());
 	else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid))
-		die(_("Unable to find current revision in submodule path '%s'"),
-			update_data->displaypath);
+		return die_message(_("Unable to find current revision in submodule path '%s'"),
+				   update_data->displaypath);
 
 	if (update_data->remote) {
 		char *remote_name = get_default_remote_submodule(update_data->sm_path);
@@ -2417,13 +2422,13 @@ static int update_submodule(struct update_data *update_data)
 		if (!update_data->nofetch) {
 			if (fetch_in_submodule(update_data->sm_path, update_data->depth,
 					      0, NULL))
-				die(_("Unable to fetch in submodule path '%s'"),
-				    update_data->sm_path);
+				return die_message(_("Unable to fetch in submodule path '%s'"),
+						   update_data->sm_path);
 		}
 
 		if (resolve_gitlink_ref(update_data->sm_path, remote_ref, &update_data->oid))
-			die(_("Unable to find %s revision in submodule path '%s'"),
-			    remote_ref, update_data->sm_path);
+			return die_message(_("Unable to find %s revision in submodule path '%s'"),
+					   remote_ref, update_data->sm_path);
 
 		free(remote_ref);
 	}
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 29/32] submodule--helper: check repo{_submodule,}_init() return values
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (27 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 28/32] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-23 23:38     ` Glen Choo
  2022-08-21 13:57   ` [PATCH v3 30/32] submodule--helper: libify more "die" paths for module_update() Ævar Arnfjörð Bjarmason
                     ` (3 subsequent siblings)
  32 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Fix code added in ce125d431aa (submodule: extract path to submodule
gitdir func, 2021-09-15) and a77c3fcb5ec (submodule--helper: get
remote names from any repository, 2022-03-04) which failed to check
the return values of repo_init() and repo_submodule_init(). If we
failed to initialize the repository or submodule we could segfault
when trying to access the invalid repository structs.

Let's also check that these were the only such logic errors in the
codebase by making use of the "warn_unused_result" attribute. This is
valid as of GCC 3.4.0 (and clang will catch it via its faking of
__GNUC__ ).

As the comment being added to git-compat-util.h we're piggy-backing on
the LAST_ARG_MUST_BE_NULL version check out of lazyness. See
9fe3edc47f1 (Add the LAST_ARG_MUST_BE_NULL macro, 2013-07-18) for its
addition. The marginal benefit of covering gcc 3.4.0..4.0.0 is
near-zero (or zero) at this point. It mostly matters that we catch
this somewhere.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 9 +++++++--
 git-compat-util.h           | 3 +++
 repository.h                | 3 +++
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 5f109d422ea..88fc01320f3 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -63,7 +63,10 @@ static char *get_default_remote_submodule(const char *module_path)
 {
 	struct repository subrepo;
 
-	repo_submodule_init(&subrepo, the_repository, module_path, null_oid());
+	if (repo_submodule_init(&subrepo, the_repository, module_path,
+				null_oid()) < 0)
+		die(_("could not get a repository handle for submodule '%s'"),
+		    module_path);
 	return repo_get_default_remote(&subrepo);
 }
 
@@ -1483,7 +1486,9 @@ static int add_possible_reference_from_superproject(
 		struct strbuf err = STRBUF_INIT;
 		strbuf_add(&sb, odb->path, len);
 
-		repo_init(&alternate, sb.buf, NULL);
+		if (repo_init(&alternate, sb.buf, NULL) < 0)
+			die(_("could not get a repository handle for gitdir '%s'"),
+			    sb.buf);
 
 		/*
 		 * We need to end the new path with '/' to mark it as a dir,
diff --git a/git-compat-util.h b/git-compat-util.h
index 36a25ae252f..01d88650ba3 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -568,8 +568,11 @@ static inline int git_has_dir_sep(const char *path)
 /* The sentinel attribute is valid from gcc version 4.0 */
 #if defined(__GNUC__) && (__GNUC__ >= 4)
 #define LAST_ARG_MUST_BE_NULL __attribute__((sentinel))
+/* warn_unused_result exists as of gcc 3.4.0, but be lazy and check 4.0 */
+#define RESULT_MUST_BE_USED __attribute__ ((warn_unused_result))
 #else
 #define LAST_ARG_MUST_BE_NULL
+#define RESULT_MUST_BE_USED
 #endif
 
 #define MAYBE_UNUSED __attribute__((__unused__))
diff --git a/repository.h b/repository.h
index 797f471cce9..24316ac944e 100644
--- a/repository.h
+++ b/repository.h
@@ -1,6 +1,7 @@
 #ifndef REPOSITORY_H
 #define REPOSITORY_H
 
+#include "git-compat-util.h"
 #include "path.h"
 
 struct config_set;
@@ -186,6 +187,7 @@ void repo_set_gitdir(struct repository *repo, const char *root,
 void repo_set_worktree(struct repository *repo, const char *path);
 void repo_set_hash_algo(struct repository *repo, int algo);
 void initialize_the_repository(void);
+RESULT_MUST_BE_USED
 int repo_init(struct repository *r, const char *gitdir, const char *worktree);
 
 /*
@@ -197,6 +199,7 @@ int repo_init(struct repository *r, const char *gitdir, const char *worktree);
  * Return 0 upon success and a non-zero value upon failure.
  */
 struct object_id;
+RESULT_MUST_BE_USED
 int repo_submodule_init(struct repository *subrepo,
 			struct repository *superproject,
 			const char *path,
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 30/32] submodule--helper: libify more "die" paths for module_update()
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (28 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 29/32] submodule--helper: check repo{_submodule,}_init() return values Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-24  0:07     ` Glen Choo
  2022-08-21 13:57   ` [PATCH v3 31/32] submodule--helper: libify even " Ævar Arnfjörð Bjarmason
                     ` (2 subsequent siblings)
  32 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

As noted in a preceding commit the get_default_remote_submodule() and
remote_submodule_branch() functions would invoke die(), and thus leave
update_submodule() only partially lib-ified. Let's address the former
of those cases.

Change the functions to return an int exit code (non-zero on failure),
while leaving the get_default_remote() function for the callers that
still want the die() semantics.

This change addresses 1/2 of the "die" issue in these two lines in
update_submodule():

	char *remote_name = get_default_remote_submodule(update_data->sm_path);
	const char *branch = remote_submodule_branch(update_data->sm_path);

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 58 +++++++++++++++++++++++--------------
 1 file changed, 37 insertions(+), 21 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 88fc01320f3..9e4069b36cb 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -31,48 +31,57 @@
 typedef void (*each_submodule_fn)(const struct cache_entry *list_item,
 				  void *cb_data);
 
-static char *repo_get_default_remote(struct repository *repo)
+static int repo_get_default_remote(struct repository *repo, char **default_remote)
 {
-	char *dest = NULL, *ret;
+	char *dest = NULL;
 	struct strbuf sb = STRBUF_INIT;
 	struct ref_store *store = get_main_ref_store(repo);
 	const char *refname = refs_resolve_ref_unsafe(store, "HEAD", 0, NULL,
 						      NULL);
 
 	if (!refname)
-		die(_("No such ref: %s"), "HEAD");
+		return die_message(_("No such ref: %s"), "HEAD");
 
 	/* detached HEAD */
-	if (!strcmp(refname, "HEAD"))
-		return xstrdup("origin");
+	if (!strcmp(refname, "HEAD")) {
+		*default_remote = xstrdup("origin");
+		return 0;
+	}
 
 	if (!skip_prefix(refname, "refs/heads/", &refname))
-		die(_("Expecting a full ref name, got %s"), refname);
+		return die_message(_("Expecting a full ref name, got %s"),
+				   refname);
 
 	strbuf_addf(&sb, "branch.%s.remote", refname);
 	if (repo_config_get_string(repo, sb.buf, &dest))
-		ret = xstrdup("origin");
+		*default_remote = xstrdup("origin");
 	else
-		ret = dest;
+		*default_remote = dest;
 
 	strbuf_release(&sb);
-	return ret;
+	return 0;
 }
 
-static char *get_default_remote_submodule(const char *module_path)
+static int get_default_remote_submodule(const char *module_path, char **default_remote)
 {
 	struct repository subrepo;
 
 	if (repo_submodule_init(&subrepo, the_repository, module_path,
 				null_oid()) < 0)
-		die(_("could not get a repository handle for submodule '%s'"),
-		    module_path);
-	return repo_get_default_remote(&subrepo);
+		return die_message(_("could not get a repository handle for submodule '%s'"),
+				   module_path);
+	return repo_get_default_remote(&subrepo, default_remote);
 }
 
 static char *get_default_remote(void)
 {
-	return repo_get_default_remote(the_repository);
+	char *default_remote;
+	int code = repo_get_default_remote(the_repository, &default_remote);
+
+	if (code)
+		exit(code);
+
+	return default_remote;
 }
 
 static char *resolve_relative_url(const char *rel_url, const char *up_path, int quiet)
@@ -1159,6 +1168,7 @@ static void sync_submodule(const char *path, const char *prefix,
 	char *sub_origin_url, *super_config_url, *displaypath, *default_remote;
 	struct strbuf sb = STRBUF_INIT;
 	char *sub_config_path = NULL;
+	int code;
 
 	if (!is_submodule_active(the_repository, path))
 		return;
@@ -1198,10 +1208,9 @@ static void sync_submodule(const char *path, const char *prefix,
 		goto cleanup;
 
 	strbuf_reset(&sb);
-	default_remote = get_default_remote_submodule(path);
-	if (!default_remote)
-		die(_("failed to get the default remote for submodule '%s'"),
-		      path);
+	code = get_default_remote_submodule(path, &default_remote);
+	if (code)
+		exit(code);
 
 	remote_key = xstrfmt("remote.%s.url", default_remote);
 	free(default_remote);
@@ -2420,9 +2429,16 @@ static int update_submodule(struct update_data *update_data)
 				   update_data->displaypath);
 
 	if (update_data->remote) {
-		char *remote_name = get_default_remote_submodule(update_data->sm_path);
-		const char *branch = remote_submodule_branch(update_data->sm_path);
-		char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+		char *remote_name;
+		const char *branch;
+		char *remote_ref;
+		int code;
+
+		code = get_default_remote_submodule(update_data->sm_path, &remote_name);
+		if (code)
+			return code;
+		branch = remote_submodule_branch(update_data->sm_path);
+		remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
 
 		if (!update_data->nofetch) {
 			if (fetch_in_submodule(update_data->sm_path, update_data->depth,
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 31/32] submodule--helper: libify even more "die" paths for module_update()
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (29 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 30/32] submodule--helper: libify more "die" paths for module_update() Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-24  0:12     ` Glen Choo
  2022-08-21 13:57   ` [PATCH v3 32/32] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  32 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

As noted in a preceding commit the get_default_remote_submodule() and
remote_submodule_branch() functions would invoke die(), and thus leave
update_submodule() only partially lib-ified. We've addressed the
former of those in a preceding commit, let's now address the latter.

In addition to lib-ifying the function this fixes a potential (but
obscure) segfault introduced by a logic error in
1012a5cbc3f (submodule--helper run-update-procedure: learn --remote,
2022-03-04):

We were assuming that remote_submodule_branch() would always return
on-NULL, but if the submodule_from_path() call in that function fails
we'll return NULL. See its introduction in
92bbe7ccf1f (submodule--helper: add remote-branch helper, 2016-08-03).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 41 ++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9e4069b36cb..65909255760 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2267,42 +2267,49 @@ static int run_update_procedure(struct update_data *ud)
 	return run_update_command(ud, subforce);
 }
 
-static const char *remote_submodule_branch(const char *path)
+static int remote_submodule_branch(const char *path, const char **branch)
 {
 	const struct submodule *sub;
-	const char *branch = NULL;
 	char *key;
+	*branch = NULL;
 
 	sub = submodule_from_path(the_repository, null_oid(), path);
 	if (!sub)
-		return NULL;
+		return die_message(_("could not initialize submodule at path '%s'"),
+				   path);
 
 	key = xstrfmt("submodule.%s.branch", sub->name);
-	if (repo_config_get_string_tmp(the_repository, key, &branch))
-		branch = sub->branch;
+	if (repo_config_get_string_tmp(the_repository, key, branch))
+		*branch = sub->branch;
 	free(key);
 
-	if (!branch)
-		return "HEAD";
+	if (!*branch) {
+		*branch = "HEAD";
+		return 0;
+	}
 
-	if (!strcmp(branch, ".")) {
+	if (!strcmp(*branch, ".")) {
 		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
 
 		if (!refname)
-			die(_("No such ref: %s"), "HEAD");
+			return die_message(_("No such ref: %s"), "HEAD");
 
 		/* detached HEAD */
 		if (!strcmp(refname, "HEAD"))
-			die(_("Submodule (%s) branch configured to inherit "
-			      "branch from superproject, but the superproject "
-			      "is not on any branch"), sub->name);
+			return die_message(_("Submodule (%s) branch configured to inherit "
+					     "branch from superproject, but the superproject "
+					     "is not on any branch"), sub->name);
 
 		if (!skip_prefix(refname, "refs/heads/", &refname))
-			die(_("Expecting a full ref name, got %s"), refname);
-		return refname;
+			return die_message(_("Expecting a full ref name, got %s"),
+					   refname);
+
+		*branch = refname;
+		return 0;
 	}
 
-	return branch;
+	/* Our "branch" is coming from repo_config_get_string_tmp() */
+	return 0;
 }
 
 static int ensure_core_worktree(const char *path)
@@ -2437,7 +2444,9 @@ static int update_submodule(struct update_data *update_data)
 		code = get_default_remote_submodule(update_data->sm_path, &remote_name);
 		if (code)
 			return code;
-		branch = remote_submodule_branch(update_data->sm_path);
+		code = remote_submodule_branch(update_data->sm_path, &branch);
+		if (code)
+			return code;
 		remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
 
 		if (!update_data->nofetch) {
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v3 32/32] submodule--helper: fix bad config API usage
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (30 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 31/32] submodule--helper: libify even " Ævar Arnfjörð Bjarmason
@ 2022-08-21 13:57   ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  32 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-21 13:57 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Fix bad config API usage added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06). After
git_config_get_string() returns successfully we know the "char **dest"
will be non-NULL.

A coccinelle patch that transforms this turns up a couple of other
such issues, one in fetch-pack.c, and another in upload-pack.c:

	@@
	identifier F =~ "^(repo|git)_config_get_string(_tmp)?$";
	identifier V;
	@@
	  !F(..., &V)
	- && (V)

But let's focus narrowly on submodule--helper for now, we can fix
those some other time.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 65909255760..e489a0f6b10 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3108,7 +3108,7 @@ static void configure_added_submodule(struct add_data *add_data)
 	 * is_submodule_active(), since that function needs to find
 	 * out the value of "submodule.active" again anyway.
 	 */
-	if (!git_config_get_string("submodule.active", &val) && val) {
+	if (!git_config_get_string("submodule.active", &val)) {
 		/*
 		 * If the submodule being added isn't already covered by the
 		 * current configured pathspec, set the submodule's active flag
-- 
2.37.2.1279.g64dec4e13cf


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* Re: [PATCH v3 17/32] submodule--helper: don't redundantly check "else if (res)"
  2022-08-21 13:57   ` [PATCH v3 17/32] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
@ 2022-08-21 16:12     ` Eric Sunshine
  0 siblings, 0 replies; 142+ messages in thread
From: Eric Sunshine @ 2022-08-21 16:12 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Git List, Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan

On Sun, Aug 21, 2022 at 10:00 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
> The "res" variable must be true at this point in update_submodule(),
> as just a few lines above this we've unconditionally:
>
>         if (!res)
>                 return 0;
>
> So we don't need to guard the "return 1" with an "else if (res)", we
> an return unconditionally at this point. See b3c5f5cb048 (submodule:

s/an/can/

> move core cmd_update() logic to C, 2022-03-15) for the initial
> introduction of this code, this check of "res" has always been
> redundant.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v3 01/32] submodule tests: test usage behavior
  2022-08-21 13:57   ` [PATCH v3 01/32] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
@ 2022-08-23 22:42     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-23 22:42 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Test what exit code and output we emit on "git submodule -h", how we
> handle "--" when no subcommand is specified, and how the top-level
> "--recursive" option is handled.
>
> For "-h" this doesn't make sense, but let's test for it so that any
> subsequent eventual behavior change will become clear.
>
> For "--" this follows up on 68cabbfda36 (submodule: document default
> behavior, 2019-02-15) and tests that "status" doesn't support
> the "--" delimiter. There's no intrinsically good reason not to
> support that. We behave this way due to edge cases in
> git-submodule.sh's implementation, but as with "-h" let's assert our
> current long-standing behavior for now.
>
> For "--recursive" the exclusion of it from the top-level appears to
> have been an omission in 15fc56a8536 (git submodule foreach: Add
> --recursive to recurse into nested submodules, 2009-08-19), there
> doesn't seem to be a reason not to support it alongside "--quiet" and
> "--cached", but let's likewise assert our existing behavior for now.
>
> I.e. as long as "status" is optional it would make sense to support
> all of its options when it's omitted, but we only do that with
> "--quiet" and "--cached", and curiously omit "--recursive".

Ah! Okay, this finally makes sense to me now. The usage strings in
Documentation/git-submodule.txt and git-submodule.sh document both
"--quiet" and "--cached", but that's bogus because we should either:

- pretend that "git submodule" doesn't default to "status", so we
  should omit "--cached", or
- be clearer that "git submodule" _does_ default to "status", so we
  should include "--recursive"

Now that we've acknowledged the existence of top-level "--recursive", we
should probably amend the usage strings. To be honest, I think a less
confusing, more consistent direction would be to just drop this "default
to status" behavior but I doubt we can do that any time soon..

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  t/t7400-submodule-basic.sh | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
>
> diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
> index e7cec2e457a..b858871a953 100755
> --- a/t/t7400-submodule-basic.sh
> +++ b/t/t7400-submodule-basic.sh
> @@ -14,6 +14,32 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>  
>  . ./test-lib.sh
>  
> +test_expect_success 'submodule usage: -h' '
> +	git submodule -h >out 2>err &&
> +	grep "^usage: git submodule" out &&
> +	test_must_be_empty err
> +'
> +
> +test_expect_success 'submodule usage: --recursive' '
> +	test_expect_code 1 git submodule --recursive >out 2>err &&
> +	grep "^usage: git submodule" err &&
> +	test_must_be_empty out
> +'
> +
> +test_expect_success 'submodule usage: status --' '
> +	test_expect_code 1 git submodule -- &&
> +	test_expect_code 1 git submodule --end-of-options
> +'
> +
> +for opt in '--quiet' '--cached'
> +do
> +	test_expect_success "submodule usage: status $opt" '
> +		git submodule $opt &&
> +		git submodule status $opt &&
> +		git submodule $opt status
> +	'
> +done
> +
>  test_expect_success 'submodule deinit works on empty repository' '
>  	git submodule deinit --all
>  '
> -- 
> 2.37.2.1279.g64dec4e13cf

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v3 28/32] submodule--helper: libify "must_die_on_failure" code paths (for die)
  2022-08-21 13:57   ` [PATCH v3 28/32] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
@ 2022-08-23 23:27     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-23 23:27 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Continue the libification of codepaths that previously relied on
> "must_die_on_failure". In these cases we've always been early aborting
> by calling die(), but as we know that these codpaths will properly

s/codpaths/codepaths :p

> handle return codes of 128 to mean an early abort let's have them use
> die_message() instead.
>
> This still isn't a complete migration away from die() for these
> codepaths, in particular this code in update_submodule() will still call die() in some cases:
>
> 	char *remote_name = get_default_remote_submodule(update_data->sm_path);
> 	const char *branch = remote_submodule_branch(update_data->sm_path);
>
> But as that code is used by other callers than the "update" code let's
> leave converting it for a subsequent commit.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 29 +++++++++++++++++------------
>  1 file changed, 17 insertions(+), 12 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 851000ae30e..5f109d422ea 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2245,9 +2245,9 @@ static int run_update_procedure(struct update_data *ud)
>  		 */
>  		if (!is_tip_reachable(ud->sm_path, &ud->oid) &&
>  		    fetch_in_submodule(ud->sm_path, ud->depth, ud->quiet, &ud->oid))
> -			die(_("Fetched in submodule path '%s', but it did not "
> -			      "contain %s. Direct fetching of that commit failed."),
> -			    ud->displaypath, oid_to_hex(&ud->oid));
> +			return die_message(_("Fetched in submodule path '%s', but it did not "
> +					     "contain %s. Direct fetching of that commit failed."),
> +					   ud->displaypath, oid_to_hex(&ud->oid));
>  	}
>  
>  	return run_update_command(ud, subforce);
> @@ -2291,13 +2291,14 @@ static const char *remote_submodule_branch(const char *path)
>  	return branch;
>  }
>  
> -static void ensure_core_worktree(const char *path)
> +static int ensure_core_worktree(const char *path)
>  {
>  	const char *cw;
>  	struct repository subrepo;
>  
>  	if (repo_submodule_init(&subrepo, the_repository, path, null_oid()))
> -		die(_("could not get a repository handle for submodule '%s'"), path);
> +		return die_message(_("could not get a repository handle for submodule '%s'"),
> +				   path);
>  
>  	if (!repo_config_get_string_tmp(&subrepo, "core.worktree", &cw)) {
>  		char *cfg_file, *abs_path;
> @@ -2315,6 +2316,8 @@ static void ensure_core_worktree(const char *path)
>  		free(abs_path);
>  		strbuf_release(&sb);
>  	}
> +
> +	return 0;
>  }
>  
>  static const char *submodule_update_type_to_label(enum submodule_update_type type)
> @@ -2390,7 +2393,9 @@ static int update_submodule(struct update_data *update_data)
>  {
>  	int ret;
>  
> -	ensure_core_worktree(update_data->sm_path);
> +	ret = ensure_core_worktree(update_data->sm_path);
> +	if (ret)
> +		return ret;
>  
>  	update_data->displaypath = get_submodule_displaypath(
>  		update_data->sm_path, update_data->prefix);
> @@ -2406,8 +2411,8 @@ static int update_submodule(struct update_data *update_data)
>  	if (update_data->just_cloned)
>  		oidcpy(&update_data->suboid, null_oid());
>  	else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid))
> -		die(_("Unable to find current revision in submodule path '%s'"),
> -			update_data->displaypath);
> +		return die_message(_("Unable to find current revision in submodule path '%s'"),
> +				   update_data->displaypath);
>  
>  	if (update_data->remote) {
>  		char *remote_name = get_default_remote_submodule(update_data->sm_path);
> @@ -2417,13 +2422,13 @@ static int update_submodule(struct update_data *update_data)
>  		if (!update_data->nofetch) {
>  			if (fetch_in_submodule(update_data->sm_path, update_data->depth,
>  					      0, NULL))
> -				die(_("Unable to fetch in submodule path '%s'"),
> -				    update_data->sm_path);
> +				return die_message(_("Unable to fetch in submodule path '%s'"),
> +						   update_data->sm_path);
>  		}
>  
>  		if (resolve_gitlink_ref(update_data->sm_path, remote_ref, &update_data->oid))
> -			die(_("Unable to find %s revision in submodule path '%s'"),
> -			    remote_ref, update_data->sm_path);
> +			return die_message(_("Unable to find %s revision in submodule path '%s'"),
> +					   remote_ref, update_data->sm_path);
>  
>  		free(remote_ref);
>  	}
> -- 
> 2.37.2.1279.g64dec4e13cf

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v3 29/32] submodule--helper: check repo{_submodule,}_init() return values
  2022-08-21 13:57   ` [PATCH v3 29/32] submodule--helper: check repo{_submodule,}_init() return values Ævar Arnfjörð Bjarmason
@ 2022-08-23 23:38     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-23 23:38 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> Fix code added in ce125d431aa (submodule: extract path to submodule
> gitdir func, 2021-09-15) and a77c3fcb5ec (submodule--helper: get
> remote names from any repository, 2022-03-04) which failed to check
> the return values of repo_init() and repo_submodule_init(). If we
> failed to initialize the repository or submodule we could segfault
> when trying to access the invalid repository structs.

Yes, this sounds correct. repo_init() and repo_submodule_init() are pure
initialization and have no intended side effects, so there's no reason
to not check the return value.

>
> Let's also check that these were the only such logic errors in the
> codebase by making use of the "warn_unused_result" attribute. This is
> valid as of GCC 3.4.0 (and clang will catch it via its faking of
> __GNUC__ ).
>
> As the comment being added to git-compat-util.h we're piggy-backing on
> the LAST_ARG_MUST_BE_NULL version check out of lazyness. See
> 9fe3edc47f1 (Add the LAST_ARG_MUST_BE_NULL macro, 2013-07-18) for its
> addition. The marginal benefit of covering gcc 3.4.0..4.0.0 is
> near-zero (or zero) at this point. It mostly matters that we catch
> this somewhere.

I'm not familiar enough with attributes and the requistie compiler
versions, so I won't comment on this bit.

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 9 +++++++--
>  git-compat-util.h           | 3 +++
>  repository.h                | 3 +++
>  3 files changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 5f109d422ea..88fc01320f3 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -63,7 +63,10 @@ static char *get_default_remote_submodule(const char *module_path)
>  {
>  	struct repository subrepo;
>  
> -	repo_submodule_init(&subrepo, the_repository, module_path, null_oid());
> +	if (repo_submodule_init(&subrepo, the_repository, module_path,
> +				null_oid()) < 0)
> +		die(_("could not get a repository handle for submodule '%s'"),
> +		    module_path);
>  	return repo_get_default_remote(&subrepo);
>  }
>  
> @@ -1483,7 +1486,9 @@ static int add_possible_reference_from_superproject(
>  		struct strbuf err = STRBUF_INIT;
>  		strbuf_add(&sb, odb->path, len);
>  
> -		repo_init(&alternate, sb.buf, NULL);
> +		if (repo_init(&alternate, sb.buf, NULL) < 0)
> +			die(_("could not get a repository handle for gitdir '%s'"),
> +			    sb.buf);
>  
>  		/*
>  		 * We need to end the new path with '/' to mark it as a dir,
> diff --git a/git-compat-util.h b/git-compat-util.h
> index 36a25ae252f..01d88650ba3 100644
> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -568,8 +568,11 @@ static inline int git_has_dir_sep(const char *path)
>  /* The sentinel attribute is valid from gcc version 4.0 */
>  #if defined(__GNUC__) && (__GNUC__ >= 4)
>  #define LAST_ARG_MUST_BE_NULL __attribute__((sentinel))
> +/* warn_unused_result exists as of gcc 3.4.0, but be lazy and check 4.0 */
> +#define RESULT_MUST_BE_USED __attribute__ ((warn_unused_result))
>  #else
>  #define LAST_ARG_MUST_BE_NULL
> +#define RESULT_MUST_BE_USED
>  #endif
>  
>  #define MAYBE_UNUSED __attribute__((__unused__))
> diff --git a/repository.h b/repository.h
> index 797f471cce9..24316ac944e 100644
> --- a/repository.h
> +++ b/repository.h
> @@ -1,6 +1,7 @@
>  #ifndef REPOSITORY_H
>  #define REPOSITORY_H
>  
> +#include "git-compat-util.h"
>  #include "path.h"
>  
>  struct config_set;
> @@ -186,6 +187,7 @@ void repo_set_gitdir(struct repository *repo, const char *root,
>  void repo_set_worktree(struct repository *repo, const char *path);
>  void repo_set_hash_algo(struct repository *repo, int algo);
>  void initialize_the_repository(void);
> +RESULT_MUST_BE_USED
>  int repo_init(struct repository *r, const char *gitdir, const char *worktree);
>  
>  /*
> @@ -197,6 +199,7 @@ int repo_init(struct repository *r, const char *gitdir, const char *worktree);
>   * Return 0 upon success and a non-zero value upon failure.
>   */
>  struct object_id;
> +RESULT_MUST_BE_USED
>  int repo_submodule_init(struct repository *subrepo,
>  			struct repository *superproject,
>  			const char *path,
> -- 
> 2.37.2.1279.g64dec4e13cf

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v3 30/32] submodule--helper: libify more "die" paths for module_update()
  2022-08-21 13:57   ` [PATCH v3 30/32] submodule--helper: libify more "die" paths for module_update() Ævar Arnfjörð Bjarmason
@ 2022-08-24  0:07     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-24  0:07 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> As noted in a preceding commit the get_default_remote_submodule() and
> remote_submodule_branch() functions would invoke die(), and thus leave
> update_submodule() only partially lib-ified. Let's address the former
> of those cases.
>
> Change the functions to return an int exit code (non-zero on failure),
> while leaving the get_default_remote() function for the callers that
> still want the die() semantics.
>
> This change addresses 1/2 of the "die" issue in these two lines in
> update_submodule():
>
> 	char *remote_name = get_default_remote_submodule(update_data->sm_path);
> 	const char *branch = remote_submodule_branch(update_data->sm_path);
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 58 +++++++++++++++++++++++--------------
>  1 file changed, 37 insertions(+), 21 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 88fc01320f3..9e4069b36cb 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -31,48 +31,57 @@
>  typedef void (*each_submodule_fn)(const struct cache_entry *list_item,
>  				  void *cb_data);
>  
> -static char *repo_get_default_remote(struct repository *repo)
> +static int repo_get_default_remote(struct repository *repo, char **default_remote)
>  {
> -	char *dest = NULL, *ret;
> +	char *dest = NULL;
>  	struct strbuf sb = STRBUF_INIT;
>  	struct ref_store *store = get_main_ref_store(repo);
>  	const char *refname = refs_resolve_ref_unsafe(store, "HEAD", 0, NULL,
>  						      NULL);
>  
>  	if (!refname)
> -		die(_("No such ref: %s"), "HEAD");
> +		return die_message(_("No such ref: %s"), "HEAD");
>  
>  	/* detached HEAD */
> -	if (!strcmp(refname, "HEAD"))
> -		return xstrdup("origin");
> +	if (!strcmp(refname, "HEAD")) {
> +		*default_remote = xstrdup("origin");
> +		return 0;
> +	}
>  
>  	if (!skip_prefix(refname, "refs/heads/", &refname))
> -		die(_("Expecting a full ref name, got %s"), refname);
> +		return die_message(_("Expecting a full ref name, got %s"),
> +				   refname);
>  
>  	strbuf_addf(&sb, "branch.%s.remote", refname);
>  	if (repo_config_get_string(repo, sb.buf, &dest))
> -		ret = xstrdup("origin");
> +		*default_remote = xstrdup("origin");
>  	else
> -		ret = dest;
> +		*default_remote = dest;
>  
>  	strbuf_release(&sb);
> -	return ret;
> +	return 0;
>  }

If we fail to look up the default remote for the branch, we assume it is
"origin", otherwise, it is the default remote. So in the preimage this
function would never return NULL, right? This matters in
sync_submodule()..

>  
> -static char *get_default_remote_submodule(const char *module_path)
> +static int get_default_remote_submodule(const char *module_path, char **default_remote)
>  {
>  	struct repository subrepo;
>  
>  	if (repo_submodule_init(&subrepo, the_repository, module_path,
>  				null_oid()) < 0)
> -		die(_("could not get a repository handle for submodule '%s'"),
> -		    module_path);
> -	return repo_get_default_remote(&subrepo);
> +		return die_message(_("could not get a repository handle for submodule '%s'"),
> +				   module_path);
> +	return repo_get_default_remote(&subrepo, default_remote);
>  }
>  
>  static char *get_default_remote(void)
>  {
> -	return repo_get_default_remote(the_repository);
> +	char *default_remote;
> +	int code = repo_get_default_remote(the_repository, &default_remote);
> +
> +	if (code)
> +		exit(code);
> +
> +	return default_remote;
>  }

repo_* usually denotes a difference between "the_repository" and "struct
repository", so I don't really like having [repo_]get_default_remote()
die/return differently. But it makes some sense to special case
"the_repository" since it is the top level, so if it fails, something is
very wrong. So on the whole, I'm ok with doing this to avoid disrupting
other callers.

> @@ -1159,6 +1168,7 @@ static void sync_submodule(const char *path, const char *prefix,
>  	char *sub_origin_url, *super_config_url, *displaypath, *default_remote;
>  	struct strbuf sb = STRBUF_INIT;
>  	char *sub_config_path = NULL;
> +	int code;
>  
>  	if (!is_submodule_active(the_repository, path))
>  		return;
> @@ -1198,10 +1208,9 @@ static void sync_submodule(const char *path, const char *prefix,
>  		goto cleanup;
>  
>  	strbuf_reset(&sb);
> -	default_remote = get_default_remote_submodule(path);
> -	if (!default_remote)
> -		die(_("failed to get the default remote for submodule '%s'"),
> -		      path);
> +	code = get_default_remote_submodule(path, &default_remote);
> +	if (code)
> +		exit(code);

In the preimage, we used to check that default_remote is not NULL, but
we don't check this any more. As we noted earlier, default_remote could
never be NULL (because we used to die() on failure), so I think we never
needed this check and it's ok to drop it.

Is this the same reasoning you had?


^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v3 31/32] submodule--helper: libify even more "die" paths for module_update()
  2022-08-21 13:57   ` [PATCH v3 31/32] submodule--helper: libify even " Ævar Arnfjörð Bjarmason
@ 2022-08-24  0:12     ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-08-24  0:12 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> As noted in a preceding commit the get_default_remote_submodule() and
> remote_submodule_branch() functions would invoke die(), and thus leave
> update_submodule() only partially lib-ified. We've addressed the
> former of those in a preceding commit, let's now address the latter.
>
> In addition to lib-ifying the function this fixes a potential (but
> obscure) segfault introduced by a logic error in
> 1012a5cbc3f (submodule--helper run-update-procedure: learn --remote,
> 2022-03-04):

Ah, good catch.

>
> We were assuming that remote_submodule_branch() would always return
> on-NULL, but if the submodule_from_path() call in that function fails

s/on-NULL/non-NULL I assume?

> we'll return NULL. See its introduction in
> 92bbe7ccf1f (submodule--helper: add remote-branch helper, 2016-08-03).
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 41 ++++++++++++++++++++++---------------
>  1 file changed, 25 insertions(+), 16 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index 9e4069b36cb..65909255760 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -2267,42 +2267,49 @@ static int run_update_procedure(struct update_data *ud)
>  	return run_update_command(ud, subforce);
>  }
>  
> -static const char *remote_submodule_branch(const char *path)
> +static int remote_submodule_branch(const char *path, const char **branch)
>  {
>  	const struct submodule *sub;
> -	const char *branch = NULL;
>  	char *key;
> +	*branch = NULL;
>  
>  	sub = submodule_from_path(the_repository, null_oid(), path);
>  	if (!sub)
> -		return NULL;
> +		return die_message(_("could not initialize submodule at path '%s'"),
> +				   path);
>  
>  	key = xstrfmt("submodule.%s.branch", sub->name);
> -	if (repo_config_get_string_tmp(the_repository, key, &branch))
> -		branch = sub->branch;
> +	if (repo_config_get_string_tmp(the_repository, key, branch))
> +		*branch = sub->branch;
>  	free(key);
>  
> -	if (!branch)
> -		return "HEAD";
> +	if (!*branch) {
> +		*branch = "HEAD";
> +		return 0;
> +	}
>  
> -	if (!strcmp(branch, ".")) {
> +	if (!strcmp(*branch, ".")) {
>  		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
>  
>  		if (!refname)
> -			die(_("No such ref: %s"), "HEAD");
> +			return die_message(_("No such ref: %s"), "HEAD");
>  
>  		/* detached HEAD */
>  		if (!strcmp(refname, "HEAD"))
> -			die(_("Submodule (%s) branch configured to inherit "
> -			      "branch from superproject, but the superproject "
> -			      "is not on any branch"), sub->name);
> +			return die_message(_("Submodule (%s) branch configured to inherit "
> +					     "branch from superproject, but the superproject "
> +					     "is not on any branch"), sub->name);
>  
>  		if (!skip_prefix(refname, "refs/heads/", &refname))
> -			die(_("Expecting a full ref name, got %s"), refname);
> -		return refname;
> +			return die_message(_("Expecting a full ref name, got %s"),
> +					   refname);
> +
> +		*branch = refname;
> +		return 0;
>  	}
>  
> -	return branch;
> +	/* Our "branch" is coming from repo_config_get_string_tmp() */
> +	return 0;
>  }
>  
>  static int ensure_core_worktree(const char *path)
> @@ -2437,7 +2444,9 @@ static int update_submodule(struct update_data *update_data)
>  		code = get_default_remote_submodule(update_data->sm_path, &remote_name);
>  		if (code)
>  			return code;
> -		branch = remote_submodule_branch(update_data->sm_path);
> +		code = remote_submodule_branch(update_data->sm_path, &branch);
> +		if (code)
> +			return code;
>  		remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
This line is the one that would segfault, I assume?

Looks good.
>  
>  		if (!update_data->nofetch) {
> -- 
> 2.37.2.1279.g64dec4e13cf

^ permalink raw reply	[flat|nested] 142+ messages in thread

* [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep
  2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                     ` (31 preceding siblings ...)
  2022-08-21 13:57   ` [PATCH v3 32/32] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17   ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 01/33] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
                       ` (33 more replies)
  32 siblings, 34 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

This series is a "prep" series for the meaty leak fixes for
submodule--helper, see [1] (which will be re-rolled on top of this
v3). The v7 re-roll will be at [2].

Changes since v3:

 * Addressed (hopefully) all of the small feedback, just typo fixes &
   commit message clarifications.

 * Marked a parameter as "const", which helps reason about subsequent
   things in the "leak" series.

Hopefully this is ready to proceed past "seen" in its current form...

1. https://lore.kernel.org/git/cover-v3-00.32-00000000000-20220821T130231Z-avarab@gmail.com/
2. https://lore.kernel.org/git/cover-v7-00.17-00000000000-20220831T231003Z-avarab@gmail.com

This series & passing CI can be seen at:
https://github.com/avar/git/tree/avar/submodule--helper-cleanup-and-tests-4

Glen Choo (2):
  submodule--helper: add "const" to copy of "update_data"
  submodule--helper: refactor "errmsg_str" to be a "struct strbuf"

Ævar Arnfjörð Bjarmason (31):
  submodule tests: test usage behavior
  submodule tests: test for "add <repository> <abs-path>"
  submodule--helper: remove unused "name" helper
  submodule--helper: remove unused "list" helper
  test-tool submodule-config: remove unused "--url" handling
  submodule--helper: move "is-active" to a test-tool
  submodule--helper: move "check-name" to a test-tool
  submodule--helper: move "resolve-relative-url-test" to a test-tool
  submodule--helper style: don't separate declared variables with \n\n
  submodule--helper style: add \n\n after variable declarations
  submodule--helper: replace memset() with { 0 }-initialization
  submodule--helper: use xstrfmt() in clone_submodule()
  submodule--helper: move "sb" in clone_submodule() to its own scope
  submodule--helper: add "const" to passed "module_clone_data"
  submodule--helper: add "const" to passed "struct update_data"
  submodule--helper: don't redundantly check "else if (res)"
  submodule--helper: rename "int res" to "int ret"
  submodule--helper: return "ret", not "1" from update_submodule()
  submodule--helper: add missing braces to "else" arm
  submodule--helper: don't call submodule_strategy_to_string() in BUG()
  submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string()
  submodule--helper: use "code" in run_update_command()
  submodule--helper: don't exit() on failure, return
  submodule--helper: libify determine_submodule_update_strategy()
  submodule--helper: libify "must_die_on_failure" code paths
  submodule--helper update: don't override 'checkout' exit code
  submodule--helper: libify "must_die_on_failure" code paths (for die)
  submodule--helper: check repo{_submodule,}_init() return values
  submodule--helper: libify more "die" paths for module_update()
  submodule--helper: libify even more "die" paths for module_update()
  submodule--helper: fix bad config API usage

 Makefile                         |   1 +
 builtin/submodule--helper.c      | 546 ++++++++++++++-----------------
 git-compat-util.h                |   3 +
 repository.h                     |   3 +
 submodule.c                      |  12 +-
 submodule.h                      |   2 +-
 t/helper/test-submodule-config.c |  11 +-
 t/helper/test-submodule.c        | 146 +++++++++
 t/helper/test-tool-utils.h       |   9 +
 t/helper/test-tool.c             |   7 +-
 t/helper/test-tool.h             |   1 +
 t/t0060-path-utils.sh            |   2 +-
 t/t7400-submodule-basic.sh       |  56 ++--
 t/t7406-submodule-update.sh      |   2 +-
 t/t7413-submodule-is-active.sh   |  35 +-
 t/t7450-bad-git-dotfiles.sh      |   2 +-
 16 files changed, 467 insertions(+), 371 deletions(-)
 create mode 100644 t/helper/test-submodule.c
 create mode 100644 t/helper/test-tool-utils.h

Range-diff against v3:
 1:  77586985ab3 =  1:  2e882837026 submodule tests: test usage behavior
 2:  7425f0025da =  2:  a015be8e89a submodule tests: test for "add <repository> <abs-path>"
 3:  1be48c0b22f =  3:  27a455d231a submodule--helper: remove unused "name" helper
 4:  10189ba3da7 =  4:  6714a04a5c8 submodule--helper: remove unused "list" helper
 5:  ef66dfcd45f =  5:  83516cdcb5c test-tool submodule-config: remove unused "--url" handling
 6:  4727fbb4b64 =  6:  51d2d946b4f submodule--helper: move "is-active" to a test-tool
 7:  9c644460b1d =  7:  3258b5a609d submodule--helper: move "check-name" to a test-tool
 8:  03c8383b8e7 =  8:  4e6929f05ec submodule--helper: move "resolve-relative-url-test" to a test-tool
 9:  b1eaa6a796b =  9:  76b55b9105f submodule--helper style: don't separate declared variables with \n\n
10:  fd7fbe08536 = 10:  44b27475864 submodule--helper style: add \n\n after variable declarations
11:  356f07db436 = 11:  008c6f4ac59 submodule--helper: replace memset() with { 0 }-initialization
12:  241ac5c7eee = 12:  84504a86a72 submodule--helper: use xstrfmt() in clone_submodule()
13:  f2f412f50c1 = 13:  474d1a9e13e submodule--helper: move "sb" in clone_submodule() to its own scope
14:  ad7848067a9 = 14:  e514f0b68c0 submodule--helper: add "const" to passed "module_clone_data"
15:  ab283479b92 = 15:  30be00d5cf7 submodule--helper: add "const" to copy of "update_data"
 -:  ----------- > 16:  b77364015cf submodule--helper: add "const" to passed "struct update_data"
16:  ab0fd2c60f0 = 17:  52da0d60b47 submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
17:  fa2417c7a17 ! 18:  1786e40ec99 submodule--helper: don't redundantly check "else if (res)"
    @@ Commit message
                         return 0;
     
         So we don't need to guard the "return 1" with an "else if (res)", we
    -    an return unconditionally at this point. See b3c5f5cb048 (submodule:
    +    can return unconditionally at this point. See b3c5f5cb048 (submodule:
         move core cmd_update() logic to C, 2022-03-15) for the initial
         introduction of this code, this check of "res" has always been
         redundant.
18:  be1ffbf2e26 = 19:  bc7d401bfb3 submodule--helper: rename "int res" to "int ret"
19:  92e17c37839 = 20:  fdd9ef8b6f6 submodule--helper: return "ret", not "1" from update_submodule()
20:  55e3ea5f9dd = 21:  9edd68f9c5a submodule--helper: add missing braces to "else" arm
21:  2bb45302392 ! 22:  f0ada6854c2 submodule--helper: don't call submodule_strategy_to_string() in BUG()
    @@ Commit message
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      		must_die_on_failure = 1;
      		break;
      	default:
    @@ builtin/submodule--helper.c: static int run_update_command(struct update_data *u
      	}
      	strvec_push(&cp.args, oid);
      
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      			    ud->update_strategy.command, oid, ud->displaypath);
      			break;
      		default:
    @@ builtin/submodule--helper.c: static int run_update_command(struct update_data *u
      		}
      		if (must_die_on_failure)
      			exit(128);
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      		       ud->displaypath, ud->update_strategy.command, oid);
      		break;
      	default:
22:  0131c197427 = 23:  d101aa6c8c5 submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string()
23:  6cac6cb2fa6 ! 24:  77d21b570e3 submodule--helper: use "code" in run_update_command()
    @@ Commit message
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      {
      	struct child_process cp = CHILD_PROCESS_INIT;
      	char *oid = oid_to_hex(&ud->oid);
    @@ builtin/submodule--helper.c: static int run_update_command(struct update_data *u
      
      	switch (ud->update_strategy.type) {
      	case SM_UPDATE_CHECKOUT:
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      		strvec_push(&cp.args, "rebase");
      		if (ud->quiet)
      			strvec_push(&cp.args, "--quiet");
    @@ builtin/submodule--helper.c: static int run_update_command(struct update_data *u
      		break;
      	default:
      		BUG("unexpected update strategy type: %d",
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      	cp.dir = xstrdup(ud->sm_path);
      	prepare_submodule_repo_env(&cp.env);
      	if (run_command(&cp)) {
24:  6d56f671c7a ! 25:  99717171578 submodule--helper: don't exit() on failure, return
    @@ Commit message
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    -@@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
    +@@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_path, int depth, int quiet,
      	return run_command(&cp);
      }
      
    --static int run_update_command(struct update_data *ud, int subforce)
    -+static int run_update_command(struct update_data *ud, int subforce,
    +-static int run_update_command(const struct update_data *ud, int subforce)
    ++static int run_update_command(const struct update_data *ud, int subforce,
     +			      int *must_die_on_failure)
      {
      	struct child_process cp = CHILD_PROCESS_INIT;
      	char *oid = oid_to_hex(&ud->oid);
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      		}
      
      		if (ret == 128)
    @@ builtin/submodule--helper.c: static int run_update_command(struct update_data *u
      		return ret;
      	}
      
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      	return 0;
      }
      
    --static int run_update_procedure(struct update_data *ud)
    -+static int run_update_procedure(struct update_data *ud,
    +-static int run_update_procedure(const struct update_data *ud)
    ++static int run_update_procedure(const struct update_data *ud,
     +				int *must_die_on_failure)
      {
      	int subforce = is_null_oid(&ud->suboid) || ud->force;
      
    -@@ builtin/submodule--helper.c: static int run_update_procedure(struct update_data *ud)
    +@@ builtin/submodule--helper.c: static int run_update_procedure(const struct update_data *ud)
      			    ud->displaypath, oid_to_hex(&ud->oid));
      	}
      
    @@ builtin/submodule--helper.c: static int run_update_procedure(struct update_data
      }
      
      static const char *remote_submodule_branch(const char *path)
    -@@ builtin/submodule--helper.c: static void update_data_to_args(struct update_data *update_data, struct strvec *
    +@@ builtin/submodule--helper.c: static void update_data_to_args(const struct update_data *update_data,
      				    "--no-single-branch");
      }
      
25:  dfd5c8bcd61 ! 26:  512106bc6be submodule--helper: libify determine_submodule_update_strategy()
    @@ builtin/submodule--helper.c: static void determine_submodule_update_strategy(str
      }
      
      struct update_clone_data {
    -@@ builtin/submodule--helper.c: static void update_data_to_args(struct update_data *update_data, struct strvec *
    +@@ builtin/submodule--helper.c: static void update_data_to_args(const struct update_data *update_data,
      static int update_submodule(struct update_data *update_data,
      			    int *must_die_on_failure)
      {
26:  da1a07afd25 ! 27:  2b066190739 submodule--helper: libify "must_die_on_failure" code paths
    @@ Commit message
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    -@@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
    +@@ builtin/submodule--helper.c: static int fetch_in_submodule(const char *module_path, int depth, int quiet,
      	return run_command(&cp);
      }
      
    --static int run_update_command(struct update_data *ud, int subforce,
    +-static int run_update_command(const struct update_data *ud, int subforce,
     -			      int *must_die_on_failure)
    -+static int run_update_command(struct update_data *ud, int subforce)
    ++static int run_update_command(const struct update_data *ud, int subforce)
      {
      	struct child_process cp = CHILD_PROCESS_INIT;
      	char *oid = oid_to_hex(&ud->oid);
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce,
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce,
      			    ud->update_strategy.type);
      		}
      
    @@ builtin/submodule--helper.c: static int run_update_command(struct update_data *u
      		return ret;
      	}
      
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce,
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce,
      	return 0;
      }
      
    --static int run_update_procedure(struct update_data *ud,
    +-static int run_update_procedure(const struct update_data *ud,
     -				int *must_die_on_failure)
    -+static int run_update_procedure(struct update_data *ud)
    ++static int run_update_procedure(const struct update_data *ud)
      {
      	int subforce = is_null_oid(&ud->suboid) || ud->force;
      
    -@@ builtin/submodule--helper.c: static int run_update_procedure(struct update_data *ud,
    +@@ builtin/submodule--helper.c: static int run_update_procedure(const struct update_data *ud,
      			    ud->displaypath, oid_to_hex(&ud->oid));
      	}
      
    @@ builtin/submodule--helper.c: static int run_update_procedure(struct update_data
      }
      
      static const char *remote_submodule_branch(const char *path)
    -@@ builtin/submodule--helper.c: static void update_data_to_args(struct update_data *update_data, struct strvec *
    +@@ builtin/submodule--helper.c: static void update_data_to_args(const struct update_data *update_data,
      				    "--no-single-branch");
      }
      
27:  2795a3738c8 ! 28:  72e3cdf6543 submodule--helper update: don't override 'checkout' exit code
    @@ Commit message
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      {
      	struct child_process cp = CHILD_PROCESS_INIT;
      	char *oid = oid_to_hex(&ud->oid);
    @@ builtin/submodule--helper.c: static int run_update_command(struct update_data *u
      
      	switch (ud->update_strategy.type) {
      	case SM_UPDATE_CHECKOUT:
    -@@ builtin/submodule--helper.c: static int run_update_command(struct update_data *ud, int subforce)
    +@@ builtin/submodule--helper.c: static int run_update_command(const struct update_data *ud, int subforce)
      
      	cp.dir = xstrdup(ud->sm_path);
      	prepare_submodule_repo_env(&cp.env);
28:  6d9bccb34c3 ! 29:  a283ae61e6e submodule--helper: libify "must_die_on_failure" code paths (for die)
    @@ Commit message
     
         Continue the libification of codepaths that previously relied on
         "must_die_on_failure". In these cases we've always been early aborting
    -    by calling die(), but as we know that these codpaths will properly
    +    by calling die(), but as we know that these codepaths will properly
         handle return codes of 128 to mean an early abort let's have them use
         die_message() instead.
     
    @@ Commit message
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    -@@ builtin/submodule--helper.c: static int run_update_procedure(struct update_data *ud)
    +@@ builtin/submodule--helper.c: static int run_update_procedure(const struct update_data *ud)
      		 */
      		if (!is_tip_reachable(ud->sm_path, &ud->oid) &&
      		    fetch_in_submodule(ud->sm_path, ud->depth, ud->quiet, &ud->oid))
29:  d4b55f07a30 = 30:  ba5c170c3a4 submodule--helper: check repo{_submodule,}_init() return values
30:  15c2490a978 ! 31:  a0d71b4e8bb submodule--helper: libify more "die" paths for module_update()
    @@ Commit message
                 char *remote_name = get_default_remote_submodule(update_data->sm_path);
                 const char *branch = remote_submodule_branch(update_data->sm_path);
     
    +    We can safely remove the "!default_remote" case from sync_submodule(),
    +    because our get_default_remote_submodule() function now returns a
    +    die_message() on failure, so we can have it an dother callers check if
    +    the exit code should be non-zero instead.
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
31:  1694ccfe882 ! 32:  3254a8ca6eb submodule--helper: libify even more "die" paths for module_update()
    @@ Commit message
         2022-03-04):
     
         We were assuming that remote_submodule_branch() would always return
    -    on-NULL, but if the submodule_from_path() call in that function fails
    +    non-NULL, but if the submodule_from_path() call in that function fails
         we'll return NULL. See its introduction in
    -    92bbe7ccf1f (submodule--helper: add remote-branch helper, 2016-08-03).
    +    92bbe7ccf1f (submodule--helper: add remote-branch helper,
    +    2016-08-03). I.e. we'd previously have segfaulted in the xstrfmt()
    +    call in update_submodule() seen in the context.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/submodule--helper.c ##
    -@@ builtin/submodule--helper.c: static int run_update_procedure(struct update_data *ud)
    +@@ builtin/submodule--helper.c: static int run_update_procedure(const struct update_data *ud)
      	return run_update_command(ud, subforce);
      }
      
32:  d133402462f = 33:  1e38bfa7f95 submodule--helper: fix bad config API usage
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply	[flat|nested] 142+ messages in thread

* [PATCH v4 01/33] submodule tests: test usage behavior
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 02/33] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
                       ` (32 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Test what exit code and output we emit on "git submodule -h", how we
handle "--" when no subcommand is specified, and how the top-level
"--recursive" option is handled.

For "-h" this doesn't make sense, but let's test for it so that any
subsequent eventual behavior change will become clear.

For "--" this follows up on 68cabbfda36 (submodule: document default
behavior, 2019-02-15) and tests that "status" doesn't support
the "--" delimiter. There's no intrinsically good reason not to
support that. We behave this way due to edge cases in
git-submodule.sh's implementation, but as with "-h" let's assert our
current long-standing behavior for now.

For "--recursive" the exclusion of it from the top-level appears to
have been an omission in 15fc56a8536 (git submodule foreach: Add
--recursive to recurse into nested submodules, 2009-08-19), there
doesn't seem to be a reason not to support it alongside "--quiet" and
"--cached", but let's likewise assert our existing behavior for now.

I.e. as long as "status" is optional it would make sense to support
all of its options when it's omitted, but we only do that with
"--quiet" and "--cached", and curiously omit "--recursive".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t7400-submodule-basic.sh | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index e7cec2e457a..b858871a953 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -14,6 +14,32 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./test-lib.sh
 
+test_expect_success 'submodule usage: -h' '
+	git submodule -h >out 2>err &&
+	grep "^usage: git submodule" out &&
+	test_must_be_empty err
+'
+
+test_expect_success 'submodule usage: --recursive' '
+	test_expect_code 1 git submodule --recursive >out 2>err &&
+	grep "^usage: git submodule" err &&
+	test_must_be_empty out
+'
+
+test_expect_success 'submodule usage: status --' '
+	test_expect_code 1 git submodule -- &&
+	test_expect_code 1 git submodule --end-of-options
+'
+
+for opt in '--quiet' '--cached'
+do
+	test_expect_success "submodule usage: status $opt" '
+		git submodule $opt &&
+		git submodule status $opt &&
+		git submodule $opt status
+	'
+done
+
 test_expect_success 'submodule deinit works on empty repository' '
 	git submodule deinit --all
 '
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 02/33] submodule tests: test for "add <repository> <abs-path>"
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 01/33] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 03/33] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
                       ` (31 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add a missing test for ""add <repository> <path>" where "<path>" is an
absolute path. This tests code added in [1] and later turned into an
"else" branch in clone_submodule() in [2] that's never been tested.

This needs to be skipped on WINDOWS because all of $PWD, $(pwd) and
the "$(pwd -P)" we get via "$submodurl" would fail in CI with e.g.:

	fatal: could not create directory 'D:/a/git/git/t/trash
	directory.t7400-submodule-basic/.git/modules/D:/a/git/git/t/trash
	directory.t7400-submodule-basic/add-abs'

I.e. we can't handle these sorts of paths in this context on that
platform.

I'm not sure where we run into the edges of "$PWD" behavior on
Windows (see [1] for a previous loose end on the topic), but for the
purposes of this test it's sufficient that we test this on other
platforms.

1. ee8838d1577 (submodule: rewrite `module_clone` shell function in C,
   2015-09-08)
2. f8eaa0ba98b (submodule--helper, module_clone: always operate on
   absolute paths, 2016-03-31)

1. https://lore.kernel.org/git/220630.86edz6c75c.gmgdl@evledraar.gmail.com/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t7400-submodule-basic.sh | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index b858871a953..6a77d817a82 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -178,6 +178,11 @@ test_expect_success 'submodule add' '
 	test_must_be_empty untracked
 '
 
+test_expect_success !WINDOWS 'submodule add (absolute path)' '
+	test_when_finished "git reset --hard" &&
+	git submodule add "$submodurl" "$submodurl/add-abs"
+'
+
 test_expect_success 'setup parent and one repository' '
 	test_create_repo parent &&
 	test_commit -C parent one
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 03/33] submodule--helper: remove unused "name" helper
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 01/33] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 02/33] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 04/33] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
                       ` (30 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The "name" helper has not been used since e83e3333b57 (submodule: port
submodule subcommand 'summary' from shell to C, 2020-08-13).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b63f420ecef..fc4d2779da6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -771,24 +771,6 @@ static int module_status(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static int module_name(int argc, const char **argv, const char *prefix)
-{
-	const struct submodule *sub;
-
-	if (argc != 2)
-		usage(_("git submodule--helper name <path>"));
-
-	sub = submodule_from_path(the_repository, null_oid(), argv[1]);
-
-	if (!sub)
-		die(_("no submodule mapping found in .gitmodules for path '%s'"),
-		    argv[1]);
-
-	printf("%s\n", sub->name);
-
-	return 0;
-}
-
 struct module_cb {
 	unsigned int mod_src;
 	unsigned int mod_dst;
@@ -3362,7 +3344,6 @@ struct cmd_struct {
 
 static struct cmd_struct commands[] = {
 	{"list", module_list, 0},
-	{"name", module_name, 0},
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 04/33] submodule--helper: remove unused "list" helper
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (2 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 03/33] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 05/33] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
                       ` (29 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Remove the "submodule--helper list" sub-command, which hasn't been
used by git-submodule.sh since 2964d6e5e1e (submodule: port subcommand
'set-branch' from shell to C, 2020-06-02).

There was a test added in 2b56bb7a87a (submodule helper list: respect
correct path prefix, 2016-02-24) which relied on it, but the right
thing to do here is to delete that test as well.

That test was regression testing the "list" subcommand itself. We're
not getting anything useful from the "list | cut -f2" invocation that
we couldn't get from "foreach 'echo $sm_path'".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 40 -------------------------------------
 t/t7400-submodule-basic.sh  | 25 -----------------------
 2 files changed, 65 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fc4d2779da6..24a305151d1 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -266,45 +266,6 @@ static char *get_up_path(const char *path)
 	return strbuf_detach(&sb, NULL);
 }
 
-static int module_list(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-
-	struct option module_list_options[] = {
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper list [--prefix=<path>] [<path>...]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_list_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	for (i = 0; i < list.nr; i++) {
-		const struct cache_entry *ce = list.entries[i];
-
-		if (ce_stage(ce))
-			printf("%06o %s U\t", ce->ce_mode,
-			       oid_to_hex(null_oid()));
-		else
-			printf("%06o %s %d\t", ce->ce_mode,
-			       oid_to_hex(&ce->oid), ce_stage(ce));
-
-		fprintf(stdout, "%s\n", ce->name);
-	}
-	return 0;
-}
-
 static void for_each_listed_submodule(const struct module_list *list,
 				      each_submodule_fn fn, void *cb_data)
 {
@@ -3343,7 +3304,6 @@ struct cmd_struct {
 };
 
 static struct cmd_struct commands[] = {
-	{"list", module_list, 0},
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 6a77d817a82..b50db3f1031 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -1255,31 +1255,6 @@ test_expect_success 'submodule add clone shallow submodule' '
 	)
 '
 
-test_expect_success 'submodule helper list is not confused by common prefixes' '
-	mkdir -p dir1/b &&
-	(
-		cd dir1/b &&
-		git init &&
-		echo hi >testfile2 &&
-		git add . &&
-		git commit -m "test1"
-	) &&
-	mkdir -p dir2/b &&
-	(
-		cd dir2/b &&
-		git init &&
-		echo hello >testfile1 &&
-		git add .  &&
-		git commit -m "test2"
-	) &&
-	git submodule add /dir1/b dir1/b &&
-	git submodule add /dir2/b dir2/b &&
-	git commit -m "first submodule commit" &&
-	git submodule--helper list dir1/b | cut -f 2 >actual &&
-	echo "dir1/b" >expect &&
-	test_cmp expect actual
-'
-
 test_expect_success 'setup superproject with submodules' '
 	git init sub1 &&
 	test_commit -C sub1 test &&
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 05/33] test-tool submodule-config: remove unused "--url" handling
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (3 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 04/33] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 06/33] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
                       ` (28 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

No test has used this "--url" parameter since the test code that made
use of it was removed in 32bc548329d (submodule-config: remove support
for overlaying repository config, 2017-08-03).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/helper/test-submodule-config.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index e2692746dfd..22a41c40926 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -15,14 +15,11 @@ int cmd__submodule_config(int argc, const char **argv)
 {
 	const char **arg = argv;
 	int my_argc = argc;
-	int output_url = 0;
 	int lookup_name = 0;
 
 	arg++;
 	my_argc--;
 	while (arg[0] && starts_with(arg[0], "--")) {
-		if (!strcmp(arg[0], "--url"))
-			output_url = 1;
 		if (!strcmp(arg[0], "--name"))
 			lookup_name = 1;
 		arg++;
@@ -57,12 +54,8 @@ int cmd__submodule_config(int argc, const char **argv)
 		if (!submodule)
 			die_usage(argc, argv, "Submodule not found.");
 
-		if (output_url)
-			printf("Submodule url: '%s' for path '%s'\n",
-					submodule->url, submodule->path);
-		else
-			printf("Submodule name: '%s' for path '%s'\n",
-					submodule->name, submodule->path);
+		printf("Submodule name: '%s' for path '%s'\n", submodule->name,
+		       submodule->path);
 
 		arg += 2;
 	}
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 06/33] submodule--helper: move "is-active" to a test-tool
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (4 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 05/33] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 07/33] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
                       ` (27 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Create a new "test-tool submodule" and move the "is-active" subcommand
over to it. It was added in 5c2bd8b77ae (submodule--helper: add
is-active subcommand, 2017-03-16), since
a452128a36c (submodule--helper: introduce add-config subcommand,
2021-08-06) it hasn't been used by git-submodule.sh.

Since we're creating a command dispatch similar to test-tool.c itself
let's split out the "struct test_cmd" into a new test-tool-utils.h,
which both this new code and test-tool.c itself can use.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Makefile                       |  1 +
 builtin/submodule--helper.c    |  9 ------
 t/helper/test-submodule.c      | 58 ++++++++++++++++++++++++++++++++++
 t/helper/test-tool-utils.h     |  9 ++++++
 t/helper/test-tool.c           |  7 ++--
 t/helper/test-tool.h           |  1 +
 t/t7413-submodule-is-active.sh | 35 ++++++++++----------
 7 files changed, 90 insertions(+), 30 deletions(-)
 create mode 100644 t/helper/test-submodule.c
 create mode 100644 t/helper/test-tool-utils.h

diff --git a/Makefile b/Makefile
index eac30126e29..e0daec07306 100644
--- a/Makefile
+++ b/Makefile
@@ -786,6 +786,7 @@ TEST_BUILTINS_OBJS += test-strcmp-offset.o
 TEST_BUILTINS_OBJS += test-string-list.o
 TEST_BUILTINS_OBJS += test-submodule-config.o
 TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
+TEST_BUILTINS_OBJS += test-submodule.o
 TEST_BUILTINS_OBJS += test-subprocess.o
 TEST_BUILTINS_OBJS += test-trace2.o
 TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 24a305151d1..e10c3ac7550 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2731,14 +2731,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static int is_active(int argc, const char **argv, const char *prefix)
-{
-	if (argc != 2)
-		die("submodule--helper is-active takes exactly 1 argument");
-
-	return !is_submodule_active(the_repository, argv[1]);
-}
-
 /*
  * Exit non-zero if any of the submodule names given on the command line is
  * invalid. If no names are given, filter stdin to print only valid names
@@ -3316,7 +3308,6 @@ static struct cmd_struct commands[] = {
 	{"summary", module_summary, 0},
 	{"push-check", push_check, 0},
 	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
-	{"is-active", is_active, 0},
 	{"check-name", check_name, 0},
 	{"config", module_config, 0},
 	{"set-url", module_set_url, 0},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
new file mode 100644
index 00000000000..494c6558d9f
--- /dev/null
+++ b/t/helper/test-submodule.c
@@ -0,0 +1,58 @@
+#include "test-tool.h"
+#include "test-tool-utils.h"
+#include "cache.h"
+#include "parse-options.h"
+#include "submodule.h"
+
+#define TEST_TOOL_IS_ACTIVE_USAGE \
+	"test-tool submodule is-active <name>"
+static const char *submodule_is_active_usage[] = {
+	TEST_TOOL_IS_ACTIVE_USAGE,
+	NULL
+};
+
+static const char *submodule_usage[] = {
+	TEST_TOOL_IS_ACTIVE_USAGE,
+	NULL
+};
+
+static int cmd__submodule_is_active(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_is_active_usage, 0);
+	if (argc != 1)
+		usage_with_options(submodule_is_active_usage, options);
+
+	setup_git_directory();
+
+	return !is_submodule_active(the_repository, argv[0]);
+}
+
+static struct test_cmd cmds[] = {
+	{ "is-active", cmd__submodule_is_active },
+};
+
+int cmd__submodule(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	size_t i;
+
+	argc = parse_options(argc, argv, "test-tools", options, submodule_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (argc < 1)
+		usage_with_options(submodule_usage, options);
+
+	for (i = 0; i < ARRAY_SIZE(cmds); i++)
+		if (!strcmp(cmds[i].name, argv[0]))
+			return cmds[i].fn(argc, argv);
+
+	usage_msg_optf("unknown subcommand '%s'", submodule_usage, options,
+		       argv[0]);
+
+	return 0;
+}
diff --git a/t/helper/test-tool-utils.h b/t/helper/test-tool-utils.h
new file mode 100644
index 00000000000..6a0e5e0074f
--- /dev/null
+++ b/t/helper/test-tool-utils.h
@@ -0,0 +1,9 @@
+#ifndef TEST_TOOL_UTILS_H
+#define TEST_TOOL_UTILS_H
+
+struct test_cmd {
+	const char *name;
+	int (*fn)(int argc, const char **argv);
+};
+
+#endif
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index d6a560f8325..50a6ae38a7d 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -1,5 +1,6 @@
 #include "git-compat-util.h"
 #include "test-tool.h"
+#include "test-tool-utils.h"
 #include "trace2.h"
 #include "parse-options.h"
 
@@ -8,11 +9,6 @@ static const char * const test_tool_usage[] = {
 	NULL
 };
 
-struct test_cmd {
-	const char *name;
-	int (*fn)(int argc, const char **argv);
-};
-
 static struct test_cmd cmds[] = {
 	{ "advise", cmd__advise_if_enabled },
 	{ "bitmap", cmd__bitmap },
@@ -79,6 +75,7 @@ static struct test_cmd cmds[] = {
 	{ "simple-ipc", cmd__simple_ipc },
 	{ "strcmp-offset", cmd__strcmp_offset },
 	{ "string-list", cmd__string_list },
+	{ "submodule", cmd__submodule },
 	{ "submodule-config", cmd__submodule_config },
 	{ "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
 	{ "subprocess", cmd__subprocess },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index 21a91b10195..6921a6fc2c5 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -69,6 +69,7 @@ int cmd__sigchain(int argc, const char **argv);
 int cmd__simple_ipc(int argc, const char **argv);
 int cmd__strcmp_offset(int argc, const char **argv);
 int cmd__string_list(int argc, const char **argv);
+int cmd__submodule(int argc, const char **argv);
 int cmd__submodule_config(int argc, const char **argv);
 int cmd__submodule_nested_repo_config(int argc, const char **argv);
 int cmd__subprocess(int argc, const char **argv);
diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
index c8e7e983317..ede6f02dbd5 100755
--- a/t/t7413-submodule-is-active.sh
+++ b/t/t7413-submodule-is-active.sh
@@ -1,9 +1,12 @@
 #!/bin/sh
 
-test_description='Test submodule--helper is-active
+test_description='Test with test-tool submodule is-active
 
-This test verifies that `git submodue--helper is-active` correctly identifies
+This test verifies that `test-tool submodule is-active` correctly identifies
 submodules which are "active" and interesting to the user.
+
+This is a unit test of the submodule.c is_submodule_active() function,
+which is also indirectly tested elsewhere.
 '
 
 . ./test-lib.sh
@@ -25,13 +28,13 @@ test_expect_success 'setup' '
 '
 
 test_expect_success 'is-active works with urls' '
-	git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2 &&
+	test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2 &&
 
 	git -C super config --unset submodule.sub1.URL &&
-	test_must_fail git -C super submodule--helper is-active sub1 &&
+	test_must_fail test-tool -C super submodule is-active sub1 &&
 	git -C super config submodule.sub1.URL ../sub &&
-	git -C super submodule--helper is-active sub1
+	test-tool -C super submodule is-active sub1
 '
 
 test_expect_success 'is-active works with submodule.<name>.active config' '
@@ -39,11 +42,11 @@ test_expect_success 'is-active works with submodule.<name>.active config' '
 	test_when_finished "git -C super config submodule.sub1.URL ../sub" &&
 
 	git -C super config --bool submodule.sub1.active "false" &&
-	test_must_fail git -C super submodule--helper is-active sub1 &&
+	test_must_fail test-tool -C super submodule is-active sub1 &&
 
 	git -C super config --bool submodule.sub1.active "true" &&
 	git -C super config --unset submodule.sub1.URL &&
-	git -C super submodule--helper is-active sub1
+	test-tool -C super submodule is-active sub1
 '
 
 test_expect_success 'is-active works with basic submodule.active config' '
@@ -53,17 +56,17 @@ test_expect_success 'is-active works with basic submodule.active config' '
 	git -C super config --add submodule.active "." &&
 	git -C super config --unset submodule.sub1.URL &&
 
-	git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active correctly works with paths that are not submodules' '
 	test_when_finished "git -C super config --unset-all submodule.active" &&
 
-	test_must_fail git -C super submodule--helper is-active not-a-submodule &&
+	test_must_fail test-tool -C super submodule is-active not-a-submodule &&
 
 	git -C super config --add submodule.active "." &&
-	test_must_fail git -C super submodule--helper is-active not-a-submodule
+	test_must_fail test-tool -C super submodule is-active not-a-submodule
 '
 
 test_expect_success 'is-active works with exclusions in submodule.active config' '
@@ -72,8 +75,8 @@ test_expect_success 'is-active works with exclusions in submodule.active config'
 	git -C super config --add submodule.active "." &&
 	git -C super config --add submodule.active ":(exclude)sub1" &&
 
-	test_must_fail git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test_must_fail test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active with submodule.active and submodule.<name>.active' '
@@ -85,8 +88,8 @@ test_expect_success 'is-active with submodule.active and submodule.<name>.active
 	git -C super config --bool submodule.sub1.active "false" &&
 	git -C super config --bool submodule.sub2.active "true" &&
 
-	test_must_fail git -C super submodule--helper is-active sub1 &&
-	git -C super submodule--helper is-active sub2
+	test_must_fail test-tool -C super submodule is-active sub1 &&
+	test-tool -C super submodule is-active sub2
 '
 
 test_expect_success 'is-active, submodule.active and submodule add' '
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 07/33] submodule--helper: move "check-name" to a test-tool
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (5 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 06/33] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 08/33] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
                       ` (26 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Move the "check-name" helper to a test-tool, since
a6226fd772b (submodule--helper: convert the bulk of cmd_add() to C,
2021-08-10) it has only been used by this test, not git-submodule.sh.

As noted with its introduction in 0383bbb9015 (submodule-config:
verify submodule names as paths, 2018-04-30) the intent of
t7450-bad-git-dotfiles.sh has always been to unit test the
check_submodule_name() function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 24 -------------------
 t/helper/test-submodule.c   | 46 +++++++++++++++++++++++++++++++++++++
 t/t7450-bad-git-dotfiles.sh |  2 +-
 3 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e10c3ac7550..e8458567976 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2731,29 +2731,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-/*
- * Exit non-zero if any of the submodule names given on the command line is
- * invalid. If no names are given, filter stdin to print only valid names
- * (which is primarily intended for testing).
- */
-static int check_name(int argc, const char **argv, const char *prefix)
-{
-	if (argc > 1) {
-		while (*++argv) {
-			if (check_submodule_name(*argv) < 0)
-				return 1;
-		}
-	} else {
-		struct strbuf buf = STRBUF_INIT;
-		while (strbuf_getline(&buf, stdin) != EOF) {
-			if (!check_submodule_name(buf.buf))
-				printf("%s\n", buf.buf);
-		}
-		strbuf_release(&buf);
-	}
-	return 0;
-}
-
 static int module_config(int argc, const char **argv, const char *prefix)
 {
 	enum {
@@ -3308,7 +3285,6 @@ static struct cmd_struct commands[] = {
 	{"summary", module_summary, 0},
 	{"push-check", push_check, 0},
 	{"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
-	{"check-name", check_name, 0},
 	{"config", module_config, 0},
 	{"set-url", module_set_url, 0},
 	{"set-branch", module_set_branch, 0},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 494c6558d9f..9f0eb440192 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -2,8 +2,16 @@
 #include "test-tool-utils.h"
 #include "cache.h"
 #include "parse-options.h"
+#include "submodule-config.h"
 #include "submodule.h"
 
+#define TEST_TOOL_CHECK_NAME_USAGE \
+	"test-tool submodule check-name <name>"
+static const char *submodule_check_name_usage[] = {
+	TEST_TOOL_CHECK_NAME_USAGE,
+	NULL
+};
+
 #define TEST_TOOL_IS_ACTIVE_USAGE \
 	"test-tool submodule is-active <name>"
 static const char *submodule_is_active_usage[] = {
@@ -12,10 +20,47 @@ static const char *submodule_is_active_usage[] = {
 };
 
 static const char *submodule_usage[] = {
+	TEST_TOOL_CHECK_NAME_USAGE,
 	TEST_TOOL_IS_ACTIVE_USAGE,
 	NULL
 };
 
+/*
+ * Exit non-zero if any of the submodule names given on the command line is
+ * invalid. If no names are given, filter stdin to print only valid names
+ * (which is primarily intended for testing).
+ */
+static int check_name(int argc, const char **argv)
+{
+	if (argc > 1) {
+		while (*++argv) {
+			if (check_submodule_name(*argv) < 0)
+				return 1;
+		}
+	} else {
+		struct strbuf buf = STRBUF_INIT;
+		while (strbuf_getline(&buf, stdin) != EOF) {
+			if (!check_submodule_name(buf.buf))
+				printf("%s\n", buf.buf);
+		}
+		strbuf_release(&buf);
+	}
+	return 0;
+}
+
+static int cmd__submodule_check_name(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_check_name_usage, 0);
+	if (argc)
+		usage_with_options(submodule_check_name_usage, options);
+
+	return check_name(argc, argv);
+}
+
 static int cmd__submodule_is_active(int argc, const char **argv)
 {
 	struct option options[] = {
@@ -32,6 +77,7 @@ static int cmd__submodule_is_active(int argc, const char **argv)
 }
 
 static struct test_cmd cmds[] = {
+	{ "check-name", cmd__submodule_check_name },
 	{ "is-active", cmd__submodule_is_active },
 };
 
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index 41706c1c9ff..2c24f120da3 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -21,7 +21,7 @@ test_expect_success 'check names' '
 	valid/with/paths
 	EOF
 
-	git submodule--helper check-name >actual <<-\EOF &&
+	test-tool submodule check-name >actual <<-\EOF &&
 	valid
 	valid/with/paths
 
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 08/33] submodule--helper: move "resolve-relative-url-test" to a test-tool
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (6 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 07/33] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 09/33] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
                       ` (25 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

As its name suggests the "resolve-relative-url-test" has never been
used outside of the test suite, see 63e95beb085 (submodule: port
resolve_relative_url from shell to C, 2016-04-15) for its original
addition.

Perhaps it would make sense to drop this code entirely, as we feel
that we've got enough indirect test coverage, but let's leave that
question to a possible follow-up change. For now let's keep the test
coverage this gives us.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 23 --------------------
 t/helper/test-submodule.c   | 42 +++++++++++++++++++++++++++++++++++++
 t/t0060-path-utils.sh       |  2 +-
 3 files changed, 43 insertions(+), 24 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e8458567976..7e2986902dd 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -96,28 +96,6 @@ static char *resolve_relative_url(const char *rel_url, const char *up_path, int
 	return resolved_url;
 }
 
-static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
-{
-	char *remoteurl, *res;
-	const char *up_path, *url;
-
-	if (argc != 4)
-		die("resolve-relative-url-test only accepts three arguments: <up_path> <remoteurl> <url>");
-
-	up_path = argv[1];
-	remoteurl = xstrdup(argv[2]);
-	url = argv[3];
-
-	if (!strcmp(up_path, "(null)"))
-		up_path = NULL;
-
-	res = relative_url(remoteurl, url, up_path);
-	puts(res);
-	free(res);
-	free(remoteurl);
-	return 0;
-}
-
 /* the result should be freed by the caller. */
 static char *get_submodule_displaypath(const char *path, const char *prefix)
 {
@@ -3276,7 +3254,6 @@ static struct cmd_struct commands[] = {
 	{"clone", module_clone, SUPPORT_SUPER_PREFIX},
 	{"add", module_add, 0},
 	{"update", module_update, SUPPORT_SUPER_PREFIX},
-	{"resolve-relative-url-test", resolve_relative_url_test, 0},
 	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
 	{"init", module_init, 0},
 	{"status", module_status, SUPPORT_SUPER_PREFIX},
diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c
index 9f0eb440192..e0e0c53d386 100644
--- a/t/helper/test-submodule.c
+++ b/t/helper/test-submodule.c
@@ -2,6 +2,7 @@
 #include "test-tool-utils.h"
 #include "cache.h"
 #include "parse-options.h"
+#include "remote.h"
 #include "submodule-config.h"
 #include "submodule.h"
 
@@ -19,9 +20,17 @@ static const char *submodule_is_active_usage[] = {
 	NULL
 };
 
+#define TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE \
+	"test-tool submodule resolve-relative-url <up_path> <remoteurl> <url>"
+static const char *submodule_resolve_relative_url_usage[] = {
+	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
+	NULL,
+};
+
 static const char *submodule_usage[] = {
 	TEST_TOOL_CHECK_NAME_USAGE,
 	TEST_TOOL_IS_ACTIVE_USAGE,
+	TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE,
 	NULL
 };
 
@@ -76,9 +85,42 @@ static int cmd__submodule_is_active(int argc, const char **argv)
 	return !is_submodule_active(the_repository, argv[0]);
 }
 
+static int resolve_relative_url(int argc, const char **argv)
+{
+	char *remoteurl, *res;
+	const char *up_path, *url;
+
+	up_path = argv[0];
+	remoteurl = xstrdup(argv[1]);
+	url = argv[2];
+
+	if (!strcmp(up_path, "(null)"))
+		up_path = NULL;
+
+	res = relative_url(remoteurl, url, up_path);
+	puts(res);
+	free(res);
+	free(remoteurl);
+	return 0;
+}
+
+static int cmd__submodule_resolve_relative_url(int argc, const char **argv)
+{
+	struct option options[] = {
+		OPT_END()
+	};
+	argc = parse_options(argc, argv, "test-tools", options,
+			     submodule_resolve_relative_url_usage, 0);
+	if (argc != 3)
+		usage_with_options(submodule_resolve_relative_url_usage, options);
+
+	return resolve_relative_url(argc, argv);
+}
+
 static struct test_cmd cmds[] = {
 	{ "check-name", cmd__submodule_check_name },
 	{ "is-active", cmd__submodule_is_active },
+	{ "resolve-relative-url", cmd__submodule_resolve_relative_url},
 };
 
 int cmd__submodule(int argc, const char **argv)
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 1f2007e62b7..68e29c904a6 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -22,7 +22,7 @@ relative_path() {
 
 test_submodule_relative_url() {
 	test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" "
-		actual=\$(git submodule--helper resolve-relative-url-test '$1' '$2' '$3') &&
+		actual=\$(test-tool submodule resolve-relative-url '$1' '$2' '$3') &&
 		test \"\$actual\" = '$4'
 	"
 }
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 09/33] submodule--helper style: don't separate declared variables with \n\n
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (7 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 08/33] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 10/33] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
                       ` (24 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The usual style in the codebase is to separate declared variables with
a single newline, not two, let's adjust this code to conform to
that. This makes the eventual addition of various "int ret" variables
more consistent.

In doing this the comment added in 2964d6e5e1e (submodule: port
subcommand 'set-branch' from shell to C, 2020-06-02) might become
ambiguous to some, although it should be clear what it's referring to,
let's move it above the 'OPT_NOOP_NOARG('q', "quiet")' to make that
clearer.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 33 +++++----------------------------
 1 file changed, 5 insertions(+), 28 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 7e2986902dd..02552410679 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -368,14 +368,12 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
 	struct foreach_cb info = FOREACH_CB_INIT;
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
-
 	struct option module_foreach_options[] = {
 		OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
 		OPT_BOOL(0, "recursive", &info.recursive,
 			 N_("recurse into nested submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
 		NULL
@@ -504,12 +502,10 @@ static int module_init(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
-
 	struct option module_init_options[] = {
 		OPT__QUIET(&quiet, N_("suppress output for initializing a submodule")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule init [<options>] [<path>]"),
 		NULL
@@ -682,14 +678,12 @@ static int module_status(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
-
 	struct option module_status_options[] = {
 		OPT__QUIET(&quiet, N_("suppress submodule status output")),
 		OPT_BIT(0, "cached", &info.flags, N_("use commit stored in the index instead of the one stored in the submodule HEAD"), OPT_CACHED),
 		OPT_BIT(0, "recursive", &info.flags, N_("recurse into nested submodules"), OPT_RECURSIVE),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
 		NULL
@@ -1085,7 +1079,6 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 	enum diff_cmd diff_cmd = DIFF_INDEX;
 	struct object_id head_oid;
 	int ret;
-
 	struct option module_summary_options[] = {
 		OPT_BOOL(0, "cached", &cached,
 			 N_("use the commit stored in the index instead of the submodule HEAD")),
@@ -1097,7 +1090,6 @@ static int module_summary(int argc, const char **argv, const char *prefix)
 			     N_("limit the summary size")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule summary [<options>] [<commit>] [--] [<path>]"),
 		NULL
@@ -1254,14 +1246,12 @@ static int module_sync(int argc, const char **argv, const char *prefix)
 	struct module_list list = MODULE_LIST_INIT;
 	int quiet = 0;
 	int recursive = 0;
-
 	struct option module_sync_options[] = {
 		OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
 		OPT_BOOL(0, "recursive", &recursive,
 			N_("recurse into nested submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule sync [--quiet] [--recursive] [<path>]"),
 		NULL
@@ -1393,14 +1383,12 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
 	int quiet = 0;
 	int force = 0;
 	int all = 0;
-
 	struct option module_deinit_options[] = {
 		OPT__QUIET(&quiet, N_("suppress submodule status output")),
 		OPT__FORCE(&force, N_("remove submodule working trees even if they contain local changes"), 0),
 		OPT_BOOL(0, "all", &all, N_("unregister all submodules")),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
 		NULL
@@ -1669,7 +1657,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
 	struct list_objects_filter_options filter_options;
-
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1701,7 +1688,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule--helper clone [--prefix=<path>] [--quiet] "
 		   "[--reference <repository>] [--name <name>] [--depth <depth>] "
@@ -2489,7 +2475,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 	struct update_data opt = UPDATE_DATA_INIT;
 	struct list_objects_filter_options filter_options;
 	int ret;
-
 	struct option module_update_options[] = {
 		OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
 		OPT_BOOL(0, "init", &opt.init,
@@ -2533,7 +2518,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule [--quiet] update"
 		" [--init [--filter=<filter-spec>]] [--remote]"
@@ -2682,7 +2666,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct module_list list = MODULE_LIST_INIT;
 	unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
-
 	struct option embed_gitdir_options[] = {
 		OPT_STRING(0, "prefix", &prefix,
 			   N_("path"),
@@ -2691,7 +2674,6 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
 			ABSORB_GITDIR_RECURSE_SUBMODULES),
 		OPT_END()
 	};
-
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule absorbgitdirs [<options>] [<path>...]"),
 		NULL
@@ -2715,7 +2697,6 @@ static int module_config(int argc, const char **argv, const char *prefix)
 		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"),
@@ -2761,7 +2742,6 @@ static int module_set_url(int argc, const char **argv, const char *prefix)
 	const char *newurl;
 	const char *path;
 	char *config_name;
-
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("suppress output for setting url of a submodule")),
 		OPT_END()
@@ -2792,13 +2772,13 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
 	const char *opt_branch = NULL;
 	const char *path;
 	char *config_name;
-
-	/*
-	 * We accept the `quiet` option for uniformity across subcommands,
-	 * though there is nothing to make less verbose in this subcommand.
-	 */
 	struct option options[] = {
+		/*
+		 * We accept the `quiet` option for uniformity across subcommands,
+		 * though there is nothing to make less verbose in this subcommand.
+		 */
 		OPT_NOOP_NOARG('q', "quiet"),
+
 		OPT_BOOL('d', "default", &opt_default,
 			N_("set the default tracking branch to master")),
 		OPT_STRING('b', "branch", &opt_branch, N_("branch"),
@@ -2833,7 +2813,6 @@ static int module_create_branch(int argc, const char **argv, const char *prefix)
 {
 	enum branch_track track;
 	int quiet = 0, force = 0, reflog = 0, dry_run = 0;
-
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("print only error messages")),
 		OPT__FORCE(&force, N_("force creation"), 0),
@@ -3132,7 +3111,6 @@ static int module_add(int argc, const char **argv, const char *prefix)
 	int force = 0, quiet = 0, progress = 0, dissociate = 0;
 	struct add_data add_data = ADD_DATA_INIT;
 	char *to_free = NULL;
-
 	struct option options[] = {
 		OPT_STRING('b', "branch", &add_data.branch, N_("branch"),
 			   N_("branch of repository to add as submodule")),
@@ -3149,7 +3127,6 @@ static int module_add(int argc, const char **argv, const char *prefix)
 		OPT_INTEGER(0, "depth", &add_data.depth, N_("depth for shallow clones")),
 		OPT_END()
 	};
-
 	const char *const usage[] = {
 		N_("git submodule add [<options>] [--] <repository> [<path>]"),
 		NULL
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 10/33] submodule--helper style: add \n\n after variable declarations
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (8 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 09/33] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 11/33] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
                       ` (23 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Since the preceding commit fixed style issues with \n\n among the
declared variables let's fix the minor stylistic issues with those
variables not being consistently followed by a \n\n.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 02552410679..a492ea3cfed 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -167,6 +167,7 @@ static int module_list_compute(int argc, const char **argv,
 {
 	int i, result = 0;
 	char *ps_matched = NULL;
+
 	parse_pathspec(pathspec, 0,
 		       PATHSPEC_PREFER_FULL,
 		       prefix, argv);
@@ -248,6 +249,7 @@ static void for_each_listed_submodule(const struct module_list *list,
 				      each_submodule_fn fn, void *cb_data)
 {
 	int i;
+
 	for (i = 0; i < list->nr; i++)
 		fn(list->entries[i], cb_data);
 }
@@ -267,7 +269,6 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
 	struct foreach_cb *info = cb_data;
 	const char *path = list_item->name;
 	const struct object_id *ce_oid = &list_item->oid;
-
 	const struct submodule *sub;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *displaypath;
@@ -456,6 +457,7 @@ static void init_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(url) ||
 		    starts_with_dot_slash(url)) {
 			char *oldurl = url;
+
 			url = resolve_relative_url(oldurl, NULL, 0);
 			free(oldurl);
 		}
@@ -493,6 +495,7 @@ static void init_submodule(const char *path, const char *prefix,
 static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
 {
 	struct init_cb *info = cb_data;
+
 	init_submodule(list_item->name, info->prefix, info->flags);
 }
 
@@ -562,6 +565,7 @@ static int handle_submodule_head_ref(const char *refname,
 				     void *cb_data)
 {
 	struct object_id *output = cb_data;
+
 	if (oid)
 		oidcpy(output, oid);
 
@@ -668,6 +672,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
 				void *cb_data)
 {
 	struct status_cb *info = cb_data;
+
 	status_submodule(list_item->name, &list_item->oid, list_item->ce_flags,
 			 info->prefix, info->flags);
 }
@@ -820,6 +825,7 @@ static void generate_submodule_summary(struct summary_cb *info,
 	if (!info->cached && oideq(&p->oid_dst, null_oid())) {
 		if (S_ISGITLINK(p->mod_dst)) {
 			struct ref_store *refs = get_submodule_ref_store(p->sm_path);
+
 			if (refs)
 				refs_head_ref(refs, handle_submodule_head_ref, &p->oid_dst);
 		} else if (S_ISLNK(p->mod_dst) || S_ISREG(p->mod_dst)) {
@@ -1161,6 +1167,7 @@ static void sync_submodule(const char *path, const char *prefix,
 		if (starts_with_dot_dot_slash(sub->url) ||
 		    starts_with_dot_slash(sub->url)) {
 			char *up_path = get_up_path(path);
+
 			sub_origin_url = resolve_relative_url(sub->url, up_path, 1);
 			super_config_url = resolve_relative_url(sub->url, NULL, 1);
 			free(up_path);
@@ -1236,6 +1243,7 @@ static void sync_submodule(const char *path, const char *prefix,
 static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data)
 {
 	struct sync_cb *info = cb_data;
+
 	sync_submodule(list_item->name, info->prefix, info->flags);
 }
 
@@ -1315,6 +1323,7 @@ static void deinit_submodule(const char *path, const char *prefix,
 
 		if (!(flags & OPT_FORCE)) {
 			struct child_process cp_rm = CHILD_PROCESS_INIT;
+
 			cp_rm.git_cmd = 1;
 			strvec_pushl(&cp_rm.args, "rm", "-qn",
 				     path, NULL);
@@ -1351,6 +1360,7 @@ static void deinit_submodule(const char *path, const char *prefix,
 	/* remove the .git/config entries (unless the user already did it) */
 	if (!capture_command(&cp_config, &sb_config, 0) && sb_config.len) {
 		char *sub_key = xstrfmt("submodule.%s", sub->name);
+
 		/*
 		 * remove the whole section so we have a clean state when
 		 * the user later decides to init this submodule again
@@ -1588,6 +1598,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
 		if (clone_data->reference.nr) {
 			struct string_list_item *item;
+
 			for_each_string_list_item(item, &clone_data->reference)
 				strvec_pushl(&cp.args, "--reference",
 					     item->string, NULL);
@@ -1938,6 +1949,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	strvec_pushl(&child->args, "--url", url, NULL);
 	if (suc->update_data->references.nr) {
 		struct string_list_item *item;
+
 		for_each_string_list_item(item, &suc->update_data->references)
 			strvec_pushl(&child->args, "--reference", item->string, NULL);
 	}
@@ -1970,6 +1982,7 @@ static int update_clone_get_next_task(struct child_process *child,
 		ce = suc->update_data->list.entries[suc->current];
 		if (prepare_to_clone_next_submodule(ce, child, suc, err)) {
 			int *p = xmalloc(sizeof(*p));
+
 			*p = suc->current;
 			*idx_task_cb = p;
 			suc->current++;
@@ -1985,6 +1998,7 @@ static int update_clone_get_next_task(struct child_process *child,
 	index = suc->current - suc->update_data->list.nr;
 	if (index < suc->failed_clones_nr) {
 		int *p;
+
 		ce = suc->failed_clones[index];
 		if (!prepare_to_clone_next_submodule(ce, child, suc, err)) {
 			suc->current ++;
@@ -2008,6 +2022,7 @@ static int update_clone_start_failure(struct strbuf *err,
 				      void *idx_task_cb)
 {
 	struct submodule_update_clone *suc = suc_cb;
+
 	suc->quickstop = 1;
 	return 1;
 }
@@ -2019,9 +2034,9 @@ static int update_clone_task_finished(int result,
 {
 	const struct cache_entry *ce;
 	struct submodule_update_clone *suc = suc_cb;
-
 	int *idxP = idx_task_cb;
 	int idx = *idxP;
+
 	free(idxP);
 
 	if (!result)
@@ -2054,6 +2069,7 @@ static int git_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;
@@ -2094,6 +2110,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	if (oid) {
 		char *hex = oid_to_hex(oid);
 		char *remote = get_default_remote();
+
 		strvec_pushl(&cp.args, remote, hex, NULL);
 		free(remote);
 	}
@@ -2343,6 +2360,7 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
 
 	if (update_data->references.nr) {
 		struct string_list_item *item;
+
 		for_each_string_list_item(item, &update_data->references)
 			strvec_pushl(args, "--reference", item->string, NULL);
 	}
@@ -2875,8 +2893,10 @@ static void append_fetch_remotes(struct strbuf *msg, const char *git_dir_path)
 	if (!capture_command(&cp_remote, &sb_remote_out, 0)) {
 		char *next_line;
 		char *line = sb_remote_out.buf;
+
 		while ((next_line = strchr(line, '\n')) != NULL) {
 			size_t len = next_line - line;
+
 			if (strip_suffix_mem(line, &len, " (fetch)"))
 				strbuf_addf(msg, "  %.*s\n", (int)len, line);
 			line = next_line + 1;
@@ -3183,6 +3203,7 @@ static int module_add(int argc, const char **argv, const char *prefix)
 		int exit_code = -1;
 		struct strbuf sb = STRBUF_INIT;
 		struct child_process cp = CHILD_PROCESS_INIT;
+
 		cp.git_cmd = 1;
 		cp.no_stdout = 1;
 		strvec_pushl(&cp.args, "add", "--dry-run", "--ignore-missing",
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 11/33] submodule--helper: replace memset() with { 0 }-initialization
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (9 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 10/33] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 12/33] submodule--helper: use xstrfmt() in clone_submodule() Ævar Arnfjörð Bjarmason
                       ` (22 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Use the less verbose { 0 }-initialization syntax rather than memset()
in builtin/submodule--helper.c, this doesn't make a difference in
terms of behavior, but as we're about to modify adjacent code makes
this more consistent, and lets us avoid worrying about when the
memset() happens v.s. a "goto cleanup".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index a492ea3cfed..7eb9fb2f00f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1667,7 +1667,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 {
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
-	struct list_objects_filter_options filter_options;
+	struct list_objects_filter_options filter_options = { 0 };
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1707,7 +1707,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		NULL
 	};
 
-	memset(&filter_options, 0, sizeof(filter_options));
 	argc = parse_options(argc, argv, prefix, module_clone_options,
 			     git_submodule_helper_usage, 0);
 
@@ -2491,7 +2490,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
 {
 	struct pathspec pathspec;
 	struct update_data opt = UPDATE_DATA_INIT;
-	struct list_objects_filter_options filter_options;
+	struct list_objects_filter_options filter_options = { 0 };
 	int ret;
 	struct option module_update_options[] = {
 		OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
@@ -2549,7 +2548,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
 	update_clone_config_from_gitmodules(&opt.max_jobs);
 	git_config(git_update_clone_config, &opt.max_jobs);
 
-	memset(&filter_options, 0, sizeof(filter_options));
 	argc = parse_options(argc, argv, prefix, module_update_options,
 			     git_submodule_helper_usage, 0);
 
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 12/33] submodule--helper: use xstrfmt() in clone_submodule()
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (10 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 11/33] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 13/33] submodule--helper: move "sb" in clone_submodule() to its own scope Ævar Arnfjörð Bjarmason
                       ` (21 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Use xstrfmt() in clone_submodule() instead of a "struct strbuf" in two
cases where we weren't getting anything out of using the "struct
strbuf".

This changes code that was was added along with other uses of "struct
strbuf" in this function in ee8838d1577 (submodule: rewrite
`module_clone` shell function in C, 2015-09-08).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 7eb9fb2f00f..c7833bae81e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1571,12 +1571,11 @@ static int clone_submodule(struct module_clone_data *clone_data)
 	sm_gitdir = absolute_pathdup(sb.buf);
 	strbuf_reset(&sb);
 
-	if (!is_absolute_path(clone_data->path)) {
-		strbuf_addf(&sb, "%s/%s", get_git_work_tree(), clone_data->path);
-		clone_data->path = strbuf_detach(&sb, NULL);
-	} else {
+	if (!is_absolute_path(clone_data->path))
+		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
+					   clone_data->path);
+	else
 		clone_data->path = xstrdup(clone_data->path);
-	}
 
 	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
 		die(_("refusing to create/use '%s' in another submodule's "
@@ -1628,14 +1627,16 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			die(_("clone of '%s' into submodule path '%s' failed"),
 			    clone_data->url, clone_data->path);
 	} else {
+		char *path;
+
 		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
 		    !is_empty_dir(clone_data->path))
 			die(_("directory not empty: '%s'"), clone_data->path);
 		if (safe_create_leading_directories_const(clone_data->path) < 0)
 			die(_("could not create directory '%s'"), clone_data->path);
-		strbuf_addf(&sb, "%s/index", sm_gitdir);
-		unlink_or_warn(sb.buf);
-		strbuf_reset(&sb);
+		path = xstrfmt("%s/index", sm_gitdir);
+		unlink_or_warn(path);
+		free(path);
 	}
 
 	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 13/33] submodule--helper: move "sb" in clone_submodule() to its own scope
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (11 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 12/33] submodule--helper: use xstrfmt() in clone_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 14/33] submodule--helper: add "const" to passed "module_clone_data" Ævar Arnfjörð Bjarmason
                       ` (20 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Refactor the only remaining use of a "struct strbuf sb" in
clone_submodule() to live in its own scope. This makes the code
clearer by limiting its lifetime.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index c7833bae81e..2f1f0e1bf34 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1560,16 +1560,24 @@ static void prepare_possible_alternates(const char *sm_name,
 	free(error_strategy);
 }
 
-static int clone_submodule(struct module_clone_data *clone_data)
+static char *clone_submodule_sm_gitdir(const char *name)
 {
-	char *p, *sm_gitdir;
-	char *sm_alternate = NULL, *error_strategy = NULL;
 	struct strbuf sb = STRBUF_INIT;
-	struct child_process cp = CHILD_PROCESS_INIT;
+	char *sm_gitdir;
 
-	submodule_name_to_gitdir(&sb, the_repository, clone_data->name);
+	submodule_name_to_gitdir(&sb, the_repository, name);
 	sm_gitdir = absolute_pathdup(sb.buf);
-	strbuf_reset(&sb);
+	strbuf_release(&sb);
+
+	return sm_gitdir;
+}
+
+static int clone_submodule(struct module_clone_data *clone_data)
+{
+	char *p;
+	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
+	char *sm_alternate = NULL, *error_strategy = NULL;
+	struct child_process cp = CHILD_PROCESS_INIT;
 
 	if (!is_absolute_path(clone_data->path))
 		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
@@ -1658,7 +1666,6 @@ static int clone_submodule(struct module_clone_data *clone_data)
 	free(sm_alternate);
 	free(error_strategy);
 
-	strbuf_release(&sb);
 	free(sm_gitdir);
 	free(p);
 	return 0;
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 14/33] submodule--helper: add "const" to passed "module_clone_data"
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (12 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 13/33] submodule--helper: move "sb" in clone_submodule() to its own scope Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 15/33] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
                       ` (19 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add "const" to the "struct module_clone_data" that we pass to
clone_submodule(), which makes the ownership clear, and stops us from
clobbering the "clone_data->path".

We still need to add to the "reference" member, which is a "struct
string_list". Let's do this by having clone_submodule() create its
own, and copy the contents over, allowing us to pass it as a
separate parameter.

This new "struct string_list" still leaks memory, just as the "struct
module_clone_data" did before. let's not fix that for now, to fix that
we'll need to add some "goto cleanup" to the relevant code. That will
eventually be done in follow-up commits, this change makes it easier
to fix the memory leak.

The scope of the new "reference" variable in add_submodule() could be
narrowed to the "else" block, but as we'll eventually free it with a
"goto cleanup" let's declare it at the start of the function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 49 ++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2f1f0e1bf34..d243c3ddfd3 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1437,7 +1437,6 @@ struct module_clone_data {
 	const char *url;
 	const char *depth;
 	struct list_objects_filter_options *filter_options;
-	struct string_list reference;
 	unsigned int quiet: 1;
 	unsigned int progress: 1;
 	unsigned int dissociate: 1;
@@ -1445,7 +1444,6 @@ struct module_clone_data {
 	int single_branch;
 };
 #define MODULE_CLONE_DATA_INIT { \
-	.reference = STRING_LIST_INIT_NODUP, \
 	.single_branch = -1, \
 }
 
@@ -1572,18 +1570,20 @@ static char *clone_submodule_sm_gitdir(const char *name)
 	return sm_gitdir;
 }
 
-static int clone_submodule(struct module_clone_data *clone_data)
+static int clone_submodule(const struct module_clone_data *clone_data,
+			   struct string_list *reference)
 {
 	char *p;
 	char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
 	char *sm_alternate = NULL, *error_strategy = NULL;
 	struct child_process cp = CHILD_PROCESS_INIT;
+	const char *clone_data_path;
 
 	if (!is_absolute_path(clone_data->path))
-		clone_data->path = xstrfmt("%s/%s", get_git_work_tree(),
-					   clone_data->path);
+		clone_data_path = xstrfmt("%s/%s", get_git_work_tree(),
+					  clone_data->path);
 	else
-		clone_data->path = xstrdup(clone_data->path);
+		clone_data_path = xstrdup(clone_data->path);
 
 	if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)
 		die(_("refusing to create/use '%s' in another submodule's "
@@ -1593,7 +1593,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 		if (safe_create_leading_directories_const(sm_gitdir) < 0)
 			die(_("could not create directory '%s'"), sm_gitdir);
 
-		prepare_possible_alternates(clone_data->name, &clone_data->reference);
+		prepare_possible_alternates(clone_data->name, reference);
 
 		strvec_push(&cp.args, "clone");
 		strvec_push(&cp.args, "--no-checkout");
@@ -1603,10 +1603,10 @@ static int clone_submodule(struct module_clone_data *clone_data)
 			strvec_push(&cp.args, "--progress");
 		if (clone_data->depth && *(clone_data->depth))
 			strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
-		if (clone_data->reference.nr) {
+		if (reference->nr) {
 			struct string_list_item *item;
 
-			for_each_string_list_item(item, &clone_data->reference)
+			for_each_string_list_item(item, reference)
 				strvec_pushl(&cp.args, "--reference",
 					     item->string, NULL);
 		}
@@ -1625,7 +1625,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
 
 		strvec_push(&cp.args, "--");
 		strvec_push(&cp.args, clone_data->url);
-		strvec_push(&cp.args, clone_data->path);
+		strvec_push(&cp.args, clone_data_path);
 
 		cp.git_cmd = 1;
 		prepare_submodule_repo_env(&cp.env);
@@ -1633,25 +1633,25 @@ static int clone_submodule(struct module_clone_data *clone_data)
 
 		if(run_command(&cp))
 			die(_("clone of '%s' into submodule path '%s' failed"),
-			    clone_data->url, clone_data->path);
+			    clone_data->url, clone_data_path);
 	} else {
 		char *path;
 
-		if (clone_data->require_init && !access(clone_data->path, X_OK) &&
-		    !is_empty_dir(clone_data->path))
-			die(_("directory not empty: '%s'"), clone_data->path);
-		if (safe_create_leading_directories_const(clone_data->path) < 0)
-			die(_("could not create directory '%s'"), clone_data->path);
+		if (clone_data->require_init && !access(clone_data_path, X_OK) &&
+		    !is_empty_dir(clone_data_path))
+			die(_("directory not empty: '%s'"), clone_data_path);
+		if (safe_create_leading_directories_const(clone_data_path) < 0)
+			die(_("could not create directory '%s'"), clone_data_path);
 		path = xstrfmt("%s/index", sm_gitdir);
 		unlink_or_warn(path);
 		free(path);
 	}
 
-	connect_work_tree_and_git_dir(clone_data->path, sm_gitdir, 0);
+	connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0);
 
-	p = git_pathdup_submodule(clone_data->path, "config");
+	p = git_pathdup_submodule(clone_data_path, "config");
 	if (!p)
-		die(_("could not get submodule directory for '%s'"), clone_data->path);
+		die(_("could not get submodule directory for '%s'"), clone_data_path);
 
 	/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
 	git_config_get_string("submodule.alternateLocation", &sm_alternate);
@@ -1676,6 +1676,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	int dissociate = 0, quiet = 0, progress = 0, require_init = 0;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
 	struct list_objects_filter_options filter_options = { 0 };
+	struct string_list reference = STRING_LIST_INIT_NODUP;
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &clone_data.prefix,
 			   N_("path"),
@@ -1689,7 +1690,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		OPT_STRING(0, "url", &clone_data.url,
 			   N_("string"),
 			   N_("url where to clone the submodule from")),
-		OPT_STRING_LIST(0, "reference", &clone_data.reference,
+		OPT_STRING_LIST(0, "reference", &reference,
 			   N_("repo"),
 			   N_("reference repository")),
 		OPT_BOOL(0, "dissociate", &dissociate,
@@ -1728,7 +1729,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		usage_with_options(git_submodule_helper_usage,
 				   module_clone_options);
 
-	clone_submodule(&clone_data);
+	clone_submodule(&clone_data, &reference);
 	list_objects_filter_release(&filter_options);
 	return 0;
 }
@@ -2916,6 +2917,7 @@ static int add_submodule(const struct add_data *add_data)
 {
 	char *submod_gitdir_path;
 	struct module_clone_data clone_data = MODULE_CLONE_DATA_INIT;
+	struct string_list reference = STRING_LIST_INIT_NODUP;
 
 	/* perhaps the path already exists and is already a git repo, else clone it */
 	if (is_directory(add_data->sm_path)) {
@@ -2932,6 +2934,7 @@ static int add_submodule(const struct add_data *add_data)
 		free(submod_gitdir_path);
 	} else {
 		struct child_process cp = CHILD_PROCESS_INIT;
+
 		submod_gitdir_path = xstrfmt(".git/modules/%s", add_data->sm_name);
 
 		if (is_directory(submod_gitdir_path)) {
@@ -2971,13 +2974,13 @@ static int add_submodule(const struct add_data *add_data)
 		clone_data.quiet = add_data->quiet;
 		clone_data.progress = add_data->progress;
 		if (add_data->reference_path)
-			string_list_append(&clone_data.reference,
+			string_list_append(&reference,
 					   xstrdup(add_data->reference_path));
 		clone_data.dissociate = add_data->dissociate;
 		if (add_data->depth >= 0)
 			clone_data.depth = xstrfmt("%d", add_data->depth);
 
-		if (clone_submodule(&clone_data))
+		if (clone_submodule(&clone_data, &reference))
 			return -1;
 
 		prepare_submodule_repo_env(&cp.env);
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 15/33] submodule--helper: add "const" to copy of "update_data"
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (13 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 14/33] submodule--helper: add "const" to passed "module_clone_data" Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 16/33] submodule--helper: add "const" to passed "struct update_data" Ævar Arnfjörð Bjarmason
                       ` (18 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

From: Glen Choo <chooglen@google.com>

Add a "const" to the copy of "struct update_data" that's tracked by
the "struct submodule_update_clone", as it neither owns nor modifies
it.

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index d243c3ddfd3..829a57ce8a9 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1780,7 +1780,7 @@ struct submodule_update_clone {
 	int current;
 
 	/* configuration parameters which are passed on to the children */
-	struct update_data *update_data;
+	const struct update_data *update_data;
 
 	/* to be consumed by update_submodule() */
 	struct update_clone_data *update_clone;
@@ -1865,7 +1865,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 	const char *update_string;
 	enum submodule_update_type update_type;
 	char *key;
-	struct update_data *ud = suc->update_data;
+	const struct update_data *ud = suc->update_data;
 	char *displaypath = get_submodule_displaypath(ce->name, ud->prefix);
 	struct strbuf sb = STRBUF_INIT;
 	int needs_cloning = 0;
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 16/33] submodule--helper: add "const" to passed "struct update_data"
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (14 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 15/33] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:17     ` [PATCH v4 17/33] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
                       ` (17 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add a "const" to the "struct update_data" passed to
run_update_procedure(), which it in turn passes along (peeled) to
is_tip_reachable() and fetch_in_submodule()).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 829a57ce8a9..4e3bb54afa2 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2083,7 +2083,7 @@ static int git_update_clone_config(const char *var, const char *value,
 	return 0;
 }
 
-static int is_tip_reachable(const char *path, struct object_id *oid)
+static int is_tip_reachable(const char *path, const struct object_id *oid)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	struct strbuf rev = STRBUF_INIT;
@@ -2102,7 +2102,8 @@ static int is_tip_reachable(const char *path, struct object_id *oid)
 	return 1;
 }
 
-static int fetch_in_submodule(const char *module_path, int depth, int quiet, struct object_id *oid)
+static int fetch_in_submodule(const char *module_path, int depth, int quiet,
+			      const struct object_id *oid)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 
@@ -2126,7 +2127,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
 	return run_command(&cp);
 }
 
-static int run_update_command(struct update_data *ud, int subforce)
+static int run_update_command(const struct update_data *ud, int subforce)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
@@ -2223,7 +2224,7 @@ static int run_update_command(struct update_data *ud, int subforce)
 	return 0;
 }
 
-static int run_update_procedure(struct update_data *ud)
+static int run_update_procedure(const struct update_data *ud)
 {
 	int subforce = is_null_oid(&ud->suboid) || ud->force;
 
@@ -2334,7 +2335,8 @@ static const char *submodule_update_type_to_label(enum submodule_update_type typ
 	BUG("unreachable with type %d", type);
 }
 
-static void update_data_to_args(struct update_data *update_data, struct strvec *args)
+static void update_data_to_args(const struct update_data *update_data,
+				struct strvec *args)
 {
 	enum submodule_update_type update_type = update_data->update_default;
 
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 17/33] submodule--helper: refactor "errmsg_str" to be a "struct strbuf"
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (15 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 16/33] submodule--helper: add "const" to passed "struct update_data" Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:17     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 18/33] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
                       ` (16 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

From: Glen Choo <chooglen@google.com>

Refactor code added in e83e3333b57 (submodule: port submodule
subcommand 'summary' from shell to C, 2020-08-13) so that "errmsg" and
"errmsg_str" are folded into one. The distinction between the empty
string and NULL is something that's tested for by
e.g. "t/t7401-submodule-summary.sh".

This is in preparation for fixing a memory leak the "struct strbuf" in
the pre-image.

Let's also pass a "const char *" to print_submodule_summary(), as it
should not be modifying the "errmsg".

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 4e3bb54afa2..07a918f7373 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -761,7 +761,7 @@ static char *verify_submodule_committish(const char *sm_path,
 	return strbuf_detach(&result, NULL);
 }
 
-static void print_submodule_summary(struct summary_cb *info, char *errmsg,
+static void print_submodule_summary(struct summary_cb *info, const char *errmsg,
 				    int total_commits, const char *displaypath,
 				    const char *src_abbrev, const char *dst_abbrev,
 				    struct module_cb *p)
@@ -819,7 +819,7 @@ static void generate_submodule_summary(struct summary_cb *info,
 {
 	char *displaypath, *src_abbrev = NULL, *dst_abbrev;
 	int missing_src = 0, missing_dst = 0;
-	char *errmsg = NULL;
+	struct strbuf errmsg = STRBUF_INIT;
 	int total_commits = -1;
 
 	if (!info->cached && oideq(&p->oid_dst, null_oid())) {
@@ -920,23 +920,21 @@ static void generate_submodule_summary(struct summary_cb *info,
 		 * submodule, i.e., deleted or changed to blob
 		 */
 		if (S_ISGITLINK(p->mod_dst)) {
-			struct strbuf errmsg_str = STRBUF_INIT;
 			if (missing_src && missing_dst) {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commits %s and %s\n",
+				strbuf_addf(&errmsg, "  Warn: %s doesn't contain commits %s and %s\n",
 					    displaypath, oid_to_hex(&p->oid_src),
 					    oid_to_hex(&p->oid_dst));
 			} else {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commit %s\n",
+				strbuf_addf(&errmsg, "  Warn: %s doesn't contain commit %s\n",
 					    displaypath, missing_src ?
 					    oid_to_hex(&p->oid_src) :
 					    oid_to_hex(&p->oid_dst));
 			}
-			errmsg = strbuf_detach(&errmsg_str, NULL);
 		}
 	}
 
-	print_submodule_summary(info, errmsg, total_commits,
-				displaypath, src_abbrev,
+	print_submodule_summary(info, errmsg.len ? errmsg.buf : NULL,
+				total_commits, displaypath, src_abbrev,
 				dst_abbrev, p);
 
 	free(displaypath);
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 18/33] submodule--helper: don't redundantly check "else if (res)"
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (16 preceding siblings ...)
  2022-08-31 23:17     ` [PATCH v4 17/33] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 19/33] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
                       ` (15 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

The "res" variable must be true at this point in update_submodule(),
as just a few lines above this we've unconditionally:

	if (!res)
		return 0;

So we don't need to guard the "return 1" with an "else if (res)", we
can return unconditionally at this point. See b3c5f5cb048 (submodule:
move core cmd_update() logic to C, 2022-03-15) for the initial
introduction of this code, this check of "res" has always been
redundant.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 07a918f7373..93ab49defb1 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2448,8 +2448,7 @@ static int update_submodule(struct update_data *update_data)
 			    update_data->displaypath);
 		if (res == 128)
 			exit(res);
-		else if (res)
-			return 1;
+		return 1;
 	}
 
 	return 0;
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 19/33] submodule--helper: rename "int res" to "int ret"
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (17 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 18/33] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 20/33] submodule--helper: return "ret", not "1" from update_submodule() Ævar Arnfjörð Bjarmason
                       ` (14 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Rename the "res" variable added in b3c5f5cb048 (submodule: move core
cmd_update() logic to C, 2022-03-15) to "ret", which is the convention
in the rest of this file.

Eventual follow-up commits will change the code in update_submodule()
to a "goto cleanup" pattern, let's have the post image look consistent
with the rest. For update_submodules() let's also use a "ret" for
consistency, that use was also added in b3c5f5cb048. We'll be
modifying that codepath in subsequent commits.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 93ab49defb1..4fbbffb4637 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2429,7 +2429,7 @@ static int update_submodule(struct update_data *update_data)
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		struct update_data next = *update_data;
-		int res;
+		int ret;
 
 		next.prefix = NULL;
 		oidcpy(&next.oid, null_oid());
@@ -2441,13 +2441,13 @@ static int update_submodule(struct update_data *update_data)
 		update_data_to_args(&next, &cp.args);
 
 		/* die() if child process die()'d */
-		res = run_command(&cp);
-		if (!res)
+		ret = run_command(&cp);
+		if (!ret)
 			return 0;
 		die_message(_("Failed to recurse into submodule path '%s'"),
 			    update_data->displaypath);
-		if (res == 128)
-			exit(res);
+		if (ret == 128)
+			exit(ret);
 		return 1;
 	}
 
@@ -2456,7 +2456,7 @@ static int update_submodule(struct update_data *update_data)
 
 static int update_submodules(struct update_data *update_data)
 {
-	int i, res = 0;
+	int i, ret = 0;
 	struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
 
 	suc.update_data = update_data;
@@ -2474,7 +2474,7 @@ static int update_submodules(struct update_data *update_data)
 	 * - the listener can avoid doing any work if fetching failed.
 	 */
 	if (suc.quickstop) {
-		res = 1;
+		ret = 1;
 		goto cleanup;
 	}
 
@@ -2486,12 +2486,12 @@ static int update_submodules(struct update_data *update_data)
 		update_data->sm_path = ucd.sub->path;
 
 		if (update_submodule(update_data))
-			res = 1;
+			ret = 1;
 	}
 
 cleanup:
 	string_list_clear(&update_data->references, 0);
-	return res;
+	return ret;
 }
 
 static int module_update(int argc, const char **argv, const char *prefix)
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 20/33] submodule--helper: return "ret", not "1" from update_submodule()
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (18 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 19/33] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 21/33] submodule--helper: add missing braces to "else" arm Ævar Arnfjörð Bjarmason
                       ` (13 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Amend the update_submodule() function to return the failing "ret" on
error, instead of overriding it with "1".

This code was added in b3c5f5cb048 (submodule: move core cmd_update()
logic to C, 2022-03-15), and this change ends up not making a
difference as this function is only called in update_submodules(). If
we return non-zero here we'll always in turn return "1" in
module_update().

But if we didn't do that and returned any other non-zero exit code in
update_submodules() we'd fail the test that's being amended
here. We're still testing the status quo here.

This change makes subsequent refactoring of update_submodule() easier,
as we'll no longer need to worry about clobbering the "ret" we get
from the run_command().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 2 +-
 t/t7406-submodule-update.sh | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 4fbbffb4637..59c3a9afe6e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2448,7 +2448,7 @@ static int update_submodule(struct update_data *update_data)
 			    update_data->displaypath);
 		if (ret == 128)
 			exit(ret);
-		return 1;
+		return ret;
 	}
 
 	return 0;
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 6cc07460dd2..c5f5dbe55e0 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -769,7 +769,7 @@ test_expect_success 'submodule update continues after recursive checkout error'
 	   echo "" > file
 	  )
 	 ) &&
-	 test_must_fail git submodule update --recursive &&
+	 test_expect_code 1 git submodule update --recursive &&
 	 (cd submodule2 &&
 	  git rev-parse --verify HEAD >../actual
 	 ) &&
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 21/33] submodule--helper: add missing braces to "else" arm
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (19 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 20/33] submodule--helper: return "ret", not "1" from update_submodule() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 22/33] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
                       ` (12 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Add missing braces to an "else" arm in init_submodule(), this
stylistic change makes this code conform to the CodingGuidelines, and
makes a subsequent commit smaller.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 59c3a9afe6e..6c40be3170f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -480,8 +480,9 @@ static void init_submodule(const char *path, const char *prefix,
 			fprintf(stderr, _("warning: command update mode suggested for submodule '%s'\n"),
 				sub->name);
 			upd = xstrdup("none");
-		} else
+		} else {
 			upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy));
+		}
 
 		if (git_config_set_gently(sb.buf, upd))
 			die(_("Failed to register update mode for submodule path '%s'"), displaypath);
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 22/33] submodule--helper: don't call submodule_strategy_to_string() in BUG()
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (20 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 21/33] submodule--helper: add missing braces to "else" arm Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 23/33] submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string() Ævar Arnfjörð Bjarmason
                       ` (11 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Don't call submodule_strategy_to_string() in a BUG() message. These
calls added in c51f8f94e5b (submodule--helper: run update procedures
from C, 2021-08-24) don't need the extra information
submodule_strategy_to_string() gives us, as we'll never reach the
SM_UPDATE_COMMAND case here.

That case is the only one where we'd get any information beyond the
straightforward number-to-string mapping.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 6c40be3170f..965196a005d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2159,8 +2159,8 @@ static int run_update_command(const struct update_data *ud, int subforce)
 		must_die_on_failure = 1;
 		break;
 	default:
-		BUG("unexpected update strategy type: %s",
-		    submodule_strategy_to_string(&ud->update_strategy));
+		BUG("unexpected update strategy type: %d",
+		    ud->update_strategy.type);
 	}
 	strvec_push(&cp.args, oid);
 
@@ -2185,8 +2185,8 @@ static int run_update_command(const struct update_data *ud, int subforce)
 			    ud->update_strategy.command, oid, ud->displaypath);
 			break;
 		default:
-			BUG("unexpected update strategy type: %s",
-			    submodule_strategy_to_string(&ud->update_strategy));
+			BUG("unexpected update strategy type: %d",
+			    ud->update_strategy.type);
 		}
 		if (must_die_on_failure)
 			exit(128);
@@ -2216,8 +2216,8 @@ static int run_update_command(const struct update_data *ud, int subforce)
 		       ud->displaypath, ud->update_strategy.command, oid);
 		break;
 	default:
-		BUG("unexpected update strategy type: %s",
-		    submodule_strategy_to_string(&ud->update_strategy));
+		BUG("unexpected update strategy type: %d",
+		    ud->update_strategy.type);
 	}
 
 	return 0;
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 23/33] submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string()
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (21 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 22/33] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 24/33] submodule--helper: use "code" in run_update_command() Ævar Arnfjörð Bjarmason
                       ` (10 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Change the submodule_strategy_to_string() function added in
3604242f080 (submodule: port init from shell to C, 2016-04-15) to
really return a "const char *". In the "SM_UPDATE_COMMAND" case it
would return a strbuf_detach().

Furthermore, this function would return NULL on SM_UPDATE_UNSPECIFIED,
so it wasn't safe to xstrdup() its return value in the general case,
or to use it in a sprintf() format as the code removed in the
preceding commit did.

But its callers would never call it with either SM_UPDATE_UNSPECIFIED
or SM_UPDATE_COMMAND. Let's have its behavior reflect how its only
user expects it to behave, and BUG() out on the rest.

By doing this we can also stop needlessly xstrdup()-ing and free()-ing
the memory for the config we're setting. We can instead always use
constant strings. We can also use the *_tmp() variant of
git_config_get_string().

Let's also rename this submodule_strategy_to_string() function to
submodule_update_type_to_string(). Now that it's only tasked with
returning a string version of the "enum submodule_update_type type".
Before it would look at the "command" field in "struct
submodule_update_strategy".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 10 +++++-----
 submodule.c                 | 12 +++++-------
 submodule.h                 |  2 +-
 3 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 965196a005d..35989c81603 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -418,7 +418,8 @@ static void init_submodule(const char *path, const char *prefix,
 {
 	const struct submodule *sub;
 	struct strbuf sb = STRBUF_INIT;
-	char *upd = NULL, *url = NULL, *displaypath;
+	const char *upd;
+	char *url = NULL, *displaypath;
 
 	displaypath = get_submodule_displaypath(path, prefix);
 
@@ -474,14 +475,14 @@ static void init_submodule(const char *path, const char *prefix,
 
 	/* Copy "update" setting when it is not set yet */
 	strbuf_addf(&sb, "submodule.%s.update", sub->name);
-	if (git_config_get_string(sb.buf, &upd) &&
+	if (git_config_get_string_tmp(sb.buf, &upd) &&
 	    sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
 		if (sub->update_strategy.type == SM_UPDATE_COMMAND) {
 			fprintf(stderr, _("warning: command update mode suggested for submodule '%s'\n"),
 				sub->name);
-			upd = xstrdup("none");
+			upd = "none";
 		} else {
-			upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy));
+			upd = submodule_update_type_to_string(sub->update_strategy.type);
 		}
 
 		if (git_config_set_gently(sb.buf, upd))
@@ -490,7 +491,6 @@ static void init_submodule(const char *path, const char *prefix,
 	strbuf_release(&sb);
 	free(displaypath);
 	free(url);
-	free(upd);
 }
 
 static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
diff --git a/submodule.c b/submodule.c
index 3fa5db3ecdf..1ebda30c506 100644
--- a/submodule.c
+++ b/submodule.c
@@ -415,10 +415,9 @@ int parse_submodule_update_strategy(const char *value,
 	return 0;
 }
 
-const char *submodule_strategy_to_string(const struct submodule_update_strategy *s)
+const char *submodule_update_type_to_string(enum submodule_update_type type)
 {
-	struct strbuf sb = STRBUF_INIT;
-	switch (s->type) {
+	switch (type) {
 	case SM_UPDATE_CHECKOUT:
 		return "checkout";
 	case SM_UPDATE_MERGE:
@@ -428,12 +427,11 @@ const char *submodule_strategy_to_string(const struct submodule_update_strategy
 	case SM_UPDATE_NONE:
 		return "none";
 	case SM_UPDATE_UNSPECIFIED:
-		return NULL;
 	case SM_UPDATE_COMMAND:
-		strbuf_addf(&sb, "!%s", s->command);
-		return strbuf_detach(&sb, NULL);
+		BUG("init_submodule() should handle type %d", type);
+	default:
+		BUG("unexpected update strategy type: %d", type);
 	}
-	return NULL;
 }
 
 void handle_ignore_submodules_arg(struct diff_options *diffopt,
diff --git a/submodule.h b/submodule.h
index bfaa9da1868..6a9fec6de11 100644
--- a/submodule.h
+++ b/submodule.h
@@ -72,7 +72,7 @@ void die_path_inside_submodule(struct index_state *istate,
 enum submodule_update_type parse_submodule_update_type(const char *value);
 int parse_submodule_update_strategy(const char *value,
 				    struct submodule_update_strategy *dst);
-const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);
+const char *submodule_update_type_to_string(enum submodule_update_type type);
 void handle_ignore_submodules_arg(struct diff_options *, const char *);
 void show_submodule_diff_summary(struct diff_options *o, const char *path,
 			    struct object_id *one, struct object_id *two,
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 24/33] submodule--helper: use "code" in run_update_command()
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (22 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 23/33] submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 25/33] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
                       ` (9 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Apply some DRY principles in run_update_command() and don't have two
"switch" statements over "ud->update_strategy.type" determine the same
thing.

First we were setting "must_die_on_failure = 1" in all cases except
"SM_UPDATE_CHECKOUT" (and we'd BUG(...) out on the rest). This code
was added in c51f8f94e5b (submodule--helper: run update procedures
from C, 2021-08-24).

Then we'd duplicate same "switch" logic when we were using the
"must_die_on_failure" variable.

Let's instead have the "case" branches in that inner "switch"
determine whether or not the "update must continue" by picking an exit
code.

This also mostly avoids hardcoding the "128" exit code, instead we can
make use of the return value of the die_message() function, which
we've been calling here since 55b3f12cb54 (submodule update: use
die_message(), 2022-03-15). We're still hardcoding it to determine if
we "exit()", but subsequent commit(s) will address that.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 35989c81603..234f1f993e1 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2130,7 +2130,6 @@ static int run_update_command(const struct update_data *ud, int subforce)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
-	int must_die_on_failure = 0;
 
 	switch (ud->update_strategy.type) {
 	case SM_UPDATE_CHECKOUT:
@@ -2144,19 +2143,16 @@ static int run_update_command(const struct update_data *ud, int subforce)
 		strvec_push(&cp.args, "rebase");
 		if (ud->quiet)
 			strvec_push(&cp.args, "--quiet");
-		must_die_on_failure = 1;
 		break;
 	case SM_UPDATE_MERGE:
 		cp.git_cmd = 1;
 		strvec_push(&cp.args, "merge");
 		if (ud->quiet)
 			strvec_push(&cp.args, "--quiet");
-		must_die_on_failure = 1;
 		break;
 	case SM_UPDATE_COMMAND:
 		cp.use_shell = 1;
 		strvec_push(&cp.args, ud->update_strategy.command);
-		must_die_on_failure = 1;
 		break;
 	default:
 		BUG("unexpected update strategy type: %d",
@@ -2167,32 +2163,35 @@ static int run_update_command(const struct update_data *ud, int subforce)
 	cp.dir = xstrdup(ud->sm_path);
 	prepare_submodule_repo_env(&cp.env);
 	if (run_command(&cp)) {
+		int ret;
+
 		switch (ud->update_strategy.type) {
 		case SM_UPDATE_CHECKOUT:
 			die_message(_("Unable to checkout '%s' in submodule path '%s'"),
 				    oid, ud->displaypath);
+			/* the command failed, but update must continue */
+			ret = 1;
 			break;
 		case SM_UPDATE_REBASE:
-			die_message(_("Unable to rebase '%s' in submodule path '%s'"),
-			    oid, ud->displaypath);
+			ret = die_message(_("Unable to rebase '%s' in submodule path '%s'"),
+					  oid, ud->displaypath);
 			break;
 		case SM_UPDATE_MERGE:
-			die_message(_("Unable to merge '%s' in submodule path '%s'"),
-			    oid, ud->displaypath);
+			ret = die_message(_("Unable to merge '%s' in submodule path '%s'"),
+					  oid, ud->displaypath);
 			break;
 		case SM_UPDATE_COMMAND:
-			die_message(_("Execution of '%s %s' failed in submodule path '%s'"),
-			    ud->update_strategy.command, oid, ud->displaypath);
+			ret = die_message(_("Execution of '%s %s' failed in submodule path '%s'"),
+					  ud->update_strategy.command, oid, ud->displaypath);
 			break;
 		default:
 			BUG("unexpected update strategy type: %d",
 			    ud->update_strategy.type);
 		}
-		if (must_die_on_failure)
-			exit(128);
 
-		/* the command failed, but update must continue */
-		return 1;
+		if (ret == 128)
+			exit(ret);
+		return ret;
 	}
 
 	if (ud->quiet)
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 25/33] submodule--helper: don't exit() on failure, return
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (23 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 24/33] submodule--helper: use "code" in run_update_command() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 26/33] submodule--helper: libify determine_submodule_update_strategy() Ævar Arnfjörð Bjarmason
                       ` (8 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Change code downstream of module_update() to short-circuit and return
to the top-level on failure, rather than calling exit().

To do so we need to diligently check whether we "must_die_on_failure",
which is a pattern started in c51f8f94e5b (submodule--helper: run
update procedures from C, 2021-08-24), but which hadn't been completed
to the point where we could avoid calling exit() here.

This introduces no functional changes, but makes it easier to both
call these routines as a library in the future, and to eventually
avoid leaking memory.

This and similar control flow in submodule--helper.c could be made
simpler by properly "libifying" it, i.e. to have it consistently
return -1 on failures, and to early return on any non-success.

But let's leave that larger project for now, and (mostly) emulate what
were doing with the "exit(128)" before this change.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 234f1f993e1..166c6aaccb2 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2126,7 +2126,8 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet,
 	return run_command(&cp);
 }
 
-static int run_update_command(const struct update_data *ud, int subforce)
+static int run_update_command(const struct update_data *ud, int subforce,
+			      int *must_die_on_failure)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
@@ -2190,7 +2191,7 @@ static int run_update_command(const struct update_data *ud, int subforce)
 		}
 
 		if (ret == 128)
-			exit(ret);
+			*must_die_on_failure = 1;
 		return ret;
 	}
 
@@ -2222,7 +2223,8 @@ static int run_update_command(const struct update_data *ud, int subforce)
 	return 0;
 }
 
-static int run_update_procedure(const struct update_data *ud)
+static int run_update_procedure(const struct update_data *ud,
+				int *must_die_on_failure)
 {
 	int subforce = is_null_oid(&ud->suboid) || ud->force;
 
@@ -2249,7 +2251,7 @@ static int run_update_procedure(const struct update_data *ud)
 			    ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
-	return run_update_command(ud, subforce);
+	return run_update_command(ud, subforce, must_die_on_failure);
 }
 
 static const char *remote_submodule_branch(const char *path)
@@ -2386,7 +2388,8 @@ static void update_data_to_args(const struct update_data *update_data,
 				    "--no-single-branch");
 }
 
-static int update_submodule(struct update_data *update_data)
+static int update_submodule(struct update_data *update_data,
+			    int *must_die_on_failure)
 {
 	ensure_core_worktree(update_data->sm_path);
 
@@ -2422,9 +2425,15 @@ static int update_submodule(struct update_data *update_data)
 		free(remote_ref);
 	}
 
-	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force)
-		if (run_update_procedure(update_data))
+	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
+		int ret;
+
+		ret = run_update_procedure(update_data, must_die_on_failure);
+		if (*must_die_on_failure)
+			return ret;
+		if (ret)
 			return 1;
+	}
 
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
@@ -2440,14 +2449,13 @@ static int update_submodule(struct update_data *update_data)
 		prepare_submodule_repo_env(&cp.env);
 		update_data_to_args(&next, &cp.args);
 
-		/* die() if child process die()'d */
 		ret = run_command(&cp);
 		if (!ret)
 			return 0;
 		die_message(_("Failed to recurse into submodule path '%s'"),
 			    update_data->displaypath);
 		if (ret == 128)
-			exit(ret);
+			*must_die_on_failure = 1;
 		return ret;
 	}
 
@@ -2480,12 +2488,19 @@ static int update_submodules(struct update_data *update_data)
 
 	for (i = 0; i < suc.update_clone_nr; i++) {
 		struct update_clone_data ucd = suc.update_clone[i];
+		int must_die_on_failure = 0;
+		int code;
 
 		oidcpy(&update_data->oid, &ucd.oid);
 		update_data->just_cloned = ucd.just_cloned;
 		update_data->sm_path = ucd.sub->path;
 
-		if (update_submodule(update_data))
+		code = update_submodule(update_data, &must_die_on_failure);
+		if (code)
+			ret = code;
+		if (must_die_on_failure)
+			goto cleanup;
+		else if (code)
 			ret = 1;
 	}
 
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 26/33] submodule--helper: libify determine_submodule_update_strategy()
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (24 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 25/33] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 27/33] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
                       ` (7 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Libify the determine_submodule_update_strategy() by having it invoke
die_message() rather than die(), and returning the code die_message()
returns on failure.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 39 ++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 166c6aaccb2..2f78529736d 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1733,24 +1733,27 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	return 0;
 }
 
-static void determine_submodule_update_strategy(struct repository *r,
-						int just_cloned,
-						const char *path,
-						enum submodule_update_type update,
-						struct submodule_update_strategy *out)
+static int determine_submodule_update_strategy(struct repository *r,
+					       int just_cloned,
+					       const char *path,
+					       enum submodule_update_type update,
+					       struct submodule_update_strategy *out)
 {
 	const struct submodule *sub = submodule_from_path(r, null_oid(), path);
 	char *key;
 	const char *val;
+	int ret;
 
 	key = xstrfmt("submodule.%s.update", sub->name);
 
 	if (update) {
 		out->type = update;
 	} else if (!repo_config_get_string_tmp(r, key, &val)) {
-		if (parse_submodule_update_strategy(val, out) < 0)
-			die(_("Invalid update mode '%s' configured for submodule path '%s'"),
-				val, path);
+		if (parse_submodule_update_strategy(val, out) < 0) {
+			ret = die_message(_("Invalid update mode '%s' configured for submodule path '%s'"),
+					  val, path);
+			goto cleanup;
+		}
 	} else if (sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
 		if (sub->update_strategy.type == SM_UPDATE_COMMAND)
 			BUG("how did we read update = !command from .gitmodules?");
@@ -1765,7 +1768,10 @@ static void determine_submodule_update_strategy(struct repository *r,
 	     out->type == SM_UPDATE_NONE))
 		out->type = SM_UPDATE_CHECKOUT;
 
+	ret = 0;
+cleanup:
 	free(key);
+	return ret;
 }
 
 struct update_clone_data {
@@ -2391,14 +2397,22 @@ static void update_data_to_args(const struct update_data *update_data,
 static int update_submodule(struct update_data *update_data,
 			    int *must_die_on_failure)
 {
+	int ret;
+
 	ensure_core_worktree(update_data->sm_path);
 
 	update_data->displaypath = get_submodule_displaypath(
 		update_data->sm_path, update_data->prefix);
 
-	determine_submodule_update_strategy(the_repository, update_data->just_cloned,
-					    update_data->sm_path, update_data->update_default,
-					    &update_data->update_strategy);
+	ret = determine_submodule_update_strategy(the_repository,
+						  update_data->just_cloned,
+						  update_data->sm_path,
+						  update_data->update_default,
+						  &update_data->update_strategy);
+	if (ret) {
+		*must_die_on_failure = 1;
+		return ret;
+	}
 
 	if (update_data->just_cloned)
 		oidcpy(&update_data->suboid, null_oid());
@@ -2426,8 +2440,6 @@ static int update_submodule(struct update_data *update_data,
 	}
 
 	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
-		int ret;
-
 		ret = run_update_procedure(update_data, must_die_on_failure);
 		if (*must_die_on_failure)
 			return ret;
@@ -2438,7 +2450,6 @@ static int update_submodule(struct update_data *update_data,
 	if (update_data->recursive) {
 		struct child_process cp = CHILD_PROCESS_INIT;
 		struct update_data next = *update_data;
-		int ret;
 
 		next.prefix = NULL;
 		oidcpy(&next.oid, null_oid());
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 27/33] submodule--helper: libify "must_die_on_failure" code paths
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (25 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 26/33] submodule--helper: libify determine_submodule_update_strategy() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 28/33] submodule--helper update: don't override 'checkout' exit code Ævar Arnfjörð Bjarmason
                       ` (6 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

In preceding commits the codepaths around update_submodules() were
changed from using exit() or die() to ferrying up a
"must_die_on_failure" in the cases where we'd exit(), and in most
cases where we'd die().

We needed to do this this to ensure that we'd early exit or otherwise
abort the update_submodules() processing before it was completed.

Now that those preceding changes have shown that we've converted those
paths, we can remove the remaining "ret == 128" special-cases, leaving
the only such special-case in update_submodules(). I.e. we now know
after having gone through the various codepaths that we were only
returning 128 if we meant to early abort.

In update_submodules() we'll for now set any non-zero non-128 exit
codes to "1", but will start ferrying up the exit code as-is in a
subsequent commit.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 45 +++++++++++++------------------------
 1 file changed, 16 insertions(+), 29 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2f78529736d..8a086723ba6 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2132,8 +2132,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet,
 	return run_command(&cp);
 }
 
-static int run_update_command(const struct update_data *ud, int subforce,
-			      int *must_die_on_failure)
+static int run_update_command(const struct update_data *ud, int subforce)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
@@ -2196,8 +2195,6 @@ static int run_update_command(const struct update_data *ud, int subforce,
 			    ud->update_strategy.type);
 		}
 
-		if (ret == 128)
-			*must_die_on_failure = 1;
 		return ret;
 	}
 
@@ -2229,8 +2226,7 @@ static int run_update_command(const struct update_data *ud, int subforce,
 	return 0;
 }
 
-static int run_update_procedure(const struct update_data *ud,
-				int *must_die_on_failure)
+static int run_update_procedure(const struct update_data *ud)
 {
 	int subforce = is_null_oid(&ud->suboid) || ud->force;
 
@@ -2257,7 +2253,7 @@ static int run_update_procedure(const struct update_data *ud,
 			    ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
-	return run_update_command(ud, subforce, must_die_on_failure);
+	return run_update_command(ud, subforce);
 }
 
 static const char *remote_submodule_branch(const char *path)
@@ -2394,8 +2390,7 @@ static void update_data_to_args(const struct update_data *update_data,
 				    "--no-single-branch");
 }
 
-static int update_submodule(struct update_data *update_data,
-			    int *must_die_on_failure)
+static int update_submodule(struct update_data *update_data)
 {
 	int ret;
 
@@ -2409,10 +2404,8 @@ static int update_submodule(struct update_data *update_data,
 						  update_data->sm_path,
 						  update_data->update_default,
 						  &update_data->update_strategy);
-	if (ret) {
-		*must_die_on_failure = 1;
+	if (ret)
 		return ret;
-	}
 
 	if (update_data->just_cloned)
 		oidcpy(&update_data->suboid, null_oid());
@@ -2440,11 +2433,9 @@ static int update_submodule(struct update_data *update_data,
 	}
 
 	if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) {
-		ret = run_update_procedure(update_data, must_die_on_failure);
-		if (*must_die_on_failure)
-			return ret;
+		ret = run_update_procedure(update_data);
 		if (ret)
-			return 1;
+			return ret;
 	}
 
 	if (update_data->recursive) {
@@ -2461,12 +2452,9 @@ static int update_submodule(struct update_data *update_data,
 		update_data_to_args(&next, &cp.args);
 
 		ret = run_command(&cp);
-		if (!ret)
-			return 0;
-		die_message(_("Failed to recurse into submodule path '%s'"),
-			    update_data->displaypath);
-		if (ret == 128)
-			*must_die_on_failure = 1;
+		if (ret)
+			die_message(_("Failed to recurse into submodule path '%s'"),
+				    update_data->displaypath);
 		return ret;
 	}
 
@@ -2499,20 +2487,19 @@ static int update_submodules(struct update_data *update_data)
 
 	for (i = 0; i < suc.update_clone_nr; i++) {
 		struct update_clone_data ucd = suc.update_clone[i];
-		int must_die_on_failure = 0;
 		int code;
 
 		oidcpy(&update_data->oid, &ucd.oid);
 		update_data->just_cloned = ucd.just_cloned;
 		update_data->sm_path = ucd.sub->path;
 
-		code = update_submodule(update_data, &must_die_on_failure);
-		if (code)
-			ret = code;
-		if (must_die_on_failure)
+		code = update_submodule(update_data);
+		if (!code)
+			continue;
+		ret = code;
+		if (ret == 128)
 			goto cleanup;
-		else if (code)
-			ret = 1;
+		ret = 1;
 	}
 
 cleanup:
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 28/33] submodule--helper update: don't override 'checkout' exit code
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (26 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 27/33] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 29/33] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
                       ` (5 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

When "git submodule update" runs it might call "checkout", "merge",
"rebase", or a custom command. Ever since run_update_command() was
added in c51f8f94e5b (submodule--helper: run update procedures from C,
2021-08-24) we'd either exit immediately if the
"submodule.<name>.update" method failed, or in the case of "checkout"
continue trying to update other submodules.

This code used to use the magical "2" return code, but in
55b3f12cb54 (submodule update: use die_message(), 2022-03-15) it was
made to exit(128), which in preceding commits has been changed to
return that 128 code to the top-level.

Let's "libify" this code even more by not having it arbitrarily
override the return code. In practice this doesn't change anything as
the code "git checkout" would return on any normal failure is "1", but
we'll now in principle properly abort the operation if "git checkout"
were to exit with 128.

It would make sense to follow-up this change with a change to allow
the "submodule.<name>.update = !..." (SM_UPDATE_COMMAND) method the
same liberties as "checkout", and perhaps to do the same with a failed
"merge" or "rebase". But let's leave that for now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 8a086723ba6..4252b6d864c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2136,6 +2136,7 @@ static int run_update_command(const struct update_data *ud, int subforce)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 	char *oid = oid_to_hex(&ud->oid);
+	int ret;
 
 	switch (ud->update_strategy.type) {
 	case SM_UPDATE_CHECKOUT:
@@ -2168,15 +2169,12 @@ static int run_update_command(const struct update_data *ud, int subforce)
 
 	cp.dir = xstrdup(ud->sm_path);
 	prepare_submodule_repo_env(&cp.env);
-	if (run_command(&cp)) {
-		int ret;
-
+	if ((ret = run_command(&cp))) {
 		switch (ud->update_strategy.type) {
 		case SM_UPDATE_CHECKOUT:
 			die_message(_("Unable to checkout '%s' in submodule path '%s'"),
 				    oid, ud->displaypath);
-			/* the command failed, but update must continue */
-			ret = 1;
+			/* No "ret" assignment, use "git checkout"'s */
 			break;
 		case SM_UPDATE_REBASE:
 			ret = die_message(_("Unable to rebase '%s' in submodule path '%s'"),
@@ -2499,7 +2497,6 @@ static int update_submodules(struct update_data *update_data)
 		ret = code;
 		if (ret == 128)
 			goto cleanup;
-		ret = 1;
 	}
 
 cleanup:
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 29/33] submodule--helper: libify "must_die_on_failure" code paths (for die)
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (27 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 28/33] submodule--helper update: don't override 'checkout' exit code Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 30/33] submodule--helper: check repo{_submodule,}_init() return values Ævar Arnfjörð Bjarmason
                       ` (4 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Continue the libification of codepaths that previously relied on
"must_die_on_failure". In these cases we've always been early aborting
by calling die(), but as we know that these codepaths will properly
handle return codes of 128 to mean an early abort let's have them use
die_message() instead.

This still isn't a complete migration away from die() for these
codepaths, in particular this code in update_submodule() will still call die() in some cases:

	char *remote_name = get_default_remote_submodule(update_data->sm_path);
	const char *branch = remote_submodule_branch(update_data->sm_path);

But as that code is used by other callers than the "update" code let's
leave converting it for a subsequent commit.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 4252b6d864c..b99fb7a244e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2246,9 +2246,9 @@ static int run_update_procedure(const struct update_data *ud)
 		 */
 		if (!is_tip_reachable(ud->sm_path, &ud->oid) &&
 		    fetch_in_submodule(ud->sm_path, ud->depth, ud->quiet, &ud->oid))
-			die(_("Fetched in submodule path '%s', but it did not "
-			      "contain %s. Direct fetching of that commit failed."),
-			    ud->displaypath, oid_to_hex(&ud->oid));
+			return die_message(_("Fetched in submodule path '%s', but it did not "
+					     "contain %s. Direct fetching of that commit failed."),
+					   ud->displaypath, oid_to_hex(&ud->oid));
 	}
 
 	return run_update_command(ud, subforce);
@@ -2292,13 +2292,14 @@ static const char *remote_submodule_branch(const char *path)
 	return branch;
 }
 
-static void ensure_core_worktree(const char *path)
+static int ensure_core_worktree(const char *path)
 {
 	const char *cw;
 	struct repository subrepo;
 
 	if (repo_submodule_init(&subrepo, the_repository, path, null_oid()))
-		die(_("could not get a repository handle for submodule '%s'"), path);
+		return die_message(_("could not get a repository handle for submodule '%s'"),
+				   path);
 
 	if (!repo_config_get_string_tmp(&subrepo, "core.worktree", &cw)) {
 		char *cfg_file, *abs_path;
@@ -2316,6 +2317,8 @@ static void ensure_core_worktree(const char *path)
 		free(abs_path);
 		strbuf_release(&sb);
 	}
+
+	return 0;
 }
 
 static const char *submodule_update_type_to_label(enum submodule_update_type type)
@@ -2392,7 +2395,9 @@ static int update_submodule(struct update_data *update_data)
 {
 	int ret;
 
-	ensure_core_worktree(update_data->sm_path);
+	ret = ensure_core_worktree(update_data->sm_path);
+	if (ret)
+		return ret;
 
 	update_data->displaypath = get_submodule_displaypath(
 		update_data->sm_path, update_data->prefix);
@@ -2408,8 +2413,8 @@ static int update_submodule(struct update_data *update_data)
 	if (update_data->just_cloned)
 		oidcpy(&update_data->suboid, null_oid());
 	else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid))
-		die(_("Unable to find current revision in submodule path '%s'"),
-			update_data->displaypath);
+		return die_message(_("Unable to find current revision in submodule path '%s'"),
+				   update_data->displaypath);
 
 	if (update_data->remote) {
 		char *remote_name = get_default_remote_submodule(update_data->sm_path);
@@ -2419,13 +2424,13 @@ static int update_submodule(struct update_data *update_data)
 		if (!update_data->nofetch) {
 			if (fetch_in_submodule(update_data->sm_path, update_data->depth,
 					      0, NULL))
-				die(_("Unable to fetch in submodule path '%s'"),
-				    update_data->sm_path);
+				return die_message(_("Unable to fetch in submodule path '%s'"),
+						   update_data->sm_path);
 		}
 
 		if (resolve_gitlink_ref(update_data->sm_path, remote_ref, &update_data->oid))
-			die(_("Unable to find %s revision in submodule path '%s'"),
-			    remote_ref, update_data->sm_path);
+			return die_message(_("Unable to find %s revision in submodule path '%s'"),
+					   remote_ref, update_data->sm_path);
 
 		free(remote_ref);
 	}
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 30/33] submodule--helper: check repo{_submodule,}_init() return values
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (28 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 29/33] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 31/33] submodule--helper: libify more "die" paths for module_update() Ævar Arnfjörð Bjarmason
                       ` (3 subsequent siblings)
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Fix code added in ce125d431aa (submodule: extract path to submodule
gitdir func, 2021-09-15) and a77c3fcb5ec (submodule--helper: get
remote names from any repository, 2022-03-04) which failed to check
the return values of repo_init() and repo_submodule_init(). If we
failed to initialize the repository or submodule we could segfault
when trying to access the invalid repository structs.

Let's also check that these were the only such logic errors in the
codebase by making use of the "warn_unused_result" attribute. This is
valid as of GCC 3.4.0 (and clang will catch it via its faking of
__GNUC__ ).

As the comment being added to git-compat-util.h we're piggy-backing on
the LAST_ARG_MUST_BE_NULL version check out of lazyness. See
9fe3edc47f1 (Add the LAST_ARG_MUST_BE_NULL macro, 2013-07-18) for its
addition. The marginal benefit of covering gcc 3.4.0..4.0.0 is
near-zero (or zero) at this point. It mostly matters that we catch
this somewhere.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 9 +++++++--
 git-compat-util.h           | 3 +++
 repository.h                | 3 +++
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index b99fb7a244e..dfd71f0f2b2 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -63,7 +63,10 @@ static char *get_default_remote_submodule(const char *module_path)
 {
 	struct repository subrepo;
 
-	repo_submodule_init(&subrepo, the_repository, module_path, null_oid());
+	if (repo_submodule_init(&subrepo, the_repository, module_path,
+				null_oid()) < 0)
+		die(_("could not get a repository handle for submodule '%s'"),
+		    module_path);
 	return repo_get_default_remote(&subrepo);
 }
 
@@ -1483,7 +1486,9 @@ static int add_possible_reference_from_superproject(
 		struct strbuf err = STRBUF_INIT;
 		strbuf_add(&sb, odb->path, len);
 
-		repo_init(&alternate, sb.buf, NULL);
+		if (repo_init(&alternate, sb.buf, NULL) < 0)
+			die(_("could not get a repository handle for gitdir '%s'"),
+			    sb.buf);
 
 		/*
 		 * We need to end the new path with '/' to mark it as a dir,
diff --git a/git-compat-util.h b/git-compat-util.h
index 4e51a1c48bc..7ebae122d40 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -569,8 +569,11 @@ static inline int git_has_dir_sep(const char *path)
 /* The sentinel attribute is valid from gcc version 4.0 */
 #if defined(__GNUC__) && (__GNUC__ >= 4)
 #define LAST_ARG_MUST_BE_NULL __attribute__((sentinel))
+/* warn_unused_result exists as of gcc 3.4.0, but be lazy and check 4.0 */
+#define RESULT_MUST_BE_USED __attribute__ ((warn_unused_result))
 #else
 #define LAST_ARG_MUST_BE_NULL
+#define RESULT_MUST_BE_USED
 #endif
 
 #define MAYBE_UNUSED __attribute__((__unused__))
diff --git a/repository.h b/repository.h
index 797f471cce9..24316ac944e 100644
--- a/repository.h
+++ b/repository.h
@@ -1,6 +1,7 @@
 #ifndef REPOSITORY_H
 #define REPOSITORY_H
 
+#include "git-compat-util.h"
 #include "path.h"
 
 struct config_set;
@@ -186,6 +187,7 @@ void repo_set_gitdir(struct repository *repo, const char *root,
 void repo_set_worktree(struct repository *repo, const char *path);
 void repo_set_hash_algo(struct repository *repo, int algo);
 void initialize_the_repository(void);
+RESULT_MUST_BE_USED
 int repo_init(struct repository *r, const char *gitdir, const char *worktree);
 
 /*
@@ -197,6 +199,7 @@ int repo_init(struct repository *r, const char *gitdir, const char *worktree);
  * Return 0 upon success and a non-zero value upon failure.
  */
 struct object_id;
+RESULT_MUST_BE_USED
 int repo_submodule_init(struct repository *subrepo,
 			struct repository *superproject,
 			const char *path,
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 31/33] submodule--helper: libify more "die" paths for module_update()
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (29 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 30/33] submodule--helper: check repo{_submodule,}_init() return values Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-09-01 20:55       ` Glen Choo
  2022-08-31 23:18     ` [PATCH v4 32/33] submodule--helper: libify even " Ævar Arnfjörð Bjarmason
                       ` (2 subsequent siblings)
  33 siblings, 1 reply; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

As noted in a preceding commit the get_default_remote_submodule() and
remote_submodule_branch() functions would invoke die(), and thus leave
update_submodule() only partially lib-ified. Let's address the former
of those cases.

Change the functions to return an int exit code (non-zero on failure),
while leaving the get_default_remote() function for the callers that
still want the die() semantics.

This change addresses 1/2 of the "die" issue in these two lines in
update_submodule():

	char *remote_name = get_default_remote_submodule(update_data->sm_path);
	const char *branch = remote_submodule_branch(update_data->sm_path);

We can safely remove the "!default_remote" case from sync_submodule(),
because our get_default_remote_submodule() function now returns a
die_message() on failure, so we can have it an dother callers check if
the exit code should be non-zero instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 58 +++++++++++++++++++++++--------------
 1 file changed, 37 insertions(+), 21 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index dfd71f0f2b2..9de3a3c921a 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -31,48 +31,57 @@
 typedef void (*each_submodule_fn)(const struct cache_entry *list_item,
 				  void *cb_data);
 
-static char *repo_get_default_remote(struct repository *repo)
+static int repo_get_default_remote(struct repository *repo, char **default_remote)
 {
-	char *dest = NULL, *ret;
+	char *dest = NULL;
 	struct strbuf sb = STRBUF_INIT;
 	struct ref_store *store = get_main_ref_store(repo);
 	const char *refname = refs_resolve_ref_unsafe(store, "HEAD", 0, NULL,
 						      NULL);
 
 	if (!refname)
-		die(_("No such ref: %s"), "HEAD");
+		return die_message(_("No such ref: %s"), "HEAD");
 
 	/* detached HEAD */
-	if (!strcmp(refname, "HEAD"))
-		return xstrdup("origin");
+	if (!strcmp(refname, "HEAD")) {
+		*default_remote = xstrdup("origin");
+		return 0;
+	}
 
 	if (!skip_prefix(refname, "refs/heads/", &refname))
-		die(_("Expecting a full ref name, got %s"), refname);
+		return die_message(_("Expecting a full ref name, got %s"),
+				   refname);
 
 	strbuf_addf(&sb, "branch.%s.remote", refname);
 	if (repo_config_get_string(repo, sb.buf, &dest))
-		ret = xstrdup("origin");
+		*default_remote = xstrdup("origin");
 	else
-		ret = dest;
+		*default_remote = dest;
 
 	strbuf_release(&sb);
-	return ret;
+	return 0;
 }
 
-static char *get_default_remote_submodule(const char *module_path)
+static int get_default_remote_submodule(const char *module_path, char **default_remote)
 {
 	struct repository subrepo;
 
 	if (repo_submodule_init(&subrepo, the_repository, module_path,
 				null_oid()) < 0)
-		die(_("could not get a repository handle for submodule '%s'"),
-		    module_path);
-	return repo_get_default_remote(&subrepo);
+		return die_message(_("could not get a repository handle for submodule '%s'"),
+				   module_path);
+	return repo_get_default_remote(&subrepo, default_remote);
 }
 
 static char *get_default_remote(void)
 {
-	return repo_get_default_remote(the_repository);
+	char *default_remote;
+	int code = repo_get_default_remote(the_repository, &default_remote);
+
+	if (code)
+		exit(code);
+
+	return default_remote;
 }
 
 static char *resolve_relative_url(const char *rel_url, const char *up_path, int quiet)
@@ -1159,6 +1168,7 @@ static void sync_submodule(const char *path, const char *prefix,
 	char *sub_origin_url, *super_config_url, *displaypath, *default_remote;
 	struct strbuf sb = STRBUF_INIT;
 	char *sub_config_path = NULL;
+	int code;
 
 	if (!is_submodule_active(the_repository, path))
 		return;
@@ -1198,10 +1208,9 @@ static void sync_submodule(const char *path, const char *prefix,
 		goto cleanup;
 
 	strbuf_reset(&sb);
-	default_remote = get_default_remote_submodule(path);
-	if (!default_remote)
-		die(_("failed to get the default remote for submodule '%s'"),
-		      path);
+	code = get_default_remote_submodule(path, &default_remote);
+	if (code)
+		exit(code);
 
 	remote_key = xstrfmt("remote.%s.url", default_remote);
 	free(default_remote);
@@ -2422,9 +2431,16 @@ static int update_submodule(struct update_data *update_data)
 				   update_data->displaypath);
 
 	if (update_data->remote) {
-		char *remote_name = get_default_remote_submodule(update_data->sm_path);
-		const char *branch = remote_submodule_branch(update_data->sm_path);
-		char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+		char *remote_name;
+		const char *branch;
+		char *remote_ref;
+		int code;
+
+		code = get_default_remote_submodule(update_data->sm_path, &remote_name);
+		if (code)
+			return code;
+		branch = remote_submodule_branch(update_data->sm_path);
+		remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
 
 		if (!update_data->nofetch) {
 			if (fetch_in_submodule(update_data->sm_path, update_data->depth,
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 32/33] submodule--helper: libify even more "die" paths for module_update()
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (30 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 31/33] submodule--helper: libify more "die" paths for module_update() Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-08-31 23:18     ` [PATCH v4 33/33] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
  2022-09-01 20:59     ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Glen Choo
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

As noted in a preceding commit the get_default_remote_submodule() and
remote_submodule_branch() functions would invoke die(), and thus leave
update_submodule() only partially lib-ified. We've addressed the
former of those in a preceding commit, let's now address the latter.

In addition to lib-ifying the function this fixes a potential (but
obscure) segfault introduced by a logic error in
1012a5cbc3f (submodule--helper run-update-procedure: learn --remote,
2022-03-04):

We were assuming that remote_submodule_branch() would always return
non-NULL, but if the submodule_from_path() call in that function fails
we'll return NULL. See its introduction in
92bbe7ccf1f (submodule--helper: add remote-branch helper,
2016-08-03). I.e. we'd previously have segfaulted in the xstrfmt()
call in update_submodule() seen in the context.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 41 ++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 9de3a3c921a..3f822eac3a1 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2268,42 +2268,49 @@ static int run_update_procedure(const struct update_data *ud)
 	return run_update_command(ud, subforce);
 }
 
-static const char *remote_submodule_branch(const char *path)
+static int remote_submodule_branch(const char *path, const char **branch)
 {
 	const struct submodule *sub;
-	const char *branch = NULL;
 	char *key;
+	*branch = NULL;
 
 	sub = submodule_from_path(the_repository, null_oid(), path);
 	if (!sub)
-		return NULL;
+		return die_message(_("could not initialize submodule at path '%s'"),
+				   path);
 
 	key = xstrfmt("submodule.%s.branch", sub->name);
-	if (repo_config_get_string_tmp(the_repository, key, &branch))
-		branch = sub->branch;
+	if (repo_config_get_string_tmp(the_repository, key, branch))
+		*branch = sub->branch;
 	free(key);
 
-	if (!branch)
-		return "HEAD";
+	if (!*branch) {
+		*branch = "HEAD";
+		return 0;
+	}
 
-	if (!strcmp(branch, ".")) {
+	if (!strcmp(*branch, ".")) {
 		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
 
 		if (!refname)
-			die(_("No such ref: %s"), "HEAD");
+			return die_message(_("No such ref: %s"), "HEAD");
 
 		/* detached HEAD */
 		if (!strcmp(refname, "HEAD"))
-			die(_("Submodule (%s) branch configured to inherit "
-			      "branch from superproject, but the superproject "
-			      "is not on any branch"), sub->name);
+			return die_message(_("Submodule (%s) branch configured to inherit "
+					     "branch from superproject, but the superproject "
+					     "is not on any branch"), sub->name);
 
 		if (!skip_prefix(refname, "refs/heads/", &refname))
-			die(_("Expecting a full ref name, got %s"), refname);
-		return refname;
+			return die_message(_("Expecting a full ref name, got %s"),
+					   refname);
+
+		*branch = refname;
+		return 0;
 	}
 
-	return branch;
+	/* Our "branch" is coming from repo_config_get_string_tmp() */
+	return 0;
 }
 
 static int ensure_core_worktree(const char *path)
@@ -2439,7 +2446,9 @@ static int update_submodule(struct update_data *update_data)
 		code = get_default_remote_submodule(update_data->sm_path, &remote_name);
 		if (code)
 			return code;
-		branch = remote_submodule_branch(update_data->sm_path);
+		code = remote_submodule_branch(update_data->sm_path, &branch);
+		if (code)
+			return code;
 		remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
 
 		if (!update_data->nofetch) {
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* [PATCH v4 33/33] submodule--helper: fix bad config API usage
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (31 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 32/33] submodule--helper: libify even " Ævar Arnfjörð Bjarmason
@ 2022-08-31 23:18     ` Ævar Arnfjörð Bjarmason
  2022-09-01 20:59     ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Glen Choo
  33 siblings, 0 replies; 142+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-08-31 23:18 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Glen Choo, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Fix bad config API usage added in a452128a36c (submodule--helper:
introduce add-config subcommand, 2021-08-06). After
git_config_get_string() returns successfully we know the "char **dest"
will be non-NULL.

A coccinelle patch that transforms this turns up a couple of other
such issues, one in fetch-pack.c, and another in upload-pack.c:

	@@
	identifier F =~ "^(repo|git)_config_get_string(_tmp)?$";
	identifier V;
	@@
	  !F(..., &V)
	- && (V)

But let's focus narrowly on submodule--helper for now, we can fix
those some other time.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/submodule--helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 3f822eac3a1..c4149f11e7f 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -3110,7 +3110,7 @@ static void configure_added_submodule(struct add_data *add_data)
 	 * is_submodule_active(), since that function needs to find
 	 * out the value of "submodule.active" again anyway.
 	 */
-	if (!git_config_get_string("submodule.active", &val) && val) {
+	if (!git_config_get_string("submodule.active", &val)) {
 		/*
 		 * If the submodule being added isn't already covered by the
 		 * current configured pathspec, set the submodule's active flag
-- 
2.37.3.1420.g76f8a3d556c


^ permalink raw reply related	[flat|nested] 142+ messages in thread

* Re: [PATCH v4 31/33] submodule--helper: libify more "die" paths for module_update()
  2022-08-31 23:18     ` [PATCH v4 31/33] submodule--helper: libify more "die" paths for module_update() Ævar Arnfjörð Bjarmason
@ 2022-09-01 20:55       ` Glen Choo
  0 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-09-01 20:55 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason         <avarab@gmail.com> writes:

> As noted in a preceding commit the get_default_remote_submodule() and
> remote_submodule_branch() functions would invoke die(), and thus leave
> update_submodule() only partially lib-ified. Let's address the former
> of those cases.
>
> Change the functions to return an int exit code (non-zero on failure),
> while leaving the get_default_remote() function for the callers that
> still want the die() semantics.
>
> This change addresses 1/2 of the "die" issue in these two lines in
> update_submodule():
>
> 	char *remote_name = get_default_remote_submodule(update_data->sm_path);
> 	const char *branch = remote_submodule_branch(update_data->sm_path);
>
> We can safely remove the "!default_remote" case from sync_submodule(),
> because our get_default_remote_submodule() function now returns a
> die_message() on failure, so we can have it an dother callers check if

If I'm reading this correctly, s/an dother/and other ?

> the exit code should be non-zero instead.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/submodule--helper.c | 58 +++++++++++++++++++++++--------------
>  1 file changed, 37 insertions(+), 21 deletions(-)
>
> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> index dfd71f0f2b2..9de3a3c921a 100644
> --- a/builtin/submodule--helper.c
> +++ b/builtin/submodule--helper.c
> @@ -31,48 +31,57 @@
>  typedef void (*each_submodule_fn)(const struct cache_entry *list_item,
>  				  void *cb_data);
>  
> -static char *repo_get_default_remote(struct repository *repo)
> +static int repo_get_default_remote(struct repository *repo, char **default_remote)
>  {
> -	char *dest = NULL, *ret;
> +	char *dest = NULL;
>  	struct strbuf sb = STRBUF_INIT;
>  	struct ref_store *store = get_main_ref_store(repo);
>  	const char *refname = refs_resolve_ref_unsafe(store, "HEAD", 0, NULL,
>  						      NULL);
>  
>  	if (!refname)
> -		die(_("No such ref: %s"), "HEAD");
> +		return die_message(_("No such ref: %s"), "HEAD");
>  
>  	/* detached HEAD */
> -	if (!strcmp(refname, "HEAD"))
> -		return xstrdup("origin");
> +	if (!strcmp(refname, "HEAD")) {
> +		*default_remote = xstrdup("origin");
> +		return 0;
> +	}
>  
>  	if (!skip_prefix(refname, "refs/heads/", &refname))
> -		die(_("Expecting a full ref name, got %s"), refname);
> +		return die_message(_("Expecting a full ref name, got %s"),
> +				   refname);
>  
>  	strbuf_addf(&sb, "branch.%s.remote", refname);
>  	if (repo_config_get_string(repo, sb.buf, &dest))
> -		ret = xstrdup("origin");
> +		*default_remote = xstrdup("origin");
>  	else
> -		ret = dest;
> +		*default_remote = dest;
>  
>  	strbuf_release(&sb);
> -	return ret;
> +	return 0;
>  }
>  
> -static char *get_default_remote_submodule(const char *module_path)
> +static int get_default_remote_submodule(const char *module_path, char **default_remote)
>  {
>  	struct repository subrepo;
>  
>  	if (repo_submodule_init(&subrepo, the_repository, module_path,
>  				null_oid()) < 0)
> -		die(_("could not get a repository handle for submodule '%s'"),
> -		    module_path);
> -	return repo_get_default_remote(&subrepo);
> +		return die_message(_("could not get a repository handle for submodule '%s'"),
> +				   module_path);
> +	return repo_get_default_remote(&subrepo, default_remote);
>  }
>  
>  static char *get_default_remote(void)
>  {
> -	return repo_get_default_remote(the_repository);
> +	char *default_remote;
> +	int code = repo_get_default_remote(the_repository, &default_remote);
> +
> +	if (code)
> +		exit(code);
> +
> +	return default_remote;
>  }
>  
>  static char *resolve_relative_url(const char *rel_url, const char *up_path, int quiet)
> @@ -1159,6 +1168,7 @@ static void sync_submodule(const char *path, const char *prefix,
>  	char *sub_origin_url, *super_config_url, *displaypath, *default_remote;
>  	struct strbuf sb = STRBUF_INIT;
>  	char *sub_config_path = NULL;
> +	int code;
>  
>  	if (!is_submodule_active(the_repository, path))
>  		return;
> @@ -1198,10 +1208,9 @@ static void sync_submodule(const char *path, const char *prefix,
>  		goto cleanup;
>  
>  	strbuf_reset(&sb);
> -	default_remote = get_default_remote_submodule(path);
> -	if (!default_remote)
> -		die(_("failed to get the default remote for submodule '%s'"),
> -		      path);
> +	code = get_default_remote_submodule(path, &default_remote);
> +	if (code)
> +		exit(code);
>  
>  	remote_key = xstrfmt("remote.%s.url", default_remote);
>  	free(default_remote);
> @@ -2422,9 +2431,16 @@ static int update_submodule(struct update_data *update_data)
>  				   update_data->displaypath);
>  
>  	if (update_data->remote) {
> -		char *remote_name = get_default_remote_submodule(update_data->sm_path);
> -		const char *branch = remote_submodule_branch(update_data->sm_path);
> -		char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
> +		char *remote_name;
> +		const char *branch;
> +		char *remote_ref;
> +		int code;
> +
> +		code = get_default_remote_submodule(update_data->sm_path, &remote_name);
> +		if (code)
> +			return code;
> +		branch = remote_submodule_branch(update_data->sm_path);
> +		remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
>  
>  		if (!update_data->nofetch) {
>  			if (fetch_in_submodule(update_data->sm_path, update_data->depth,
> -- 
> 2.37.3.1420.g76f8a3d556c

^ permalink raw reply	[flat|nested] 142+ messages in thread

* Re: [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep
  2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
                       ` (32 preceding siblings ...)
  2022-08-31 23:18     ` [PATCH v4 33/33] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
@ 2022-09-01 20:59     ` Glen Choo
  33 siblings, 0 replies; 142+ messages in thread
From: Glen Choo @ 2022-09-01 20:59 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git
  Cc: Junio C Hamano, Atharva Raykar, Prathamesh Chavan,
	Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> This series is a "prep" series for the meaty leak fixes for
> submodule--helper, see [1] (which will be re-rolled on top of this
> v3). The v7 re-roll will be at [2].
>
> Changes since v3:
>
>  * Addressed (hopefully) all of the small feedback, just typo fixes &
>    commit message clarifications.
>
>  * Marked a parameter as "const", which helps reason about subsequent
>    things in the "leak" series.
>
> Hopefully this is ready to proceed past "seen" in its current form...
>
> 1. https://lore.kernel.org/git/cover-v3-00.32-00000000000-20220821T130231Z-avarab@gmail.com/
> 2. https://lore.kernel.org/git/cover-v7-00.17-00000000000-20220831T231003Z-avarab@gmail.com

Thanks!

I still have no comments on the attributes and macros on 30/33. Others
may want to take look at that.

I spotted one typo in 31/33's commit message, but maybe that can be
fixed on patch application.

Otherwise, everything else LGTM.

  Reviewed-by: Glen Choo <chooglen@google.com>

^ permalink raw reply	[flat|nested] 142+ messages in thread

end of thread, other threads:[~2022-09-01 21:00 UTC | newest]

Thread overview: 142+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-28 16:16 [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
2022-07-28 16:16 ` [PATCH 01/20] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
2022-07-29 20:30   ` Glen Choo
2022-07-28 16:16 ` [PATCH 02/20] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
2022-07-28 16:16 ` [PATCH 03/20] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
2022-07-28 16:16 ` [PATCH 04/20] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
2022-07-29 21:31   ` Glen Choo
2022-07-28 16:16 ` [PATCH 05/20] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
2022-07-28 16:16 ` [PATCH 06/20] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
2022-07-29 21:45   ` Glen Choo
2022-07-28 16:16 ` [PATCH 07/20] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
2022-07-29 21:55   ` Glen Choo
2022-07-28 16:16 ` [PATCH 08/20] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
2022-07-29 21:58   ` Glen Choo
2022-07-28 16:16 ` [PATCH 09/20] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
2022-07-28 16:16 ` [PATCH 10/20] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
2022-07-28 16:16 ` [PATCH 11/20] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
2022-07-28 16:16 ` [PATCH 12/20] submodule--helper: convert a strbuf_detach() to xstrfmt() Ævar Arnfjörð Bjarmason
2022-07-28 16:16 ` [PATCH 13/20] submodule--helper: stop conflating "sb" in clone_submodule() Ævar Arnfjörð Bjarmason
2022-07-29 17:08   ` Glen Choo
2022-07-28 16:16 ` [PATCH 14/20] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
2022-07-29 22:09   ` Glen Choo
2022-08-01 15:05     ` Ævar Arnfjörð Bjarmason
2022-07-28 16:17 ` [PATCH 15/20] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
2022-07-28 16:17 ` [PATCH 16/20] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
2022-07-28 16:17 ` [PATCH 17/20] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
2022-07-28 16:17 ` [PATCH 18/20] submodule--helper: add skeleton "goto cleanup" to update_submodule() Ævar Arnfjörð Bjarmason
2022-07-28 16:17 ` [PATCH 19/20] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
2022-07-29 22:23   ` Glen Choo
2022-07-28 16:17 ` [PATCH 20/20] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
2022-07-29 22:52 ` [PATCH 00/20] submodule--helper: add tests, rm dead code, refactor & leak prep Glen Choo
2022-08-02 15:45 ` [PATCH v2 00/28] " Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 01/28] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
2022-08-02 22:30     ` Glen Choo
2022-08-02 15:45   ` [PATCH v2 02/28] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 03/28] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 04/28] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 05/28] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 06/28] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 07/28] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 08/28] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
2022-08-02 22:32     ` Glen Choo
2022-08-02 15:45   ` [PATCH v2 09/28] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 10/28] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 11/28] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 12/28] submodule--helper: use xstrfmt() in clone_submodule() Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 13/28] submodule--helper: move "sb" in clone_submodule() to its own scope Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 14/28] submodule--helper: pass a "const struct module_clone_data" to clone_submodule() Ævar Arnfjörð Bjarmason
2022-08-02 15:45   ` [PATCH v2 15/28] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 16/28] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 17/28] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 18/28] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 19/28] submodule--helper: return "ret", not "1" from update_submodule() Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 20/28] submodule--helper: add missing braces to "else" arm Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 21/28] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
2022-08-02 23:08     ` Glen Choo
2022-08-02 15:46   ` [PATCH v2 22/28] submodule--helper: move submodule_strategy_to_string() to only user Ævar Arnfjörð Bjarmason
2022-08-02 23:30     ` Glen Choo
2022-08-03 13:06       ` Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 23/28] submodule--helper: use "code" in run_update_command() Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 24/28] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 25/28] submodule--helper: libify determine_submodule_update_strategy() Ævar Arnfjörð Bjarmason
2022-08-02 15:46   ` [PATCH v2 26/28] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
2022-08-03  4:37     ` Glen Choo
2022-08-02 15:46   ` [PATCH v2 27/28] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
2022-08-03  4:32     ` Glen Choo
2022-08-02 15:46   ` [PATCH v2 28/28] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
2022-08-21 13:57 ` [PATCH v3 00/32] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 01/32] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
2022-08-23 22:42     ` Glen Choo
2022-08-21 13:57   ` [PATCH v3 02/32] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 03/32] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 04/32] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 05/32] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 06/32] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 07/32] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 08/32] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 09/32] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 10/32] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 11/32] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 12/32] submodule--helper: use xstrfmt() in clone_submodule() Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 13/32] submodule--helper: move "sb" in clone_submodule() to its own scope Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 14/32] submodule--helper: add "const" to passed "module_clone_data" Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 15/32] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 16/32] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 17/32] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
2022-08-21 16:12     ` Eric Sunshine
2022-08-21 13:57   ` [PATCH v3 18/32] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 19/32] submodule--helper: return "ret", not "1" from update_submodule() Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 20/32] submodule--helper: add missing braces to "else" arm Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 21/32] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 22/32] submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string() Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 23/32] submodule--helper: use "code" in run_update_command() Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 24/32] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 25/32] submodule--helper: libify determine_submodule_update_strategy() Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 26/32] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 27/32] submodule--helper update: don't override 'checkout' exit code Ævar Arnfjörð Bjarmason
2022-08-21 13:57   ` [PATCH v3 28/32] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
2022-08-23 23:27     ` Glen Choo
2022-08-21 13:57   ` [PATCH v3 29/32] submodule--helper: check repo{_submodule,}_init() return values Ævar Arnfjörð Bjarmason
2022-08-23 23:38     ` Glen Choo
2022-08-21 13:57   ` [PATCH v3 30/32] submodule--helper: libify more "die" paths for module_update() Ævar Arnfjörð Bjarmason
2022-08-24  0:07     ` Glen Choo
2022-08-21 13:57   ` [PATCH v3 31/32] submodule--helper: libify even " Ævar Arnfjörð Bjarmason
2022-08-24  0:12     ` Glen Choo
2022-08-21 13:57   ` [PATCH v3 32/32] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
2022-08-31 23:17   ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 01/33] submodule tests: test usage behavior Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 02/33] submodule tests: test for "add <repository> <abs-path>" Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 03/33] submodule--helper: remove unused "name" helper Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 04/33] submodule--helper: remove unused "list" helper Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 05/33] test-tool submodule-config: remove unused "--url" handling Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 06/33] submodule--helper: move "is-active" to a test-tool Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 07/33] submodule--helper: move "check-name" " Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 08/33] submodule--helper: move "resolve-relative-url-test" " Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 09/33] submodule--helper style: don't separate declared variables with \n\n Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 10/33] submodule--helper style: add \n\n after variable declarations Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 11/33] submodule--helper: replace memset() with { 0 }-initialization Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 12/33] submodule--helper: use xstrfmt() in clone_submodule() Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 13/33] submodule--helper: move "sb" in clone_submodule() to its own scope Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 14/33] submodule--helper: add "const" to passed "module_clone_data" Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 15/33] submodule--helper: add "const" to copy of "update_data" Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 16/33] submodule--helper: add "const" to passed "struct update_data" Ævar Arnfjörð Bjarmason
2022-08-31 23:17     ` [PATCH v4 17/33] submodule--helper: refactor "errmsg_str" to be a "struct strbuf" Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 18/33] submodule--helper: don't redundantly check "else if (res)" Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 19/33] submodule--helper: rename "int res" to "int ret" Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 20/33] submodule--helper: return "ret", not "1" from update_submodule() Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 21/33] submodule--helper: add missing braces to "else" arm Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 22/33] submodule--helper: don't call submodule_strategy_to_string() in BUG() Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 23/33] submodule API: don't handle SM_..{UNSPECIFIED,COMMAND} in to_string() Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 24/33] submodule--helper: use "code" in run_update_command() Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 25/33] submodule--helper: don't exit() on failure, return Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 26/33] submodule--helper: libify determine_submodule_update_strategy() Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 27/33] submodule--helper: libify "must_die_on_failure" code paths Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 28/33] submodule--helper update: don't override 'checkout' exit code Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 29/33] submodule--helper: libify "must_die_on_failure" code paths (for die) Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 30/33] submodule--helper: check repo{_submodule,}_init() return values Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 31/33] submodule--helper: libify more "die" paths for module_update() Ævar Arnfjörð Bjarmason
2022-09-01 20:55       ` Glen Choo
2022-08-31 23:18     ` [PATCH v4 32/33] submodule--helper: libify even " Ævar Arnfjörð Bjarmason
2022-08-31 23:18     ` [PATCH v4 33/33] submodule--helper: fix bad config API usage Ævar Arnfjörð Bjarmason
2022-09-01 20:59     ` [PATCH v4 00/33] submodule--helper: add tests, rm dead code, refactor & leak prep Glen Choo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).