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 RevCommit c;
111 
112 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
113 		assertNull(c.getTree());
114 		assertNull(c.parents);
115 
116 		try (RevWalk rw = new RevWalk(db)) {
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 		try (RevWalk rw = new RevWalk(db)) {
152 			c.parseCanonical(rw, b.toString().getBytes(UTF_8));
153 			return c;
154 		}
155 	}
156 
157 	@Test
158 	public void testParse_WeirdHeaderOnlyCommit() throws Exception {
159 		final StringBuilder b = new StringBuilder();
160 		b.append("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n");
161 		b.append("author A U. Thor <a_u_thor@example.com> 1218123387 +0700\n");
162 		b.append("committer C O. Miter <c@example.com> 1218123390 -0500\n");
163 
164 		final RevCommit c;
165 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
166 		try (RevWalk rw = new RevWalk(db)) {
167 			c.parseCanonical(rw, b.toString().getBytes(UTF_8));
168 		}
169 		assertEquals("", c.getFullMessage());
170 		assertEquals("", c.getShortMessage());
171 	}
172 
173 	@Test
174 	public void testParse_incompleteAuthorAndCommitter() throws Exception {
175 		final StringBuilder b = new StringBuilder();
176 		b.append("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n");
177 		b.append("author <a_u_thor@example.com> 1218123387 +0700\n");
178 		b.append("committer <> 1218123390 -0500\n");
179 
180 		final RevCommit c;
181 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
182 		try (RevWalk rw = new RevWalk(db)) {
183 			c.parseCanonical(rw, b.toString().getBytes(UTF_8));
184 		}
185 		assertEquals(new PersonIdent("", "a_u_thor@example.com", 1218123387000l, 7), c.getAuthorIdent());
186 		assertEquals(new PersonIdent("", "", 1218123390000l, -5), c.getCommitterIdent());
187 	}
188 
189 	@Test
190 	public void testParse_implicit_UTF8_encoded() throws Exception {
191 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
192 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
193 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(UTF_8));
194 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
195 		b.write("\n".getBytes(UTF_8));
196 		b.write("Sm\u00f6rg\u00e5sbord\n".getBytes(UTF_8));
197 		b.write("\n".getBytes(UTF_8));
198 		b.write("\u304d\u308c\u3044\n".getBytes(UTF_8));
199 		final RevCommit c;
200 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
201 		try (RevWalk rw = new RevWalk(db)) {
202 			c.parseCanonical(rw, b.toByteArray());
203 		}
204 		assertSame(UTF_8, c.getEncoding());
205 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
206 		assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage());
207 		assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c.getFullMessage());
208 	}
209 
210 	@Test
211 	public void testParse_implicit_mixed_encoded() throws Exception {
212 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
213 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
214 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(ISO_8859_1));
215 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
216 		b.write("\n".getBytes(UTF_8));
217 		b.write("Sm\u00f6rg\u00e5sbord\n".getBytes(UTF_8));
218 		b.write("\n".getBytes(UTF_8));
219 		b.write("\u304d\u308c\u3044\n".getBytes(UTF_8));
220 		final RevCommit c;
221 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
222 		try (RevWalk rw = new RevWalk(db)) {
223 			c.parseCanonical(rw, b.toByteArray());
224 		}
225 		assertSame(UTF_8, c.getEncoding());
226 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
227 		assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage());
228 		assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c.getFullMessage());
229 	}
230 
231 	/**
232 	 * Test parsing of a commit whose encoding is given and works.
233 	 *
234 	 * @throws Exception
235 	 */
236 	@Test
237 	public void testParse_explicit_encoded() throws Exception {
238 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
239 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes("EUC-JP"));
240 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes("EUC-JP"));
241 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes("EUC-JP"));
242 		b.write("encoding euc_JP\n".getBytes("EUC-JP"));
243 		b.write("\n".getBytes("EUC-JP"));
244 		b.write("\u304d\u308c\u3044\n".getBytes("EUC-JP"));
245 		b.write("\n".getBytes("EUC-JP"));
246 		b.write("Hi\n".getBytes("EUC-JP"));
247 		final RevCommit c;
248 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
249 		try (RevWalk rw = new RevWalk(db)) {
250 			c.parseCanonical(rw, b.toByteArray());
251 		}
252 
253 		assertEquals("EUC-JP", c.getEncoding().name());
254 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
255 		assertEquals("\u304d\u308c\u3044", c.getShortMessage());
256 		assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage());
257 	}
258 
259 	/**
260 	 * This is a twisted case, but show what we expect here. We can revise the
261 	 * expectations provided this case is updated.
262 	 *
263 	 * What happens here is that an encoding us given, but data is not encoded
264 	 * that way (and we can detect it), so we try other encodings.
265 	 *
266 	 * @throws Exception
267 	 */
268 	@Test
269 	public void testParse_explicit_bad_encoded() throws Exception {
270 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
271 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
272 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(ISO_8859_1));
273 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
274 		b.write("encoding EUC-JP\n".getBytes(UTF_8));
275 		b.write("\n".getBytes(UTF_8));
276 		b.write("\u304d\u308c\u3044\n".getBytes(UTF_8));
277 		b.write("\n".getBytes(UTF_8));
278 		b.write("Hi\n".getBytes(UTF_8));
279 		final RevCommit c;
280 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
281 		try (RevWalk rw = new RevWalk(db)) {
282 			c.parseCanonical(rw, b.toByteArray());
283 		}
284 
285 		assertEquals("EUC-JP", c.getEncoding().name());
286 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
287 		assertEquals("\u304d\u308c\u3044", c.getShortMessage());
288 		assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage());
289 	}
290 
291 	/**
292 	 * This is a twisted case too, but show what we expect here. We can revise the
293 	 * expectations provided this case is updated.
294 	 *
295 	 * What happens here is that an encoding us given, but data is not encoded
296 	 * that way (and we can detect it), so we try other encodings. Here data could
297 	 * actually be decoded in the stated encoding, but we override using UTF-8.
298 	 *
299 	 * @throws Exception
300 	 */
301 	@Test
302 	public void testParse_explicit_bad_encoded2() throws Exception {
303 		final ByteArrayOutputStream b = new ByteArrayOutputStream();
304 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
305 		b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(UTF_8));
306 		b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
307 		b.write("encoding ISO-8859-1\n".getBytes(UTF_8));
308 		b.write("\n".getBytes(UTF_8));
309 		b.write("\u304d\u308c\u3044\n".getBytes(UTF_8));
310 		b.write("\n".getBytes(UTF_8));
311 		b.write("Hi\n".getBytes(UTF_8));
312 		final RevCommit c;
313 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id
314 		try (RevWalk rw = new RevWalk(db)) {
315 			c.parseCanonical(rw, b.toByteArray());
316 		}
317 
318 		assertEquals("ISO-8859-1", c.getEncoding().name());
319 		assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName());
320 		assertEquals("\u304d\u308c\u3044", c.getShortMessage());
321 		assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage());
322 	}
323 
324 	@Test
325 	public void testParse_incorrectUtf8Name() throws Exception {
326 		ByteArrayOutputStream b = new ByteArrayOutputStream();
327 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n"
328 				.getBytes(UTF_8));
329 		b.write("author au <a@example.com> 1218123387 +0700\n".getBytes(UTF_8));
330 		b.write("committer co <c@example.com> 1218123390 -0500\n"
331 				.getBytes(UTF_8));
332 		b.write("encoding 'utf8'\n".getBytes(UTF_8));
333 		b.write("\n".getBytes(UTF_8));
334 		b.write("Sm\u00f6rg\u00e5sbord\n".getBytes(UTF_8));
335 
336 		RevCommit c = new RevCommit(
337 				id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
338 		try (RevWalk rw = new RevWalk(db)) {
339 			c.parseCanonical(rw, b.toByteArray());
340 		}
341 		assertEquals("'utf8'", c.getEncodingName());
342 		assertEquals("Sm\u00f6rg\u00e5sbord\n", c.getFullMessage());
343 
344 		try {
345 			c.getEncoding();
346 			fail("Expected " + IllegalCharsetNameException.class);
347 		} catch (IllegalCharsetNameException badName) {
348 			assertEquals("'utf8'", badName.getMessage());
349 		}
350 	}
351 
352 	@Test
353 	public void testParse_illegalEncoding() throws Exception {
354 		ByteArrayOutputStream b = new ByteArrayOutputStream();
355 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
356 		b.write("author au <a@example.com> 1218123387 +0700\n".getBytes(UTF_8));
357 		b.write("committer co <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
358 		b.write("encoding utf-8logoutputencoding=gbk\n".getBytes(UTF_8));
359 		b.write("\n".getBytes(UTF_8));
360 		b.write("message\n".getBytes(UTF_8));
361 
362 		RevCommit c = new RevCommit(
363 				id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
364 		try (RevWalk rw = new RevWalk(db)) {
365 			c.parseCanonical(rw, b.toByteArray());
366 		}
367 		assertEquals("utf-8logoutputencoding=gbk", c.getEncodingName());
368 		assertEquals("message\n", c.getFullMessage());
369 		assertEquals("message", c.getShortMessage());
370 		assertTrue(c.getFooterLines().isEmpty());
371 		assertEquals("au", c.getAuthorIdent().getName());
372 
373 		try {
374 			c.getEncoding();
375 			fail("Expected " + IllegalCharsetNameException.class);
376 		} catch (IllegalCharsetNameException badName) {
377 			assertEquals("utf-8logoutputencoding=gbk", badName.getMessage());
378 		}
379 	}
380 
381 	@Test
382 	public void testParse_unsupportedEncoding() throws Exception {
383 		ByteArrayOutputStream b = new ByteArrayOutputStream();
384 		b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8));
385 		b.write("author au <a@example.com> 1218123387 +0700\n".getBytes(UTF_8));
386 		b.write("committer co <c@example.com> 1218123390 -0500\n".getBytes(UTF_8));
387 		b.write("encoding it_IT.UTF8\n".getBytes(UTF_8));
388 		b.write("\n".getBytes(UTF_8));
389 		b.write("message\n".getBytes(UTF_8));
390 
391 		RevCommit c = new RevCommit(
392 				id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
393 		try (RevWalk rw = new RevWalk(db)) {
394 			c.parseCanonical(rw, b.toByteArray());
395 		}
396 		assertEquals("it_IT.UTF8", c.getEncodingName());
397 		assertEquals("message\n", c.getFullMessage());
398 		assertEquals("message", c.getShortMessage());
399 		assertTrue(c.getFooterLines().isEmpty());
400 		assertEquals("au", c.getAuthorIdent().getName());
401 
402 		try {
403 			c.getEncoding();
404 			fail("Expected " + UnsupportedCharsetException.class);
405 		} catch (UnsupportedCharsetException badName) {
406 			assertEquals("it_IT.UTF8", badName.getMessage());
407 		}
408 	}
409 
410 	@Test
411 	public void testParse_NoMessage() throws Exception {
412 		final String msg = "";
413 		final RevCommit c = create(msg);
414 		assertEquals(msg, c.getFullMessage());
415 		assertEquals(msg, c.getShortMessage());
416 	}
417 
418 	@Test
419 	public void testParse_OnlyLFMessage() throws Exception {
420 		final RevCommit c = create("\n");
421 		assertEquals("\n", c.getFullMessage());
422 		assertEquals("", c.getShortMessage());
423 	}
424 
425 	@Test
426 	public void testParse_ShortLineOnlyNoLF() throws Exception {
427 		final String shortMsg = "This is a short message.";
428 		final RevCommit c = create(shortMsg);
429 		assertEquals(shortMsg, c.getFullMessage());
430 		assertEquals(shortMsg, c.getShortMessage());
431 	}
432 
433 	@Test
434 	public void testParse_ShortLineOnlyEndLF() throws Exception {
435 		final String shortMsg = "This is a short message.";
436 		final String fullMsg = shortMsg + "\n";
437 		final RevCommit c = create(fullMsg);
438 		assertEquals(fullMsg, c.getFullMessage());
439 		assertEquals(shortMsg, c.getShortMessage());
440 	}
441 
442 	@Test
443 	public void testParse_ShortLineOnlyEmbeddedLF() throws Exception {
444 		final String fullMsg = "This is a\nshort message.";
445 		final String shortMsg = fullMsg.replace('\n', ' ');
446 		final RevCommit c = create(fullMsg);
447 		assertEquals(fullMsg, c.getFullMessage());
448 		assertEquals(shortMsg, c.getShortMessage());
449 	}
450 
451 	@Test
452 	public void testParse_ShortLineOnlyEmbeddedAndEndingLF() throws Exception {
453 		final String fullMsg = "This is a\nshort message.\n";
454 		final String shortMsg = "This is a short message.";
455 		final RevCommit c = create(fullMsg);
456 		assertEquals(fullMsg, c.getFullMessage());
457 		assertEquals(shortMsg, c.getShortMessage());
458 	}
459 
460 	@Test
461 	public void testParse_GitStyleMessage() throws Exception {
462 		final String shortMsg = "This fixes a bug.";
463 		final String body = "We do it with magic and pixie dust and stuff.\n"
464 				+ "\n" + "Signed-off-by: A U. Thor <author@example.com>\n";
465 		final String fullMsg = shortMsg + "\n" + "\n" + body;
466 		final RevCommit c = create(fullMsg);
467 		assertEquals(fullMsg, c.getFullMessage());
468 		assertEquals(shortMsg, c.getShortMessage());
469 	}
470 
471 	@Test
472 	public void testParse_PublicParseMethod()
473 			throws UnsupportedEncodingException {
474 		CommitBuilder src = new CommitBuilder();
475 		try (ObjectInserter.Formatter fmt = new ObjectInserter.Formatter()) {
476 			src.setTreeId(fmt.idFor(Constants.OBJ_TREE, new byte[] {}));
477 		}
478 		src.setAuthor(author);
479 		src.setCommitter(committer);
480 		src.setMessage("Test commit\n\nThis is a test.\n");
481 
482 		RevCommit p = RevCommit.parse(src.build());
483 		assertEquals(src.getTreeId(), p.getTree());
484 		assertEquals(0, p.getParentCount());
485 		assertEquals(author, p.getAuthorIdent());
486 		assertEquals(committer, p.getCommitterIdent());
487 		assertEquals("Test commit", p.getShortMessage());
488 		assertEquals(src.getMessage(), p.getFullMessage());
489 	}
490 
491 	@Test
492 	public void testParse_GitStyleMessageWithCRLF() throws Exception {
493 		final String shortMsgIn = "This fixes a\r\nbug.\r\n\r\n";
494 		final String shortMsg = "This fixes a bug.";
495 		final String body = "We do it with magic and pixie dust\r\nand stuff.\r\n"
496 				+ "\r\n\r\n"
497 				+ "Signed-off-by: A U. Thor <author@example.com>\r\n";
498 		final String fullMsg = shortMsgIn + "\r\n" + "\r\n" + body;
499 		final RevCommit c = create(fullMsg);
500 		assertEquals(fullMsg, c.getFullMessage());
501 		assertEquals(shortMsg, c.getShortMessage());
502 	}
503 
504 	private static ObjectId id(String str) {
505 		return ObjectId.fromString(str);
506 	}
507 
508 	@Test
509 	public void testParse_gpgSig() throws Exception {
510 		String commit = "tree e3a1035abd2b319bb01e57d69b0ba6cab289297e\n" +
511 		"parent 54e895b87c0768d2317a2b17062e3ad9f76a8105\n" +
512 		"committer A U Thor <author@xample.com 1528968566 +0200\n" +
513 		"gpgsig -----BEGIN PGP SIGNATURE-----\n" +
514 		" \n" +
515 		" wsBcBAABCAAQBQJbGB4pCRBK7hj4Ov3rIwAAdHIIAENrvz23867ZgqrmyPemBEZP\n" +
516 		" U24B1Tlq/DWvce2buaxmbNQngKZ0pv2s8VMc11916WfTIC9EKvioatmpjduWvhqj\n" +
517 		" znQTFyiMor30pyYsfrqFuQZvqBW01o8GEWqLg8zjf9Rf0R3LlOEw86aT8CdHRlm6\n" +
518 		" wlb22xb8qoX4RB+LYfz7MhK5F+yLOPXZdJnAVbuyoMGRnDpwdzjL5Hj671+XJxN5\n" +
519 		" SasRdhxkkfw/ZnHxaKEc4juMz8Nziz27elRwhOQqlTYoXNJnsV//wy5Losd7aKi1\n" +
520 		" xXXyUpndEOmT0CIcKHrN/kbYoVL28OJaxoBuva3WYQaRrzEe3X02NMxZe9gkSqA=\n" +
521 		" =TClh\n" +
522 		" -----END PGP SIGNATURE-----\n" +
523 		"some other header\n\n" +
524 		"commit message";
525 
526 		final RevCommit c;
527 		c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67"));
528 		try (RevWalk rw = new RevWalk(db)) {
529 			c.parseCanonical(rw, commit.getBytes(UTF_8));
530 		}
531 		String gpgSig = new String(c.getRawGpgSignature(), UTF_8);
532 		assertTrue(gpgSig.startsWith("-----BEGIN"));
533 		assertTrue(gpgSig.endsWith("END PGP SIGNATURE-----"));
534 	}
535 
536 	@Test
537 	public void testParse_NoGpgSig() throws Exception {
538 		final RevCommit c = create("a message");
539 		assertNull(c.getRawGpgSignature());
540 	}
541 }