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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.