Merge branch 'es/pretty-describe-more'

Extend "git log --format=%(describe)" placeholder to allow passing
selected command-line options to the underlying "git describe"
command.

* es/pretty-describe-more:
  pretty: add abbrev option to %(describe)
  pretty: add tag option to %(describe)
  pretty.c: rework describe options parsing for better extensibility
This commit is contained in:
Junio C Hamano
2021-12-15 09:39:48 -08:00
3 changed files with 75 additions and 15 deletions

View File

@ -220,6 +220,12 @@ The placeholders are:
inconsistent when tags are added or removed at inconsistent when tags are added or removed at
the same time. the same time.
+ +
** 'tags[=<bool-value>]': Instead of only considering annotated tags,
consider lightweight tags as well.
** 'abbrev=<number>': Instead of using the default number of hexadecimal digits
(which will vary according to the number of objects in the repository with a
default of 7) of the abbreviated object name, use <number> digits, or as many
digits as needed to form a unique object name.
** 'match=<pattern>': Only consider tags matching the given ** 'match=<pattern>': Only consider tags matching the given
`glob(7)` pattern, excluding the "refs/tags/" prefix. `glob(7)` pattern, excluding the "refs/tags/" prefix.
** 'exclude=<pattern>': Do not consider tags matching the given ** 'exclude=<pattern>': Do not consider tags matching the given
@ -273,11 +279,6 @@ endif::git-rev-list[]
If any option is provided multiple times the If any option is provided multiple times the
last occurrence wins. last occurrence wins.
+ +
The boolean options accept an optional value `[=<value>]`. The values
`true`, `false`, `on`, `off` etc. are all accepted. See the "boolean"
sub-section in "EXAMPLES" in linkgit:git-config[1]. If a boolean
option is given with no value, it's enabled.
+
** 'key=<key>': only show trailers with specified <key>. Matching is done ** 'key=<key>': only show trailers with specified <key>. Matching is done
case-insensitively and trailing colon is optional. If option is case-insensitively and trailing colon is optional. If option is
given multiple times trailer lines matching any of the keys are given multiple times trailer lines matching any of the keys are
@ -313,6 +314,11 @@ insert an empty string unless we are traversing reflog entries (e.g., by
decoration format if `--decorate` was not already provided on the command decoration format if `--decorate` was not already provided on the command
line. line.
The boolean options accept an optional value `[=<bool-value>]`. The values
`true`, `false`, `on`, `off` etc. are all accepted. See the "boolean"
sub-section in "EXAMPLES" in linkgit:git-config[1]. If a boolean
option is given with no value, it's enabled.
If you add a `+` (plus sign) after '%' of a placeholder, a line-feed If you add a `+` (plus sign) after '%' of a placeholder, a line-feed
is inserted immediately before the expansion if and only if the is inserted immediately before the expansion if and only if the
placeholder expands to a non-empty string. placeholder expands to a non-empty string.

View File

@ -1275,28 +1275,66 @@ int format_set_trailers_options(struct process_trailer_options *opts,
static size_t parse_describe_args(const char *start, struct strvec *args) static size_t parse_describe_args(const char *start, struct strvec *args)
{ {
const char *options[] = { "match", "exclude" }; struct {
char *name;
enum {
DESCRIBE_ARG_BOOL,
DESCRIBE_ARG_INTEGER,
DESCRIBE_ARG_STRING,
} type;
} option[] = {
{ "tags", DESCRIBE_ARG_BOOL},
{ "abbrev", DESCRIBE_ARG_INTEGER },
{ "exclude", DESCRIBE_ARG_STRING },
{ "match", DESCRIBE_ARG_STRING },
};
const char *arg = start; const char *arg = start;
for (;;) { for (;;) {
const char *matched = NULL; int found = 0;
const char *argval; const char *argval;
size_t arglen = 0; size_t arglen = 0;
int optval = 0;
int i; int i;
for (i = 0; i < ARRAY_SIZE(options); i++) { for (i = 0; !found && i < ARRAY_SIZE(option); i++) {
if (match_placeholder_arg_value(arg, options[i], &arg, switch (option[i].type) {
&argval, &arglen)) { case DESCRIBE_ARG_BOOL:
matched = options[i]; if (match_placeholder_bool_arg(arg, option[i].name, &arg, &optval)) {
if (optval)
strvec_pushf(args, "--%s", option[i].name);
else
strvec_pushf(args, "--no-%s", option[i].name);
found = 1;
}
break;
case DESCRIBE_ARG_INTEGER:
if (match_placeholder_arg_value(arg, option[i].name, &arg,
&argval, &arglen)) {
char *endptr;
if (!arglen)
return 0;
strtol(argval, &endptr, 10);
if (endptr - argval != arglen)
return 0;
strvec_pushf(args, "--%s=%.*s", option[i].name, (int)arglen, argval);
found = 1;
}
break;
case DESCRIBE_ARG_STRING:
if (match_placeholder_arg_value(arg, option[i].name, &arg,
&argval, &arglen)) {
if (!arglen)
return 0;
strvec_pushf(args, "--%s=%.*s", option[i].name, (int)arglen, argval);
found = 1;
}
break; break;
} }
} }
if (!matched) if (!found)
break; break;
if (!arglen)
return 0;
strvec_pushf(args, "--%s=%.*s", matched, (int)arglen, argval);
} }
return arg - start; return arg - start;
} }

View File

@ -1002,4 +1002,20 @@ test_expect_success '%(describe:exclude=...) vs git describe --exclude ...' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_success '%(describe:tags) vs git describe --tags' '
test_when_finished "git tag -d tagname" &&
git tag tagname &&
git describe --tags >expect &&
git log -1 --format="%(describe:tags)" >actual &&
test_cmp expect actual
'
test_expect_success '%(describe:abbrev=...) vs git describe --abbrev=...' '
test_when_finished "git tag -d tagname" &&
git tag -a -m tagged tagname &&
git describe --abbrev=15 >expect &&
git log -1 --format="%(describe:abbrev=15)" >actual &&
test_cmp expect actual
'
test_done test_done