From: Junio C Hamano <gitster@pobox.com>
To: Paulius Zaleckas <paulius.zaleckas@gmail.com>
Cc: git@vger.kernel.org, "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
"Glen Choo" <glencbz@gmail.com>, "Patrick Steinhardt" <ps@pks.im>
Subject: Re: [PATCH v4 2/2] fetch: add fetch.submoduleErrors to make submodule fetch errors non-fatal
Date: Tue, 14 Jul 2026 10:14:14 -0700 [thread overview]
Message-ID: <xmqq1pd5trx5.fsf@gitster.g> (raw)
In-Reply-To: <20260714132959.3368867-3-paulius.zaleckas@gmail.com> (Paulius Zaleckas's message of "Tue, 14 Jul 2026 16:29:57 +0300")
Paulius Zaleckas <paulius.zaleckas@gmail.com> writes:
> + if (!strcmp(k, "fetch.submoduleerrors")) {
> + if (!v)
> + return config_error_nonbool(k);
> + else if (!strcasecmp(v, "fail"))
> + fetch_config->submodule_errors = SUBMODULE_ERRORS_FAIL;
> + else if (!strcasecmp(v, "warn"))
> + fetch_config->submodule_errors = SUBMODULE_ERRORS_WARN;
> + else
> + die(_("invalid value for '%s': '%s'"),
> + "fetch.submoduleErrors", v);
> + return 0;
> + }
Two points.
* Do not use strcasecmp() on the value.
While "fetch.submoduleerrors" may be case-insenstive, the value
does not have to be. We do not want to encourage users to write
"[fetch] submoduleErrors = Fail", as some people may want to
write third-party add-on scripts that parse "git config --get
fetch.submoduleerrors" output. For example:
error_handling=$(git config --get fetch.submoduleErrors)
case "$error_handling" in
fail)
... do something ... ;;
warn)
... do something else ... ;;
esac
We should not force them to write extra code to handle the value
case-insensitively.
* Since you need to convert between the enum and the string here,
in option_parse_submodule_errors(), and in add_options_to_argv(),
defining a pair of parse/format functions would be cleaner.
/* really private - use accessors to parse and format */
static const char *submodule_errors_[] = {
[SUBMODULE_ERRORS_FAIL] = "fail",
[SUBMODULE_ERRORS_WARN] = "warn",
};
static const char *submodule_error(int num)
{
assert(0 <= num && num < ARRAY_SIZE(submodule_errors_));
return submodule_errors[num];
}
static int parse_submodule_error(const char *name)
{
for (int num = 0; num < ARRAY_SIZE(submodule_errors_); num++)
if (!strcmp(submodule_errors_[num], name))
return num;
return -1;
}
The configuration parsing block would then become:
if (!strcmp(k, "fetch.submoduleerrors")) {
int num;
if (!v)
return config_error_nonbool(k);
num = parse_submodule_error(v);
if (num < 0)
die(_("invalid value..."), ...);
fetch_config->submodule_errors = num;
return 0;
}
This approach is much more maintainable. You only need to keep the
submodule_errors_[] array up to date with respect to the error-handling
preprocessor macros. Some reviewers might suggest converting these macros
into a proper enum. I would not object to that change, but I would not
bother doing it myself as I do not personally care much about the
distinction between an enum and a preprocessor macro in this context.
> @@ -2205,6 +2219,10 @@ static void add_options_to_argv(struct strvec *argv,
> strvec_push(argv, "--no-recurse-submodules");
> else if (config->recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
> strvec_push(argv, "--recurse-submodules=on-demand");
> + if (config->submodule_errors == SUBMODULE_ERRORS_FAIL)
> + strvec_push(argv, "--submodule-errors=fail");
> + else if (config->submodule_errors == SUBMODULE_ERRORS_WARN)
> + strvec_push(argv, "--submodule-errors=warn");
This part then becomes:
if (config->submodule_errors < 0)
; /* nothing */
else {
const char *name = submodule_error(config->submodule_errors);
strvec_push(argv, "--submodule-errors=%s", name);
}
This is, again, much more miantainable.
> +static int option_parse_submodule_errors(const struct option *opt,
> + const char *arg, int unset)
> +{
> + int *v = opt->value;
> + if (unset || !strcasecmp(arg, "fail"))
> + *v = SUBMODULE_ERRORS_FAIL;
> + else if (!strcasecmp(arg, "warn"))
> + *v = SUBMODULE_ERRORS_WARN;
> + else
> + die(_("invalid value for '%s': '%s'"), "--submodule-errors", arg);
> + return 0;
> +}
Updating this function is left as an exercise ;-)
prev parent reply other threads:[~2026-07-14 17:14 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-10 12:26 [PATCH v3 0/2] fetch: make submodule fetch errors configurable Paulius Zaleckas
2026-07-10 12:26 ` [PATCH v3 1/2] submodule: fix premature failure in recursive submodule fetch Paulius Zaleckas
2026-07-10 12:26 ` [PATCH v3 2/2] fetch: add fetch.submoduleErrors to make submodule fetch errors non-fatal Paulius Zaleckas
2026-07-10 22:21 ` Junio C Hamano
2026-07-14 13:29 ` Paulius Zaleckas
2026-07-14 13:29 ` [PATCH v4 0/2] fetch: make submodule fetch errors configurable Paulius Zaleckas
2026-07-14 13:29 ` [PATCH v4 1/2] submodule: fix premature failure in recursive submodule fetch Paulius Zaleckas
2026-07-14 13:29 ` [PATCH v4 2/2] fetch: add fetch.submoduleErrors to make submodule fetch errors non-fatal Paulius Zaleckas
2026-07-14 15:34 ` Junio C Hamano
2026-07-14 17:14 ` Junio C Hamano [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=xmqq1pd5trx5.fsf@gitster.g \
--to=gitster@pobox.com \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=glencbz@gmail.com \
--cc=paulius.zaleckas@gmail.com \
--cc=ps@pks.im \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox