trace: avoid unnecessary quoting

Trace output which contains arbitrary strings (e.g., the arguments to commands which we are running) is always passed through sq_quote_buf(). That function always adds single-quotes, even if the output consists of vanilla characters. This can make the output a bit hard to read. Let's avoid the quoting if there are no characters which a shell would interpret. Trace output doesn't necessarily need to be shell-compatible, but: - the shell language is a good ballpark for what humans consider readable (well, humans versed in command line tools) - the run_command bits can be cut-and-pasted to a shell, and we'll keep that property - it covers any cases which would make the output visually ambiguous (e.g., embedded whitespace or quotes) Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jan 15, 2018 at 17:59 UTC 1fbdab21bb452ca4732bf088539247047465b99d
3 files changed +36 -2
quote.c
+26
@@ -43,6 +43,22 @@ void sq_quote_buf(struct strbuf *dst, const char *src)
43 free(to_free);
44 }
45
46 +void sq_quote_buf_pretty(struct strbuf *dst, const char *src)
47 +{
48 + static const char ok_punct[] = "+,-./:=@_^";
49 + const char *p;
50 +
51 + for (p = src; *p; p++) {
52 + if (!isalpha(*p) && !isdigit(*p) && !strchr(ok_punct, *p)) {
53 + sq_quote_buf(dst, src);
54 + return;
55 + }
56 + }
57 +
58 + /* if we get here, we did not need quoting */
59 + strbuf_addstr(dst, src);
60 +}
61 +
62 void sq_quotef(struct strbuf *dst, const char *fmt, ...)
63 {
64 struct strbuf src = STRBUF_INIT;
@@ -68,6 +84,16 @@ void sq_quote_argv(struct strbuf *dst, const char **argv)
84 }
85 }
86
87 +void sq_quote_argv_pretty(struct strbuf *dst, const char **argv)
88 +{
89 + int i;
90 +
91 + for (i = 0; argv[i]; i++) {
92 + strbuf_addch(dst, ' ');
93 + sq_quote_buf_pretty(dst, argv[i]);
94 + }
95 +}
96 +
97 static char *sq_dequote_step(char *arg, char **next)
98 {
99 char *dst = arg;
quote.h
+8
@@ -33,6 +33,14 @@ extern void sq_quote_buf(struct strbuf *, const char *src);
33 extern void sq_quote_argv(struct strbuf *, const char **argv);
34 extern void sq_quotef(struct strbuf *, const char *fmt, ...);
35
36 +/*
37 + * These match their non-pretty variants, except that they avoid
38 + * quoting when there are no exotic characters. These should only be used for
39 + * human-readable output, as sq_dequote() is not smart enough to dequote it.
40 + */
41 +void sq_quote_buf_pretty(struct strbuf *, const char *src);
42 +void sq_quote_argv_pretty(struct strbuf *, const char **argv);
43 +
44 /* This unwraps what sq_quote() produces in place, but returns
45 * NULL if the input does not look like what sq_quote would have
46 * produced.
trace.c
+2 -2
@@ -157,7 +157,7 @@ static void trace_argv_vprintf_fl(const char *file, int line,
157
158 strbuf_vaddf(&buf, format, ap);
159
160 - sq_quote_argv(&buf, argv);
160 + sq_quote_argv_pretty(&buf, argv);
161 print_trace_line(&trace_default_key, &buf);
162 }
163
@@ -426,6 +426,6 @@ void trace_command_performance(const char **argv)
426 atexit(print_command_performance_atexit);
427
428 strbuf_reset(&command_line);
429 - sq_quote_argv(&command_line, argv);
429 + sq_quote_argv_pretty(&command_line, argv);
430 command_start_time = getnanotime();
431 }