Sometimes people want to specify additional configuration data as "best effort" basis. Maybe commit.template configuration file points at somewhere in ~/template/ but on a particular system, the file may not exist and the user may be OK without using the template in such a case. When the value given to a configuration variable whose type is pathname wants to signal such an optional file, it can be marked by prepending ":(optional)" in front of it. Such a setting that is marked optional would avoid getting the command barf for a missing file, as an optional configuration setting that names a missing or an empty file is not even seen. cf. <xmqq5ywehb69.fsf@gitster.g> Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- Documentation/config.txt | 5 ++++- config.c | 16 ++++++++++++++-- t/t7500-commit-template-squash-signoff.sh | 9 +++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 8c0b3ed807..199e29ccea 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -358,7 +358,10 @@ compiled without runtime prefix support, the compiled-in prefix will be substituted instead. In the unlikely event that a literal path needs to be specified that should _not_ be expanded, it needs to be prefixed by `./`, like so: `./%(prefix)/bin`. - ++ +If prefixed with `:(optional)`, the configuration variable is treated +as if it does not exist, if the named path does not exist or names an +empty file. Variables ~~~~~~~~~ diff --git a/config.c b/config.c index a11bb85da3..4a060f1d82 100644 --- a/config.c +++ b/config.c @@ -1364,11 +1364,23 @@ int git_config_string(char **dest, const char *var, const char *value) int git_config_pathname(char **dest, const char *var, const char *value) { + int is_optional; + char *path; + if (!value) return config_error_nonbool(var); - *dest = interpolate_path(value, 0); - if (!*dest) + + is_optional = skip_prefix(value, ":(optional)", &value); + path = interpolate_path(value, 0); + if (!path) die(_("failed to expand user dir in: '%s'"), value); + + if (is_optional && is_empty_or_missing_file(path)) { + free(path); + return 0; + } + + *dest = path; return 0; } diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh index 4927b7260d..e28a79987d 100755 --- a/t/t7500-commit-template-squash-signoff.sh +++ b/t/t7500-commit-template-squash-signoff.sh @@ -46,6 +46,15 @@ test_expect_success 'nonexistent template file in config should return error' ' ) ' +test_expect_success 'nonexistent optional template file in config' ' + test_config commit.template ":(optional)$PWD"/notexist && + ( + GIT_EDITOR="echo hello >\"\$1\"" && + export GIT_EDITOR && + git commit --allow-empty + ) +' + # From now on we'll use a template file that exists. TEMPLATE="$PWD"/template -- 2.47.0-148-g19c85929c5