Git fork

config: values of pathname type can be prefixed with :(optional)

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
file is not even seen.

cf. <xmqq5ywehb69.fsf@gitster.g>

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

+41 -4
+3 -1
Documentation/config.adoc
··· 358 358 substituted instead. In the unlikely event that a literal path needs to 359 359 be specified that should _not_ be expanded, it needs to be prefixed by 360 360 `./`, like so: `./%(prefix)/bin`. 361 - 361 + + 362 + If prefixed with `:(optional)`, the configuration variable is treated 363 + as if it does not exist, if the named path does not exist. 362 364 363 365 Variables 364 366 ~~~~~~~~~
+14 -2
config.c
··· 1279 1279 1280 1280 int git_config_pathname(char **dest, const char *var, const char *value) 1281 1281 { 1282 + int is_optional; 1283 + char *path; 1284 + 1282 1285 if (!value) 1283 1286 return config_error_nonbool(var); 1284 - *dest = interpolate_path(value, 0); 1285 - if (!*dest) 1287 + 1288 + is_optional = skip_prefix(value, ":(optional)", &value); 1289 + path = interpolate_path(value, 0); 1290 + if (!path) 1286 1291 die(_("failed to expand user dir in: '%s'"), value); 1292 + 1293 + if (is_optional && is_missing_file(path)) { 1294 + free(path); 1295 + return 0; 1296 + } 1297 + 1298 + *dest = path; 1287 1299 return 0; 1288 1300 } 1289 1301
+8
t/t7500-commit-template-squash-signoff.sh
··· 46 46 ) 47 47 ' 48 48 49 + test_expect_success 'nonexistent optional template file in config' ' 50 + test_config commit.template ":(optional)$PWD"/notexist && 51 + GIT_EDITOR="echo hello >" git commit --allow-empty && 52 + git cat-file commit HEAD | sed -e "1,/^$/d" >actual && 53 + echo hello >expect && 54 + test_cmp expect actual 55 + ' 56 + 49 57 # From now on we'll use a template file that exists. 50 58 TEMPLATE="$PWD"/template 51 59
+13
wrapper.c
··· 721 721 return ret; 722 722 } 723 723 724 + int is_missing_file(const char *filename) 725 + { 726 + struct stat st; 727 + 728 + if (stat(filename, &st) < 0) { 729 + if (errno == ENOENT) 730 + return 1; 731 + die_errno(_("could not stat %s"), filename); 732 + } 733 + 734 + return 0; 735 + } 736 + 724 737 int is_empty_or_missing_file(const char *filename) 725 738 { 726 739 struct stat st;
+3 -1
wrapper.h
··· 66 66 __attribute__((format (printf, 2, 3))) 67 67 void write_file(const char *path, const char *fmt, ...); 68 68 69 - /* Return 1 if the file is empty or does not exists, 0 otherwise. */ 69 + /* Return 1 if the file does not exist, 0 otherwise. */ 70 + int is_missing_file(const char *filename); 71 + /* Return 1 if the file is empty or does not exist, 0 otherwise. */ 70 72 int is_empty_or_missing_file(const char *filename); 71 73 72 74 enum fsync_action {