]> git.ipfire.org Git - thirdparty/git.git/commitdiff
ref-filter: --format=%(raw) support --perl
authorZheNing Hu <adlternative@gmail.com>
Mon, 26 Jul 2021 03:26:48 +0000 (03:26 +0000)
committerJunio C Hamano <gitster@pobox.com>
Mon, 26 Jul 2021 19:01:25 +0000 (12:01 -0700)
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>
Documentation/git-for-each-ref.txt
quote.c
quote.h
ref-filter.c
t/t6300-for-each-ref.sh

index cbb6f87d13f776435f4d703f5261c7566d87e127..6da899c62964275a97854c0b338f83f51db4bdfe 100644 (file)
@@ -241,8 +241,8 @@ raw:size::
        The raw data size of the object.
 
 Note that `--format=%(raw)` can not be used with `--python`, `--shell`, `--tcl`,
-`--perl` because such language may not support arbitrary binary data in their
-string variable type.
+because such language may not support arbitrary binary data in their string
+variable type.
 
 The message in a commit or a tag object is `contents`, from which
 `contents:<part>` can be used to extract various parts out of:
diff --git a/quote.c b/quote.c
index 8a3a5e39eb12adff643d8bd2d90d1e625203a2ce..26719d21d1e7555d92289b26402a73030e330606 100644 (file)
--- a/quote.c
+++ b/quote.c
@@ -471,6 +471,23 @@ void perl_quote_buf(struct strbuf *sb, const char *src)
        strbuf_addch(sb, sq);
 }
 
+void perl_quote_buf_with_len(struct strbuf *sb, const char *src, size_t len)
+{
+       const char sq = '\'';
+       const char bq = '\\';
+       const char *c = src;
+       const char *end = src + len;
+
+       strbuf_addch(sb, sq);
+       while (c != end) {
+               if (*c == sq || *c == bq)
+                       strbuf_addch(sb, bq);
+               strbuf_addch(sb, *c);
+               c++;
+       }
+       strbuf_addch(sb, sq);
+}
+
 void python_quote_buf(struct strbuf *sb, const char *src)
 {
        const char sq = '\'';
diff --git a/quote.h b/quote.h
index 768cc6338e27d73c8a10cf5eae76ad5626c73e3e..0fe69e264b0e7085e0b8d543434e6fccd1732c82 100644 (file)
--- a/quote.h
+++ b/quote.h
@@ -94,6 +94,7 @@ char *quote_path(const char *in, const char *prefix, struct strbuf *out, unsigne
 
 /* quoting as a string literal for other languages */
 void perl_quote_buf(struct strbuf *sb, const char *src);
+void perl_quote_buf_with_len(struct strbuf *sb, const char *src, size_t len);
 void python_quote_buf(struct strbuf *sb, const char *src);
 void tcl_quote_buf(struct strbuf *sb, const char *src);
 void basic_regex_quote_buf(struct strbuf *sb, const char *src);
index 0d5eb91ed5432b50bb95baf33679944f9de9bc93..ce6c2115016415fb56943678196b609a32a0ec19 100644 (file)
@@ -746,7 +746,10 @@ static void quote_formatting(struct strbuf *s, const char *str, ssize_t len, int
                sq_quote_buf(s, str);
                break;
        case QUOTE_PERL:
-               perl_quote_buf(s, str);
+               if (len < 0)
+                       perl_quote_buf(s, str);
+               else
+                       perl_quote_buf_with_len(s, str, len);
                break;
        case QUOTE_PYTHON:
                python_quote_buf(s, str);
@@ -1009,10 +1012,14 @@ int verify_ref_format(struct ref_format *format)
                at = parse_ref_filter_atom(format, sp + 2, ep, &err);
                if (at < 0)
                        die("%s", err.buf);
-               if (format->quote_style && used_atom[at].atom_type == ATOM_RAW &&
-                   used_atom[at].u.raw_data.option == RAW_BARE)
+
+               if ((format->quote_style == QUOTE_PYTHON ||
+                    format->quote_style == QUOTE_SHELL ||
+                    format->quote_style == QUOTE_TCL) &&
+                    used_atom[at].atom_type == ATOM_RAW &&
+                    used_atom[at].u.raw_data.option == RAW_BARE)
                        die(_("--format=%.*s cannot be used with"
-                             "--python, --shell, --tcl, --perl"), (int)(ep - sp - 2), sp + 2);
+                             "--python, --shell, --tcl"), (int)(ep - sp - 2), sp + 2);
                cp = ep + 1;
 
                if (skip_prefix(used_atom[at].name, "color:", &color))
index 18554f62d94109704b4a00bc3cd10b34936e1975..3d15d0a5360174a52fd67c13a56b213aa10a64a8 100755 (executable)
@@ -915,8 +915,23 @@ test_expect_success '%(raw) with --tcl must fail' '
        test_must_fail git for-each-ref --format="%(raw)" --tcl
 '
 
-test_expect_success '%(raw) with --perl must fail' '
-       test_must_fail git for-each-ref --format="%(raw)" --perl
+test_expect_success '%(raw) with --perl' '
+       git for-each-ref --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/blob1 --perl | perl >actual &&
+       cmp blob1 actual &&
+       git for-each-ref --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/blob3 --perl | perl >actual &&
+       cmp blob3 actual &&
+       git for-each-ref --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/blob8 --perl | perl >actual &&
+       cmp blob8 actual &&
+       git for-each-ref --format="\$name= %(raw);
+print \"\$name\"" refs/myblobs/first --perl | perl >actual &&
+       cmp one actual &&
+       git cat-file tree refs/mytrees/first > expected &&
+       git for-each-ref --format="\$name= %(raw);
+print \"\$name\"" refs/mytrees/first --perl | perl >actual &&
+       cmp expected actual
 '
 
 test_expect_success '%(raw) with --shell must fail' '