Merge branch 'jk/format-patch-multiline-header' into maint

* jk/format-patch-multiline-header:
  format-patch: rfc2047-encode newlines in headers
  format-patch: wrap long header lines
  strbuf: add fixed-length version of add_wrapped_text
This commit is contained in:
Junio C Hamano 2011-04-03 12:31:19 -07:00
commit c3d1a4368a
4 changed files with 121 additions and 10 deletions

View File

@ -216,36 +216,53 @@ static int is_rfc2047_special(char ch)
static void add_rfc2047(struct strbuf *sb, const char *line, int len, static void add_rfc2047(struct strbuf *sb, const char *line, int len,
const char *encoding) const char *encoding)
{ {
int i, last; static const int max_length = 78; /* per rfc2822 */
int i;
int line_len;
/* How many bytes are already used on the current line? */
for (i = sb->len - 1; i >= 0; i--)
if (sb->buf[i] == '\n')
break;
line_len = sb->len - (i+1);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
int ch = line[i]; int ch = line[i];
if (non_ascii(ch)) if (non_ascii(ch) || ch == '\n')
goto needquote; goto needquote;
if ((i + 1 < len) && (ch == '=' && line[i+1] == '?')) if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
goto needquote; goto needquote;
} }
strbuf_add(sb, line, len); strbuf_add_wrapped_bytes(sb, line, len, 0, 1, max_length - line_len);
return; return;
needquote: needquote:
strbuf_grow(sb, len * 3 + strlen(encoding) + 100); strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
strbuf_addf(sb, "=?%s?q?", encoding); strbuf_addf(sb, "=?%s?q?", encoding);
for (i = last = 0; i < len; i++) { line_len += strlen(encoding) + 5; /* 5 for =??q? */
for (i = 0; i < len; i++) {
unsigned ch = line[i] & 0xFF; unsigned ch = line[i] & 0xFF;
if (line_len >= max_length - 2) {
strbuf_addf(sb, "?=\n =?%s?q?", encoding);
line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
}
/* /*
* We encode ' ' using '=20' even though rfc2047 * We encode ' ' using '=20' even though rfc2047
* allows using '_' for readability. Unfortunately, * allows using '_' for readability. Unfortunately,
* many programs do not understand this and just * many programs do not understand this and just
* leave the underscore in place. * leave the underscore in place.
*/ */
if (is_rfc2047_special(ch) || ch == ' ') { if (is_rfc2047_special(ch) || ch == ' ' || ch == '\n') {
strbuf_add(sb, line + last, i - last);
strbuf_addf(sb, "=%02X", ch); strbuf_addf(sb, "=%02X", ch);
last = i + 1; line_len += 3;
}
else {
strbuf_addch(sb, ch);
line_len++;
} }
} }
strbuf_add(sb, line + last, len - last);
strbuf_addstr(sb, "?="); strbuf_addstr(sb, "?=");
} }
@ -1106,11 +1123,10 @@ void pp_title_line(enum cmit_fmt fmt,
const char *encoding, const char *encoding,
int need_8bit_cte) int need_8bit_cte)
{ {
const char *line_separator = (fmt == CMIT_FMT_EMAIL) ? "\n " : " ";
struct strbuf title; struct strbuf title;
strbuf_init(&title, 80); strbuf_init(&title, 80);
*msg_p = format_subject(&title, *msg_p, line_separator); *msg_p = format_subject(&title, *msg_p, " ");
strbuf_grow(sb, title.len + 1024); strbuf_grow(sb, title.len + 1024);
if (subject) { if (subject) {

View File

@ -709,4 +709,88 @@ test_expect_success TTY 'format-patch --stdout paginates' '
test_path_is_missing .git/pager_used test_path_is_missing .git/pager_used
' '
test_expect_success 'format-patch handles multi-line subjects' '
rm -rf patches/ &&
echo content >>file &&
for i in one two three; do echo $i; done >msg &&
git add file &&
git commit -F msg &&
git format-patch -o patches -1 &&
grep ^Subject: patches/0001-one.patch >actual &&
echo "Subject: [PATCH] one two three" >expect &&
test_cmp expect actual
'
test_expect_success 'format-patch handles multi-line encoded subjects' '
rm -rf patches/ &&
echo content >>file &&
for i in en två tre; do echo $i; done >msg &&
git add file &&
git commit -F msg &&
git format-patch -o patches -1 &&
grep ^Subject: patches/0001-en.patch >actual &&
echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
test_cmp expect actual
'
M8="foo bar "
M64=$M8$M8$M8$M8$M8$M8$M8$M8
M512=$M64$M64$M64$M64$M64$M64$M64$M64
cat >expect <<'EOF'
Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
foo bar foo bar foo bar foo bar
EOF
test_expect_success 'format-patch wraps extremely long headers (ascii)' '
echo content >>file &&
git add file &&
git commit -m "$M512" &&
git format-patch --stdout -1 >patch &&
sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
test_cmp expect subject
'
M8="föö bar "
M64=$M8$M8$M8$M8$M8$M8$M8$M8
M512=$M64$M64$M64$M64$M64$M64$M64$M64
cat >expect <<'EOF'
Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
=?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
EOF
test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
rm -rf patches/ &&
echo content >>file &&
git add file &&
git commit -m "$M512" &&
git format-patch --stdout -1 >patch &&
sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
test_cmp expect subject
'
test_done test_done

9
utf8.c
View File

@ -405,6 +405,15 @@ new_line:
} }
} }
int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
int indent, int indent2, int width)
{
char *tmp = xstrndup(data, len);
int r = strbuf_add_wrapped_text(buf, tmp, indent, indent2, width);
free(tmp);
return r;
}
int is_encoding_utf8(const char *name) int is_encoding_utf8(const char *name)
{ {
if (!name) if (!name)

2
utf8.h
View File

@ -10,6 +10,8 @@ int is_encoding_utf8(const char *name);
int strbuf_add_wrapped_text(struct strbuf *buf, int strbuf_add_wrapped_text(struct strbuf *buf,
const char *text, int indent, int indent2, int width); const char *text, int indent, int indent2, int width);
int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
int indent, int indent2, int width);
#ifndef NO_ICONV #ifndef NO_ICONV
char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding); char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding);