Imported Upstream version 2.24.1
[platform/upstream/git.git] / quote.c
diff --git a/quote.c b/quote.c
index 7920e18..24a58ba 100644 (file)
--- a/quote.c
+++ b/quote.c
@@ -4,9 +4,15 @@
 
 int quote_path_fully = 1;
 
+static inline int need_bs_quote(char c)
+{
+       return (c == '\'' || c == '!');
+}
+
 /* Help to copy the thing properly quoted for the shell safety.
  * any single quote is replaced with '\'', any exclamation point
  * is replaced with '\!', and the whole thing is enclosed in a
+ * single quote pair.
  *
  * E.g.
  *  original     sq_quote     result
@@ -15,11 +21,6 @@ int quote_path_fully = 1;
  *  a'b      ==> a'\''b    ==> 'a'\''b'
  *  a!b      ==> a'\!'b    ==> 'a'\!'b'
  */
-static inline int need_bs_quote(char c)
-{
-       return (c == '\'' || c == '!');
-}
-
 void sq_quote_buf(struct strbuf *dst, const char *src)
 {
        char *to_free = NULL;
@@ -42,7 +43,42 @@ void sq_quote_buf(struct strbuf *dst, const char *src)
        free(to_free);
 }
 
-void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
+void sq_quote_buf_pretty(struct strbuf *dst, const char *src)
+{
+       static const char ok_punct[] = "+,-./:=@_^";
+       const char *p;
+
+       /* Avoid losing a zero-length string by adding '' */
+       if (!*src) {
+               strbuf_addstr(dst, "''");
+               return;
+       }
+
+       for (p = src; *p; p++) {
+               if (!isalpha(*p) && !isdigit(*p) && !strchr(ok_punct, *p)) {
+                       sq_quote_buf(dst, src);
+                       return;
+               }
+       }
+
+       /* if we get here, we did not need quoting */
+       strbuf_addstr(dst, src);
+}
+
+void sq_quotef(struct strbuf *dst, const char *fmt, ...)
+{
+       struct strbuf src = STRBUF_INIT;
+
+       va_list ap;
+       va_start(ap, fmt);
+       strbuf_vaddf(&src, fmt, ap);
+       va_end(ap);
+
+       sq_quote_buf(dst, src.buf);
+       strbuf_release(&src);
+}
+
+void sq_quote_argv(struct strbuf *dst, const char **argv)
 {
        int i;
 
@@ -51,8 +87,32 @@ void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
        for (i = 0; argv[i]; ++i) {
                strbuf_addch(dst, ' ');
                sq_quote_buf(dst, argv[i]);
-               if (maxlen && dst->len > maxlen)
-                       die("Too many or long arguments");
+       }
+}
+
+/*
+ * Legacy function to append each argv value, quoted as necessasry,
+ * with whitespace before each value.  This results in a leading
+ * space in the result.
+ */
+void sq_quote_argv_pretty(struct strbuf *dst, const char **argv)
+{
+       if (argv[0])
+               strbuf_addch(dst, ' ');
+       sq_append_quote_argv_pretty(dst, argv);
+}
+
+/*
+ * Append each argv value, quoted as necessary, with whitespace between them.
+ */
+void sq_append_quote_argv_pretty(struct strbuf *dst, const char **argv)
+{
+       int i;
+
+       for (i = 0; argv[i]; i++) {
+               if (i > 0)
+                       strbuf_addch(dst, ' ');
+               sq_quote_buf_pretty(dst, argv[i]);
        }
 }
 
@@ -80,9 +140,15 @@ static char *sq_dequote_step(char *arg, char **next)
                                *next = NULL;
                        return arg;
                case '\\':
-                       c = *++src;
-                       if (need_bs_quote(c) && *++src == '\'') {
-                               *dst++ = c;
+                       /*
+                        * Allow backslashed characters outside of
+                        * single-quotes only if they need escaping,
+                        * and only if we resume the single-quoted part
+                        * afterward.
+                        */
+                       if (need_bs_quote(src[1]) && src[2] == '\'') {
+                               *dst++ = src[1];
+                               src += 2;
                                continue;
                        }
                /* Fallthrough */
@@ -190,7 +256,7 @@ static size_t next_quote_pos(const char *s, ssize_t maxlen)
  *     Return value is the same as in (1).
  */
 static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
-                                    struct strbuf *sb, FILE *fp, int no_dq)
+                                   struct strbuf *sb, FILE *fp, int no_dq)
 {
 #undef EMIT
 #define EMIT(c)                                 \
@@ -417,6 +483,7 @@ void tcl_quote_buf(struct strbuf *sb, const char *src)
                case '{': case '}':
                case '$': case '\\': case '"':
                        strbuf_addch(sb, '\\');
+                       /* fallthrough */
                default:
                        strbuf_addch(sb, c);
                        break;
@@ -439,3 +506,40 @@ void tcl_quote_buf(struct strbuf *sb, const char *src)
        }
        strbuf_addch(sb, '"');
 }
+
+void basic_regex_quote_buf(struct strbuf *sb, const char *src)
+{
+       char c;
+
+       if (*src == '^') {
+               /* only beginning '^' is special and needs quoting */
+               strbuf_addch(sb, '\\');
+               strbuf_addch(sb, *src++);
+       }
+       if (*src == '*')
+               /* beginning '*' is not special, no quoting */
+               strbuf_addch(sb, *src++);
+
+       while ((c = *src++)) {
+               switch (c) {
+               case '[':
+               case '.':
+               case '\\':
+               case '*':
+                       strbuf_addch(sb, '\\');
+                       strbuf_addch(sb, c);
+                       break;
+
+               case '$':
+                       /* only the end '$' is special and needs quoting */
+                       if (*src == '\0')
+                               strbuf_addch(sb, '\\');
+                       strbuf_addch(sb, c);
+                       break;
+
+               default:
+                       strbuf_addch(sb, c);
+                       break;
+               }
+       }
+}