pretty: add abbrev option to %(describe)

The %(describe) placeholder by default, like `git describe`, uses a seven-character abbreviated commit object name. This may not be sufficient to fully describe all commits in a given repository, resulting in a placeholder replacement changing its length because the repository grew in size. This could cause the output of git-archive to change. Add the --abbrev option to `git describe` to the placeholder interface in order to provide tools to the user for fine-tuning project defaults and ensure reproducible archives. One alternative would be to just always specify --abbrev=40 but this may be a bit too biased... Signed-off-by: Eli Schwartz <eschwartz@archlinux.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Eli Schwartz committed Oct 31, 2021 at 13:15 UTC eccd97d0b02a87db0b0e828dd4f0b441c5462a9c
3 files changed +27
Documentation/pretty-formats.txt
+4
@@ -222,6 +222,10 @@ The placeholders are:
222 +
223 ** 'tags[=<bool>]': Instead of only considering annotated tags,
224 consider lightweight tags as well.
225 +** 'abbrev=<number>': Instead of using the default number of hexadecimal digits
226 + (which will vary according to the number of objects in the repository with a
227 + default of 7) of the abbreviated object name, use <number> digits, or as many
228 + digits as needed to form a unique object name.
229 ** 'match=<pattern>': Only consider tags matching the given
230 `glob(7)` pattern, excluding the "refs/tags/" prefix.
231 ** 'exclude=<pattern>': Do not consider tags matching the given
pretty.c
+15
@@ -1220,10 +1220,12 @@ static size_t parse_describe_args(const char *start, struct strvec *args)
1220 char *name;
1221 enum {
1222 DESCRIBE_ARG_BOOL,
1223 + DESCRIBE_ARG_INTEGER,
1224 DESCRIBE_ARG_STRING,
1225 } type;
1226 } option[] = {
1227 { "tags", DESCRIBE_ARG_BOOL},
1228 + { "abbrev", DESCRIBE_ARG_INTEGER },
1229 { "exclude", DESCRIBE_ARG_STRING },
1230 { "match", DESCRIBE_ARG_STRING },
1231 };
@@ -1247,6 +1249,19 @@ static size_t parse_describe_args(const char *start, struct strvec *args)
1249 found = 1;
1250 }
1251 break;
1252 + case DESCRIBE_ARG_INTEGER:
1253 + if (match_placeholder_arg_value(arg, option[i].name, &arg,
1254 + &argval, &arglen)) {
1255 + char *endptr;
1256 + if (!arglen)
1257 + return 0;
1258 + strtol(argval, &endptr, 10);
1259 + if (endptr - argval != arglen)
1260 + return 0;
1261 + strvec_pushf(args, "--%s=%.*s", option[i].name, (int)arglen, argval);
1262 + found = 1;
1263 + }
1264 + break;
1265 case DESCRIBE_ARG_STRING:
1266 if (match_placeholder_arg_value(arg, option[i].name, &arg,
1267 &argval, &arglen)) {
t/t4205-log-pretty-formats.sh
+8
@@ -1010,4 +1010,12 @@ test_expect_success '%(describe:tags) vs git describe --tags' '
1010 test_cmp expect actual
1011 '
1012
1013 +test_expect_success '%(describe:abbrev=...) vs git describe --abbrev=...' '
1014 + test_when_finished "git tag -d tagname" &&
1015 + git tag -a -m tagged tagname &&
1016 + git describe --abbrev=15 >expect &&
1017 + git log -1 --format="%(describe:abbrev=15)" >actual &&
1018 + test_cmp expect actual
1019 +'
1020 +
1021 test_done