config: format paths gently

Move the logic for formatting path config values into a helper method and use gentle parsing when needed. We need to be careful about how to handle the ':(optional)' macro, which as tested in t1311-config-optional.sh must allow for ignoring a missing path when other multiple values exist, but cause 'git config get' to fail if it is the only possible value and thus no result is output. In the case of our list, we need to omit those values silently. This necessitates the use of the 'gently' parameter here. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Feb 23, 2026 at 12:26 UTC bcfb9128c9ce87dfeacaffe051257f7a5fc866e9
2 files changed +23 -12
builtin/config.c
+22 -10
@@ -314,6 +314,25 @@ static int format_config_bool_or_str(struct strbuf *buf,
314 return 0;
315 }
316
317 +static int format_config_path(struct strbuf *buf,
318 + const char *key_,
319 + const char *value_,
320 + int gently)
321 +{
322 + char *v;
323 +
324 + if (git_config_pathname(&v, key_, value_) < 0)
325 + return -1;
326 +
327 + if (v)
328 + strbuf_addstr(buf, v);
329 + else
330 + return gently ? -1 : 1; /* :(optional)no-such-file */
331 +
332 + free(v);
333 + return 0;
334 +}
335 +
336 /*
337 * Format the configuration key-value pair (`key_`, `value_`) and
338 * append it into strbuf `buf`. Returns a negative value on failure,
@@ -347,16 +366,9 @@ static int format_config(const struct config_display_options *opts,
366 res = format_config_bool_or_int(buf, key_, value_, kvi, gently);
367 else if (opts->type == TYPE_BOOL_OR_STR)
368 res = format_config_bool_or_str(buf, value_);
350 - else if (opts->type == TYPE_PATH) {
351 - char *v;
352 - if (git_config_pathname(&v, key_, value_) < 0)
353 - return -1;
354 - if (v)
355 - strbuf_addstr(buf, v);
356 - else
357 - return 1; /* :(optional)no-such-file */
358 - free((char *)v);
359 - } else if (opts->type == TYPE_EXPIRY_DATE) {
369 + else if (opts->type == TYPE_PATH)
370 + res = format_config_path(buf, key_, value_, gently);
371 + else if (opts->type == TYPE_EXPIRY_DATE) {
372 timestamp_t t;
373 if (git_config_expiry_date(&t, key_, value_) < 0)
374 return -1;
t/t1300-config.sh
+1 -2
@@ -2545,7 +2545,6 @@ test_expect_success 'list --type=bool-or-int shows only canonicalizable values'
2545 '
2546
2547 test_expect_success 'list --type=path shows only canonicalizable path values' '
2548 - # TODO: handling of missing path is incorrect here.
2548 cat >expect <<-EOF &&
2549 section.foo=True
2550 section.number=10
@@ -2554,7 +2553,7 @@ test_expect_success 'list --type=path shows only canonicalizable path values' '
2553 section.red=red
2554 section.blue=Blue
2555 section.date=Fri Jun 4 15:46:55 2010
2557 - section.missing=section.exists=expect
2556 + section.exists=expect
2557 EOF
2558
2559 git config ${mode_prefix}list --type=path >actual 2>err &&