Merge branch 'jk/format-patch-quote-special-in-from'
authorJunio C Hamano <gitster@pobox.com>
Fri, 6 May 2011 17:50:18 +0000 (10:50 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 6 May 2011 17:50:18 +0000 (10:50 -0700)
* jk/format-patch-quote-special-in-from:
pretty: quote rfc822 specials in email addresses

Conflicts:
pretty.c
t/t4014-format-patch.sh

1  2 
pretty.c
t/t4014-format-patch.sh
diff --combined pretty.c
index ba95de92cd66f9ba24d84e706b013d2679ef554a,0252a21a0d62dc59a9325d0365db0c0061b70eb7..dff5c8d1831ca4019d1a502a393cb95f20ad18f7
+++ 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 == '_'));
@@@ -287,22 -339,20 +339,29 @@@ void pp_user_info(const char *what, enu
        if (fmt == CMIT_FMT_EMAIL) {
                char *name_tail = strchr(line, '<');
                int display_name_length;
 +              int final_line;
                if (!name_tail)
                        return;
                while (line < name_tail && isspace(name_tail[-1]))
                        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);
+               }
 +              for (final_line = 0; final_line < sb->len; final_line++)
 +                      if (sb->buf[sb->len - final_line - 1] == '\n')
 +                              break;
 +              if (namelen - display_name_length + final_line > 78) {
 +                      strbuf_addch(sb, '\n');
 +                      if (!isspace(name_tail[0]))
 +                              strbuf_addch(sb, ' ');
 +              }
                strbuf_add(sb, name_tail, namelen - display_name_length);
                strbuf_addch(sb, '\n');
        } else {
@@@ -885,7 -935,11 +944,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 a7060b75be60fd5d16128274e15344c6333de76f,6f8a96cd809916c8edd007b2fe46a5e35ff58ca9..045cee312cdeb515869eeeda3f7b167fb5b91504
@@@ -616,11 -616,11 +616,11 @@@ echo "fatal: --check does not make sens
  
  test_expect_success 'options no longer allowed for format-patch' '
        test_must_fail git format-patch --name-only 2> output &&
 -      test_cmp expect.name-only output &&
 +      test_i18ncmp expect.name-only output &&
        test_must_fail git format-patch --name-status 2> output &&
 -      test_cmp expect.name-status output &&
 +      test_i18ncmp expect.name-status output &&
        test_must_fail git format-patch --check 2> output &&
 -      test_cmp expect.check output'
 +      test_i18ncmp expect.check output'
  
  test_expect_success 'format-patch --numstat should produce a patch' '
        git format-patch --numstat --stdout master..side > output &&
@@@ -793,19 -793,46 +793,62 @@@ test_expect_success 'format-patch wrap
        test_cmp expect subject
  '
  
 +M8="foo_bar_"
 +M64=$M8$M8$M8$M8$M8$M8$M8$M8
 +cat >expect <<EOF
 +From: $M64
 + <foobar@foo.bar>
 +EOF
 +test_expect_success 'format-patch wraps non-quotable headers' '
 +      rm -rf patches/ &&
 +      echo content >>file &&
 +      git add file &&
 +      git commit -mfoo --author "$M64 <foobar@foo.bar>" &&
 +      git format-patch --stdout -1 >patch &&
 +      sed -n "/^From: /p; /^ /p; /^$/q" <patch >from &&
 +      test_cmp expect from
 +'
++
+ 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