Merge branch 'jk/format-patch-quote-special-in-from' into maint
authorJunio C Hamano <gitster@pobox.com>
Sun, 15 May 2011 22:56:44 +0000 (15:56 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 15 May 2011 22:56:44 +0000 (15:56 -0700)
* jk/format-patch-quote-special-in-from:
pretty: quote rfc822 specials in email addresses

1  2 
pretty.c
t/t4014-format-patch.sh
diff --combined pretty.c
index e1d8a8f414bf052a59fbe78d022e611f44ed8361,0252a21a0d62dc59a9325d0365db0c0061b70eb7..13618d82644b72adc6068add826daa72dfe64f38
+++ b/pretty.c
@@@ -208,6 -208,58 +208,58 @@@ int has_non_ascii(const char *s
        return 0;
  }
  
+ static int is_rfc822_special(char ch)
+ {
+       switch (ch) {
+       case '(':
+       case ')':
+       case '<':
+       case '>':
+       case '[':
+       case ']':
+       case ':':
+       case ';':
+       case '@':
+       case ',':
+       case '.':
+       case '"':
+       case '\\':
+               return 1;
+       default:
+               return 0;
+       }
+ }
+ static int has_rfc822_specials(const char *s, int len)
+ {
+       int i;
+       for (i = 0; i < len; i++)
+               if (is_rfc822_special(s[i]))
+                       return 1;
+       return 0;
+ }
+ static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
+ {
+       int i;
+       /* just a guess, we may have to also backslash-quote */
+       strbuf_grow(out, len + 2);
+       strbuf_addch(out, '"');
+       for (i = 0; i < len; i++) {
+               switch (s[i]) {
+               case '"':
+               case '\\':
+                       strbuf_addch(out, '\\');
+                       /* fall through */
+               default:
+                       strbuf_addch(out, s[i]);
+               }
+       }
+       strbuf_addch(out, '"');
+ }
  static int is_rfc2047_special(char ch)
  {
        return (non_ascii(ch) || (ch == '=') || (ch == '?') || (ch == '_'));
@@@ -293,7 -345,14 +345,14 @@@ void pp_user_info(const char *what, enu
                        name_tail--;
                display_name_length = name_tail - line;
                strbuf_addstr(sb, "From: ");
-               add_rfc2047(sb, line, display_name_length, encoding);
+               if (!has_rfc822_specials(line, display_name_length)) {
+                       add_rfc2047(sb, line, display_name_length, encoding);
+               } else {
+                       struct strbuf quoted = STRBUF_INIT;
+                       add_rfc822_quoted(&quoted, line, display_name_length);
+                       add_rfc2047(sb, quoted.buf, quoted.len, encoding);
+                       strbuf_release(&quoted);
+               }
                strbuf_add(sb, name_tail, namelen - display_name_length);
                strbuf_addch(sb, '\n');
        } else {
@@@ -876,7 -935,11 +935,7 @@@ static size_t format_commit_one(struct 
                                              c->abbrev_parent_hashes.off;
                return 1;
        case 'm':               /* left/right/bottom */
 -              strbuf_addch(sb, (commit->object.flags & BOUNDARY)
 -                               ? '-'
 -                               : (commit->object.flags & SYMMETRIC_LEFT)
 -                               ? '<'
 -                               : '>');
 +              strbuf_addstr(sb, get_revision_mark(NULL, commit));
                return 1;
        case 'd':
                format_decoration(sb, commit);
diff --combined t/t4014-format-patch.sh
index c3cdb5205350985f3362268b0cd63bc59bee2444,6f8a96cd809916c8edd007b2fe46a5e35ff58ca9..dd406c44b509895cac0af3bfa08654823636f78e
@@@ -614,7 -614,7 +614,7 @@@ echo "fatal: --name-only does not make 
  echo "fatal: --name-status does not make sense" > expect.name-status
  echo "fatal: --check does not make sense" > expect.check
  
 -test_expect_success 'options no longer allowed for format-patch' '
 +test_expect_success C_LOCALE_OUTPUT 'options no longer allowed for format-patch' '
        test_must_fail git format-patch --name-only 2> output &&
        test_cmp expect.name-only output &&
        test_must_fail git format-patch --name-status 2> output &&
@@@ -793,4 -793,46 +793,46 @@@ test_expect_success 'format-patch wrap
        test_cmp expect subject
  '
  
+ check_author() {
+       echo content >>file &&
+       git add file &&
+       GIT_AUTHOR_NAME=$1 git commit -m author-check &&
+       git format-patch --stdout -1 >patch &&
+       grep ^From: patch >actual &&
+       test_cmp expect actual
+ }
+ cat >expect <<'EOF'
+ From: "Foo B. Bar" <author@example.com>
+ EOF
+ test_expect_success 'format-patch quotes dot in headers' '
+       check_author "Foo B. Bar"
+ '
+ cat >expect <<'EOF'
+ From: "Foo \"The Baz\" Bar" <author@example.com>
+ EOF
+ test_expect_success 'format-patch quotes double-quote in headers' '
+       check_author "Foo \"The Baz\" Bar"
+ '
+ cat >expect <<'EOF'
+ From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <author@example.com>
+ EOF
+ test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' '
+       check_author "Föo B. Bar"
+ '
+ cat >expect <<'EOF'
+ Subject: header with . in it
+ EOF
+ test_expect_success 'subject lines do not have 822 atom-quoting' '
+       echo content >>file &&
+       git add file &&
+       git commit -m "header with . in it" &&
+       git format-patch -k -1 --stdout >patch &&
+       grep ^Subject: patch >actual &&
+       test_cmp expect actual
+ '
  test_done