Skip to content

Commit ccfcaf3

Browse files
committed
parseopt: values of pathname type can be prefixed with :(optional)
In the previous step, we introduced an optional filename that can be given to a configuration variable, and nullify the fact that such a configuration setting even existed if the named path is missing or empty. Let's do the same for command line options that name a pathname. Signed-off-by: Junio C Hamano <[email protected]> Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: D. Ben Knoble <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 749d6d1 commit ccfcaf3

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

Documentation/gitcli.adoc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,20 @@ $ git describe --abbrev=10 HEAD # correct
216216
$ git describe --abbrev 10 HEAD # NOT WHAT YOU MEANT
217217
----------------------------
218218
219+
220+
Magic filename options
221+
~~~~~~~~~~~~~~~~~~~~~~
222+
Options that take a filename allow a prefix `:(optional)`. For example:
223+
224+
----------------------------
225+
git commit -F :(optional)COMMIT_EDITMSG
226+
# if COMMIT_EDITMSG does not exist, equivalent to
227+
git commit
228+
----------------------------
229+
230+
Like with configuration values, if the named file is missing Git behaves as if
231+
the option was not given at all. See "Values" in linkgit:git-config[1].
232+
219233
NOTES ON FREQUENTLY CONFUSED OPTIONS
220234
------------------------------------
221235

parse-options.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
133133
{
134134
const char *arg;
135135
const int unset = flags & OPT_UNSET;
136-
int err;
137136

138137
if (unset && p->opt)
139138
return error(_("%s takes no value"), optname(opt, flags));
@@ -209,21 +208,31 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
209208
case OPTION_FILENAME:
210209
{
211210
const char *value;
212-
213-
FREE_AND_NULL(*(char **)opt->value);
214-
215-
err = 0;
211+
int is_optional;
216212

217213
if (unset)
218214
value = NULL;
219215
else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
220-
value = (const char *) opt->defval;
221-
else
222-
err = get_arg(p, opt, flags, &value);
216+
value = (char *)opt->defval;
217+
else {
218+
int err = get_arg(p, opt, flags, &value);
219+
if (err)
220+
return err;
221+
}
222+
if (!value)
223+
return 0;
223224

224-
if (!err)
225-
*(char **)opt->value = fix_filename(p->prefix, value);
226-
return err;
225+
is_optional = skip_prefix(value, ":(optional)", &value);
226+
if (!value)
227+
is_optional = 0;
228+
value = fix_filename(p->prefix, value);
229+
if (is_optional && is_empty_or_missing_file(value)) {
230+
free((char *)value);
231+
} else {
232+
FREE_AND_NULL(*(char **)opt->value);
233+
*(const char **)opt->value = value;
234+
}
235+
return 0;
227236
}
228237
case OPTION_CALLBACK:
229238
{

t/t7500-commit-template-squash-signoff.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ test_expect_success 'nonexistent template file should return error' '
3737
)
3838
'
3939

40+
test_expect_success 'nonexistent optional template file on command line' '
41+
echo changes >> foo &&
42+
git add foo &&
43+
(
44+
GIT_EDITOR="echo hello >\"\$1\"" &&
45+
export GIT_EDITOR &&
46+
git commit --template ":(optional)$PWD/notexist"
47+
)
48+
'
49+
4050
test_expect_success 'nonexistent template file in config should return error' '
4151
test_config commit.template "$PWD"/notexist &&
4252
(

0 commit comments

Comments
 (0)