ref-filter: --format=%(raw) support --perl
Because the perl language can handle binary data correctly, add the function perl_quote_buf_with_len(), which can specify the length of the data and prevent the data from being truncated at '\0' to help `--format="%(raw)"` support `--perl`. Reviewed-by: Jacob Keller <jacob.keller@gmail.com> Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: ZheNing Hu <adlternative@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
ZheNing Hu committed
Jul 26, 2021 at 03:26 UTC
7121c4d4e2877115fb372b3f147fad4cd1306751
5 files changed
+48
-8
Documentation/git-for-each-ref.txt
+2
-2
@@ -241,8 +241,8 @@ raw:size::
241
The raw data size of the object.
242
243
Note that `--format=%(raw)` can not be used with `--python`, `--shell`, `--tcl`,
244
-`--perl` because such language may not support arbitrary binary data in their
245
-string variable type.
244
+because such language may not support arbitrary binary data in their string
245
+variable type.
246
247
The message in a commit or a tag object is `contents`, from which
248
`contents:<part>` can be used to extract various parts out of:
quote.c
+17
@@ -471,6 +471,23 @@ void perl_quote_buf(struct strbuf *sb, const char *src)
471
strbuf_addch(sb, sq);
472
}
473
474
+void perl_quote_buf_with_len(struct strbuf *sb, const char *src, size_t len)
475
+{
476
+ const char sq = '\'';
477
+ const char bq = '\\';
478
+ const char *c = src;
479
+ const char *end = src + len;
480
+
481
+ strbuf_addch(sb, sq);
482
+ while (c != end) {
483
+ if (*c == sq || *c == bq)
484
+ strbuf_addch(sb, bq);
485
+ strbuf_addch(sb, *c);
486
+ c++;
487
+ }
488
+ strbuf_addch(sb, sq);
489
+}
490
+
491
void python_quote_buf(struct strbuf *sb, const char *src)
492
{
493
const char sq = '\'';
quote.h
+1
@@ -94,6 +94,7 @@ char *quote_path(const char *in, const char *prefix, struct strbuf *out, unsigne
94
95
/* quoting as a string literal for other languages */
96
void perl_quote_buf(struct strbuf *sb, const char *src);
97
+void perl_quote_buf_with_len(struct strbuf *sb, const char *src, size_t len);
98
void python_quote_buf(struct strbuf *sb, const char *src);
99
void tcl_quote_buf(struct strbuf *sb, const char *src);
100
void basic_regex_quote_buf(struct strbuf *sb, const char *src);
ref-filter.c
+11
-4
@@ -746,7 +746,10 @@ static void quote_formatting(struct strbuf *s, const char *str, ssize_t len, int
746
sq_quote_buf(s, str);
747
break;
748
case QUOTE_PERL:
749
- perl_quote_buf(s, str);
749
+ if (len < 0)
750
+ perl_quote_buf(s, str);
751
+ else
752
+ perl_quote_buf_with_len(s, str, len);
753
break;
754
case QUOTE_PYTHON:
755
python_quote_buf(s, str);
@@ -1009,10 +1012,14 @@ int verify_ref_format(struct ref_format *format)
1012
at = parse_ref_filter_atom(format, sp + 2, ep, &err);
1013
if (at < 0)
1014
die("%s", err.buf);
1012
- if (format->quote_style && used_atom[at].atom_type == ATOM_RAW &&
1013
- used_atom[at].u.raw_data.option == RAW_BARE)
1015
+
1016
+ if ((format->quote_style == QUOTE_PYTHON ||
1017
+ format->quote_style == QUOTE_SHELL ||
1018
+ format->quote_style == QUOTE_TCL) &&
1019
+ used_atom[at].atom_type == ATOM_RAW &&
1020
+ used_atom[at].u.raw_data.option == RAW_BARE)
1021
die(_("--format=%.*s cannot be used with"
1015
- "--python, --shell, --tcl, --perl"), (int)(ep - sp - 2), sp + 2);
1022
+ "--python, --shell, --tcl"), (int)(ep - sp - 2), sp + 2);
1023
cp = ep + 1;
1024
1025
if (skip_prefix(used_atom[at].name, "color:", &color))
t/t6300-for-each-ref.sh
+17
-2
@@ -915,8 +915,23 @@ test_expect_success '%(raw) with --tcl must fail' '
915
test_must_fail git for-each-ref --format="%(raw)" --tcl
916
'
917
918
-test_expect_success '%(raw) with --perl must fail' '
919
- test_must_fail git for-each-ref --format="%(raw)" --perl
918
+test_expect_success '%(raw) with --perl' '
919
+ git for-each-ref --format="\$name= %(raw);
920
+print \"\$name\"" refs/myblobs/blob1 --perl | perl >actual &&
921
+ cmp blob1 actual &&
922
+ git for-each-ref --format="\$name= %(raw);
923
+print \"\$name\"" refs/myblobs/blob3 --perl | perl >actual &&
924
+ cmp blob3 actual &&
925
+ git for-each-ref --format="\$name= %(raw);
926
+print \"\$name\"" refs/myblobs/blob8 --perl | perl >actual &&
927
+ cmp blob8 actual &&
928
+ git for-each-ref --format="\$name= %(raw);
929
+print \"\$name\"" refs/myblobs/first --perl | perl >actual &&
930
+ cmp one actual &&
931
+ git cat-file tree refs/mytrees/first > expected &&
932
+ git for-each-ref --format="\$name= %(raw);
933
+print \"\$name\"" refs/mytrees/first --perl | perl >actual &&
934
+ cmp expected actual
935
'
936
937
test_expect_success '%(raw) with --shell must fail' '