View Javadoc
1   /*
2    * Copyright (C) 2008-2009, Google Inc.
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  
44  package org.eclipse.jgit.revwalk;
45  
46  import static java.nio.charset.StandardCharsets.ISO_8859_1;
47  import static java.nio.charset.StandardCharsets.UTF_8;
48  import static org.junit.Assert.assertEquals;
49  import static org.junit.Assert.assertNotNull;
50  import static org.junit.Assert.assertNull;
51  import static org.junit.Assert.assertSame;
52  import static org.junit.Assert.assertTrue;
53  import static org.junit.Assert.fail;
54  
55  import java.io.ByteArrayOutputStream;
56  import java.io.UnsupportedEncodingException;
57  import java.nio.charset.IllegalCharsetNameException;
58  import java.nio.charset.UnsupportedCharsetException;
59  import java.util.TimeZone;
60  
61  import org.eclipse.jgit.junit.RepositoryTestCase;
62  import org.eclipse.jgit.lib.CommitBuilder;
63  import org.eclipse.jgit.lib.Constants;
64  import org.eclipse.jgit.lib.ObjectId;
65  import org.eclipse.jgit.lib.ObjectInserter;
66  import org.eclipse.jgit.lib.PersonIdent;
67  import org.junit.Test;
68  
69  public class RevCommitParseTest extends RepositoryTestCase {
70  	@Test
71  	public void testParse_NoParents() throws Exception {
72  		final ObjectId treeId = id("9788669ad918b6fcce64af8882fc9a81cb6aba67");
73  		final String authorName = "A U. Thor";
74  		final String authorEmail = "a_u_thor@example.com";
75  		final int authorTime = 1218123387;
76  		final String authorTimeZone = "+0700";
77  
78  		final String committerName = "C O. Miter";
79  		final String committerEmail = "comiter@example.com";
80  		final int committerTime = 1218123390;
81  		final String committerTimeZone = "-0500";
82  		final StringBuilder body = new StringBuilder();
83  
84  		body.append("tree ");
85  		body.append(treeId.name());
86  		body.append("\n");
87  
88  		body.append("author ");
89  		body.append(authorName);
90  		body.append(" <");
91  		body.append(authorEmail);
92  		body.append("> ");
93  		body.append(authorTime);
94  		body.append(" ");
95  		body.append(authorTimeZone);
96  		body.append(" \n");
97  
98  		body.append("committer ");
99  		body.append(committerName);
100 		body.append(" <");
101 		body.append(committerEmail);
102 		body.append("> ");
103 		body.append(committerTime);
104 		body.append(" ");
105 		body.append(committerTimeZone);
106 		body.append("\n");
107 
108 		body.append("\n");
109 
110 		final RevWalk rw = new RevWalk(db);
111 		final RevCommit c;
112 
113 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
114 		assertNull(c.getTree());
115 		assertNull(c.parents);
116 
117 		c.parseCanonical(rw, body.toString().getBytes(UTF_8));
118 		assertNotNull(c.getTree());
119 		assertEquals(treeId, c.getTree().getId());
120 		assertSame(rw.lookupTree(treeId), c.getTree());
121 
122 		assertNotNull(c.parents);
123 		assertEquals(0, c.parents.length);
124 		assertEquals("", c.getFullMessage());
125 
126 		final PersonIdent cAuthor = c.getAuthorIdent();
127 		assertNotNull(cAuthor);
128 		assertEquals(authorName, cAuthor.getName());
129 		assertEquals(authorEmail, cAuthor.getEmailAddress());
130 		assertEquals((long)authorTime * 1000, cAuthor.getWhen().getTime());
131 		assertEquals(TimeZone.getTimeZone("GMT" + authorTimeZone), cAuthor.getTimeZone());
132 
133 		final PersonIdent cCommitter = c.getCommitterIdent();
134 		assertNotNull(cCommitter);
135 		assertEquals(committerName, cCommitter.getName());
136 		assertEquals(committerEmail, cCommitter.getEmailAddress());
137 		assertEquals((long)committerTime * 1000, cCommitter.getWhen().getTime());
138 		assertEquals(TimeZone.getTimeZone("GMT" + committerTimeZone), cCommitter.getTimeZone());
139 	}
140 
141 	private RevCommit create(String msg) throws Exception {
142 		final StringBuilder b = new StringBuilder();
143 		b.append("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n");
144 		b.append("author A U. Thor <a_u_thor@example.com> 1218123387 +0700\n");
145 		b.append("committer C O. Miter <c@example.com> 1218123390 -0500\n");
146 		b.append("\n");
147 		b.append(msg);
148 
149 		final RevCommit c;
150 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
151 		c.parseCanonical(new RevWalk(db), b.toString().getBytes(UTF_8));
152 		return c;
153 	}
154 
155 	@Test
156 	public void testParse_WeirdHeaderOnlyCommit() throws Exception {
157 		final StringBuilder b = new StringBuilder();
158 		b.append("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n");
159 		b.append("author A U. Thor <a_u_thor@example.com> 1218123387 +0700\n");
160 		b.append("committer C O. Miter <c@example.com> 1218123390 -0500\n");
161 
162 		final RevCommit c;
163 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
164 		c.parseCanonical(new RevWalk(db), b.toString().getBytes(UTF_8));
165 
166 		assertEquals("", c.getFullMessage());
167 		assertEquals("", c.getShortMessage());
168 	}
169 
170 	@Test
171 	public void testParse_incompleteAuthorAndCommitter() throws Exception {
172 		final StringBuilder b = new StringBuilder();
173 		b.append("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n");
174 		b.append("author <a_u_thor@example.com> 1218123387 +0700\n");
175 		b.append("committer <> 1218123390 -0500\n");
176 
177 		final RevCommit c;
178 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
179 		c.parseCanonical(new RevWalk(db), b.toString().getBytes(UTF_8));
180 
181 		assertEquals(new PersonIdent("", "a_u_thor@example.com", 1218123387000l, 7), c.getAuthorIdent());
182 		assertEquals(new PersonIdent("", "", 1218123390000l, -5), c.getCommitterIdent());
183 	}
184 
185 	@Test
186 	public void testParse_implicit_UTF8_encoded() throws Exception {
187 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
188 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
189 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(UTF_8));
190 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
191 		b.write("\n".getBytes(UTF_8));
192 		b.write("Sm\u00f6rg\u00e5sbord\n".getBytes(UTF_8));
193 		b.write("\n".getBytes(UTF_8));
194 		b.write("\u304d\u308c\u3044\n".getBytes(UTF_8));
195 		final RevCommit c;
196 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
197 		c.parseCanonical(new RevWalk(db), b.toByteArray());
198 
199 		assertSame(UTF_8, c.getEncoding());
200 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
201 		assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage());
202 		assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c.getFullMessage());
203 	}
204 
205 	@Test
206 	public void testParse_implicit_mixed_encoded() throws Exception {
207 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
208 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
209 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(ISO_8859_1));
210 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
211 		b.write("\n".getBytes(UTF_8));
212 		b.write("Sm\u00f6rg\u00e5sbord\n".getBytes(UTF_8));
213 		b.write("\n".getBytes(UTF_8));
214 		b.write("\u304d\u308c\u3044\n".getBytes(UTF_8));
215 		final RevCommit c;
216 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
217 		c.parseCanonical(new RevWalk(db), b.toByteArray());
218 
219 		assertSame(UTF_8, c.getEncoding());
220 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
221 		assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage());
222 		assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c.getFullMessage());
223 	}
224 
225 	/**
226 	 * Test parsing of a commit whose encoding is given and works.
227 	 *
228 	 * @throws Exception
229 	 */
230 	@Test
231 	public void testParse_explicit_encoded() throws Exception {
232 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
233 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes("EUC-JP"));
234 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes("EUC-JP"));
235 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes("EUC-JP"));
236 		b.write("encoding euc_JP\n".getBytes("EUC-JP"));
237 		b.write("\n".getBytes("EUC-JP"));
238 		b.write("\u304d\u308c\u3044\n".getBytes("EUC-JP"));
239 		b.write("\n".getBytes("EUC-JP"));
240 		b.write("Hi\n".getBytes("EUC-JP"));
241 		final RevCommit c;
242 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
243 		c.parseCanonical(new RevWalk(db), b.toByteArray());
244 
245 		assertEquals("EUC-JP", c.getEncoding().name());
246 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
247 		assertEquals("\u304d\u308c\u3044", c.getShortMessage());
248 		assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage());
249 	}
250 
251 	/**
252 	 * This is a twisted case, but show what we expect here. We can revise the
253 	 * expectations provided this case is updated.
254 	 *
255 	 * What happens here is that an encoding us given, but data is not encoded
256 	 * that way (and we can detect it), so we try other encodings.
257 	 *
258 	 * @throws Exception
259 	 */
260 	@Test
261 	public void testParse_explicit_bad_encoded() throws Exception {
262 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
263 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
264 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(ISO_8859_1));
265 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
266 		b.write("encoding EUC-JP\n".getBytes(UTF_8));
267 		b.write("\n".getBytes(UTF_8));
268 		b.write("\u304d\u308c\u3044\n".getBytes(UTF_8));
269 		b.write("\n".getBytes(UTF_8));
270 		b.write("Hi\n".getBytes(UTF_8));
271 		final RevCommit c;
272 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
273 		c.parseCanonical(new RevWalk(db), b.toByteArray());
274 
275 		assertEquals("EUC-JP", c.getEncoding().name());
276 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
277 		assertEquals("\u304d\u308c\u3044", c.getShortMessage());
278 		assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage());
279 	}
280 
281 	/**
282 	 * This is a twisted case too, but show what we expect here. We can revise the
283 	 * expectations provided this case is updated.
284 	 *
285 	 * What happens here is that an encoding us given, but data is not encoded
286 	 * that way (and we can detect it), so we try other encodings. Here data could
287 	 * actually be decoded in the stated encoding, but we override using UTF-8.
288 	 *
289 	 * @throws Exception
290 	 */
291 	@Test
292 	public void testParse_explicit_bad_encoded2() throws Exception {
293 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
294 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
295 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(UTF_8));
296 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
297 		b.write("encoding ISO-8859-1\n".getBytes(UTF_8));
298 		b.write("\n".getBytes(UTF_8));
299 		b.write("\u304d\u308c\u3044\n".getBytes(UTF_8));
300 		b.write("\n".getBytes(UTF_8));
301 		b.write("Hi\n".getBytes(UTF_8));
302 		final RevCommit c;
303 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
304 		c.parseCanonical(new RevWalk(db), b.toByteArray());
305 
306 		assertEquals("ISO-8859-1", c.getEncoding().name());
307 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
308 		assertEquals("\u304d\u308c\u3044", c.getShortMessage());
309 		assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage());
310 	}
311 
312 	@Test
313 	public void testParse_incorrectUtf8Name() throws Exception {
314 		ByteArrayOutputStream b = new ByteArrayOutputStream();
315 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n"
316 				.getBytes(UTF_8));
317 		b.write("author au <a@example.com> 1218123387 +0700\n".getBytes(UTF_8));
318 		b.write("committer co <c@example.com> 1218123390 -0500\n"
319 				.getBytes(UTF_8));
320 		b.write("encoding 'utf8'\n".getBytes(UTF_8));
321 		b.write("\n".getBytes(UTF_8));
322 		b.write("Sm\u00f6rg\u00e5sbord\n".getBytes(UTF_8));
323 
324 		RevCommit c = new RevCommit(
325 				id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
326 		c.parseCanonical(new RevWalk(db), b.toByteArray());
327 		assertEquals("'utf8'", c.getEncodingName());
328 		assertEquals("Sm\u00f6rg\u00e5sbord\n", c.getFullMessage());
329 
330 		try {
331 			c.getEncoding();
332 			fail("Expected " + IllegalCharsetNameException.class);
333 		} catch (IllegalCharsetNameException badName) {
334 			assertEquals("'utf8'", badName.getMessage());
335 		}
336 	}
337 
338 	@Test
339 	public void testParse_illegalEncoding() throws Exception {
340 		ByteArrayOutputStream b = new ByteArrayOutputStream();
341 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
342 		b.write("author au <a@example.com> 1218123387 +0700\n".getBytes(UTF_8));
343 		b.write("committer co <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
344 		b.write("encoding utf-8logoutputencoding=gbk\n".getBytes(UTF_8));
345 		b.write("\n".getBytes(UTF_8));
346 		b.write("message\n".getBytes(UTF_8));
347 
348 		RevCommit c = new RevCommit(
349 				id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
350 		c.parseCanonical(new RevWalk(db), b.toByteArray());
351 		assertEquals("utf-8logoutputencoding=gbk", c.getEncodingName());
352 		assertEquals("message\n", c.getFullMessage());
353 		assertEquals("message", c.getShortMessage());
354 		assertTrue(c.getFooterLines().isEmpty());
355 		assertEquals("au", c.getAuthorIdent().getName());
356 
357 		try {
358 			c.getEncoding();
359 			fail("Expected " + IllegalCharsetNameException.class);
360 		} catch (IllegalCharsetNameException badName) {
361 			assertEquals("utf-8logoutputencoding=gbk", badName.getMessage());
362 		}
363 	}
364 
365 	@Test
366 	public void testParse_unsupportedEncoding() throws Exception {
367 		ByteArrayOutputStream b = new ByteArrayOutputStream();
368 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
369 		b.write("author au <a@example.com> 1218123387 +0700\n".getBytes(UTF_8));
370 		b.write("committer co <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
371 		b.write("encoding it_IT.UTF8\n".getBytes(UTF_8));
372 		b.write("\n".getBytes(UTF_8));
373 		b.write("message\n".getBytes(UTF_8));
374 
375 		RevCommit c = new RevCommit(
376 				id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
377 		c.parseCanonical(new RevWalk(db), b.toByteArray());
378 		assertEquals("it_IT.UTF8", c.getEncodingName());
379 		assertEquals("message\n", c.getFullMessage());
380 		assertEquals("message", c.getShortMessage());
381 		assertTrue(c.getFooterLines().isEmpty());
382 		assertEquals("au", c.getAuthorIdent().getName());
383 
384 		try {
385 			c.getEncoding();
386 			fail("Expected " + UnsupportedCharsetException.class);
387 		} catch (UnsupportedCharsetException badName) {
388 			assertEquals("it_IT.UTF8", badName.getMessage());
389 		}
390 	}
391 
392 	@Test
393 	public void testParse_NoMessage() throws Exception {
394 		final String msg = "";
395 		final RevCommit c = create(msg);
396 		assertEquals(msg, c.getFullMessage());
397 		assertEquals(msg, c.getShortMessage());
398 	}
399 
400 	@Test
401 	public void testParse_OnlyLFMessage() throws Exception {
402 		final RevCommit c = create("\n");
403 		assertEquals("\n", c.getFullMessage());
404 		assertEquals("", c.getShortMessage());
405 	}
406 
407 	@Test
408 	public void testParse_ShortLineOnlyNoLF() throws Exception {
409 		final String shortMsg = "This is a short message.";
410 		final RevCommit c = create(shortMsg);
411 		assertEquals(shortMsg, c.getFullMessage());
412 		assertEquals(shortMsg, c.getShortMessage());
413 	}
414 
415 	@Test
416 	public void testParse_ShortLineOnlyEndLF() throws Exception {
417 		final String shortMsg = "This is a short message.";
418 		final String fullMsg = shortMsg + "\n";
419 		final RevCommit c = create(fullMsg);
420 		assertEquals(fullMsg, c.getFullMessage());
421 		assertEquals(shortMsg, c.getShortMessage());
422 	}
423 
424 	@Test
425 	public void testParse_ShortLineOnlyEmbeddedLF() throws Exception {
426 		final String fullMsg = "This is a\nshort message.";
427 		final String shortMsg = fullMsg.replace('\n', ' ');
428 		final RevCommit c = create(fullMsg);
429 		assertEquals(fullMsg, c.getFullMessage());
430 		assertEquals(shortMsg, c.getShortMessage());
431 	}
432 
433 	@Test
434 	public void testParse_ShortLineOnlyEmbeddedAndEndingLF() throws Exception {
435 		final String fullMsg = "This is a\nshort message.\n";
436 		final String shortMsg = "This is a short message.";
437 		final RevCommit c = create(fullMsg);
438 		assertEquals(fullMsg, c.getFullMessage());
439 		assertEquals(shortMsg, c.getShortMessage());
440 	}
441 
442 	@Test
443 	public void testParse_GitStyleMessage() throws Exception {
444 		final String shortMsg = "This fixes a bug.";
445 		final String body = "We do it with magic and pixie dust and stuff.\n"
446 				+ "\n" + "Signed-off-by: A U. Thor <author@example.com>\n";
447 		final String fullMsg = shortMsg + "\n" + "\n" + body;
448 		final RevCommit c = create(fullMsg);
449 		assertEquals(fullMsg, c.getFullMessage());
450 		assertEquals(shortMsg, c.getShortMessage());
451 	}
452 
453 	@Test
454 	public void testParse_PublicParseMethod()
455 			throws UnsupportedEncodingException {
456 		CommitBuilder src = new CommitBuilder();
457 		try (ObjectInserter.Formatter fmt = new ObjectInserter.Formatter()) {
458 			src.setTreeId(fmt.idFor(Constants.OBJ_TREE, new byte[] {}));
459 		}
460 		src.setAuthor(author);
461 		src.setCommitter(committer);
462 		src.setMessage("Test commit\n\nThis is a test.\n");
463 
464 		RevCommit p = RevCommit.parse(src.build());
465 		assertEquals(src.getTreeId(), p.getTree());
466 		assertEquals(0, p.getParentCount());
467 		assertEquals(author, p.getAuthorIdent());
468 		assertEquals(committer, p.getCommitterIdent());
469 		assertEquals("Test commit", p.getShortMessage());
470 		assertEquals(src.getMessage(), p.getFullMessage());
471 	}
472 
473 	@Test
474 	public void testParse_GitStyleMessageWithCRLF() throws Exception {
475 		final String shortMsgIn = "This fixes a\r\nbug.\r\n\r\n";
476 		final String shortMsg = "This fixes a bug.";
477 		final String body = "We do it with magic and pixie dust\r\nand stuff.\r\n"
478 				+ "\r\n\r\n"
479 				+ "Signed-off-by: A U. Thor <author@example.com>\r\n";
480 		final String fullMsg = shortMsgIn + "\r\n" + "\r\n" + body;
481 		final RevCommit c = create(fullMsg);
482 		assertEquals(fullMsg, c.getFullMessage());
483 		assertEquals(shortMsg, c.getShortMessage());
484 	}
485 
486 	private static ObjectId id(String str) {
487 		return ObjectId.fromString(str);
488 	}
489 
490 	@Test
491 	public void testParse_gpgSig() throws Exception {
492 		String commit = "tree e3a1035abd2b319bb01e57d69b0ba6cab289297e\n" +
493 		"parent 54e895b87c0768d2317a2b17062e3ad9f76a8105\n" +
494 		"committer A U Thor <author@xample.com 1528968566 +0200\n" +
495 		"gpgsig -----BEGIN PGP SIGNATURE-----\n" +
496 		" \n" +
497 		" wsBcBAABCAAQBQJbGB4pCRBK7hj4Ov3rIwAAdHIIAENrvz23867ZgqrmyPemBEZP\n" +
498 		" U24B1Tlq/DWvce2buaxmbNQngKZ0pv2s8VMc11916WfTIC9EKvioatmpjduWvhqj\n" +
499 		" znQTFyiMor30pyYsfrqFuQZvqBW01o8GEWqLg8zjf9Rf0R3LlOEw86aT8CdHRlm6\n" +
500 		" wlb22xb8qoX4RB+LYfz7MhK5F+yLOPXZdJnAVbuyoMGRnDpwdzjL5Hj671+XJxN5\n" +
501 		" SasRdhxkkfw/ZnHxaKEc4juMz8Nziz27elRwhOQqlTYoXNJnsV//wy5Losd7aKi1\n" +
502 		" xXXyUpndEOmT0CIcKHrN/kbYoVL28OJaxoBuva3WYQaRrzEe3X02NMxZe9gkSqA=\n" +
503 		" =TClh\n" +
504 		" -----END PGP SIGNATURE-----\n" +
505 		"some other header\n\n" +
506 		"commit message";
507 
508 		final RevCommit c;
509 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
510 		c.parseCanonical(new RevWalk(db), commit.getBytes(UTF_8));
511 		String gpgSig = new String(c.getRawGpgSignature(), UTF_8);
512 		assertTrue(gpgSig.startsWith("-----BEGIN"));
513 		assertTrue(gpgSig.endsWith("END PGP SIGNATURE-----"));
514 	}
515 
516 	@Test
517 	public void testParse_NoGpgSig() throws Exception {
518 		final RevCommit c = create("a message");
519 		assertNull(c.getRawGpgSignature());
520 	}
521 }