Allow to replace existing Change-Id
[jgit.git] / org.eclipse.jgit.test / tst / org / eclipse / jgit / util / ChangeIdUtilTest.java
bloba15cadfbda4f3c515f54a1a5f0e366ad4be1ee83
1 /*
2 * Copyright (C) 2010, Robin Rosenberg
3 * Copyright (C) 2009, Google, Inc.
4 * and other copyright owners as documented in the project's IP log.
6 * This program and the accompanying materials are made available
7 * under the terms of the Eclipse Distribution License v1.0 which
8 * accompanies this distribution, is reproduced below, and is
9 * available at http://www.eclipse.org/org/documents/edl-v10.php
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
15 * conditions are met:
17 * - Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials provided
23 * with the distribution.
25 * - Neither the name of the Eclipse Foundation, Inc. nor the
26 * names of its contributors may be used to endorse or promote
27 * products derived from this software without specific prior
28 * written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
42 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 package org.eclipse.jgit.util;
46 import java.io.IOException;
47 import java.util.concurrent.TimeUnit;
49 import junit.framework.TestCase;
51 import org.eclipse.jgit.junit.MockSystemReader;
52 import org.eclipse.jgit.lib.ObjectId;
53 import org.eclipse.jgit.lib.PersonIdent;
55 /**
56 * Portions of this test is from CommitMsgHookTest in the Android project Gerrit
58 public class ChangeIdUtilTest extends TestCase {
60 private final String SOB1 = "Signed-off-by: J Author <ja@example.com>\n";
62 private final String SOB2 = "Signed-off-by: J Committer <jc@example.com>\n";
64 final PersonIdent p = new PersonIdent(
65 "A U Thor <author@example.com> 1142878501 -0500");
67 final PersonIdent q = new PersonIdent(
68 "W Riter <writer@example.com> 1142878502 -0500");
70 ObjectId treeId = ObjectId
71 .fromString("f51de923607cd51cf872b928a6b523ba823f7f35");
73 ObjectId treeId1 = ObjectId
74 .fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904");
76 final ObjectId treeId2 = ObjectId
77 .fromString("617601c79811cbbae338512798318b4e5b70c9ac");
79 ObjectId parentId = ObjectId
80 .fromString("91fea719aaf9447feb9580477eb3dd08b62b5eca");
82 ObjectId parentId1 = null;
84 final ObjectId parentId2 = ObjectId
85 .fromString("485c91e0600b165c301c278bfbae3e492413980c");
87 MockSystemReader mockSystemReader = new MockSystemReader();
89 final long when = mockSystemReader.getCurrentTime();
91 final int tz = new MockSystemReader().getTimezone(when);
93 PersonIdent author = new PersonIdent("J. Author", "ja@example.com");
95 author = new PersonIdent(author, when, tz);
98 PersonIdent committer = new PersonIdent("J. Committer", "jc@example.com");
100 committer = new PersonIdent(committer, when, tz);
103 public void testClean() {
104 assertEquals("hej", ChangeIdUtil.clean("hej\n\n"));
105 assertEquals("hej\n\nsan", ChangeIdUtil.clean("hej\n\nsan\n\n"));
106 assertEquals("hej\nsan", ChangeIdUtil.clean("hej\n#men\nsan\n\n#men"));
107 assertEquals("hej\nsan", ChangeIdUtil.clean("hej\nsan\n\n#men"));
108 assertEquals("hej\nsan", ChangeIdUtil.clean("#no\nhej\nsan\n\n#men"));
109 assertEquals("hej\nsan", ChangeIdUtil
110 .clean("#no\nhej\nsan\nSigned-off-by: me \n#men"));
113 public void testId() throws IOException {
114 String msg = "A\nMessage\n";
115 ObjectId id = ChangeIdUtil.computeChangeId(treeId, parentId, p, q, msg);
116 assertEquals("73f3751208ac92cbb76f9a26ac4a0d9d472e381b", ObjectId
117 .toString(id));
120 public void testHasChangeid() throws Exception {
121 assertEquals(
122 "has changeid\n\nBug: 33\nmore text\nSigned-off-by: me@you.too\nChange-Id: I0123456789012345678901234567890123456789\nAnd then some\n",
123 call("has changeid\n\nBug: 33\nmore text\nSigned-off-by: me@you.too\nChange-Id: I0123456789012345678901234567890123456789\nAnd then some\n"));
126 public void testHasChangeidWithReplacement() throws Exception {
127 assertEquals(
128 "has changeid\n\nBug: 33\nmore text\nSigned-off-by: me@you.too\nChange-Id: I988d2d7a6f2c0578fccabd4ebd3cec0768bc7f9f\nAnd then some\n",
129 call("has changeid\n\nBug: 33\nmore text\nSigned-off-by: me@you.too\nChange-Id: I0123456789012345678901234567890123456789\nAnd then some\n",
130 true));
133 public void testOneliner() throws Exception {
134 assertEquals(
135 "oneliner\n\nChange-Id: I3a98091ce4470de88d52ae317fcd297e2339f063\n",
136 call("oneliner\n"));
139 public void testOnelinerFollowedByBlank() throws Exception {
140 assertEquals(
141 "oneliner followed by blank\n\nChange-Id: I3a12c21ef342a18498f95c62efbc186cd782b743\n",
142 call("oneliner followed by blank\n"));
145 public void testATwoLines() throws Exception {
146 assertEquals(
147 "a two lines\nwith text withour break after subject line\n\nChange-Id: I549a0fed3d69b7876c54b4f5a35637135fd43fac\n",
148 call("a two lines\nwith text withour break after subject line\n"));
151 public void testRegularCommit() throws Exception {
152 assertEquals(
153 "regular commit\n\nwith header and body\n\nChange-Id: I62d8749d3c3a888c11e3fadc3924220a19389766\n",
154 call("regular commit\n\nwith header and body\n"));
157 public void testRegularCommitWithSob_ButNoBody() throws Exception {
158 assertEquals(
159 "regular commit with sob, but no body\n\nChange-Id: I0f0b4307e9944ecbd5a9f6b9489e25cfaede43c4\nSigned-off-by: me@you.too\n",
160 call("regular commit with sob, but no body\n\nSigned-off-by: me@you.too\n"));
163 public void testACommitWithBug_SubButNoBody() throws Exception {
164 assertEquals(
165 "a commit with bug, sub but no body\n\nBug: 33\nChange-Id: I337e264868613dab6d1e11a34f394db369487412\nSigned-off-by: me@you.too\n",
166 call("a commit with bug, sub but no body\n\nBug: 33\nSigned-off-by: me@you.too\n"));
169 public void testACommitWithSubject_NoBodySobAndBug() throws Exception {
170 assertEquals(
171 "a commit with subject, no body sob and bug\n\nChange-Id: Ib3616d4bf77707a3215a6cb0602c004ee119a445\nSigned-off-by: me@you.too\nBug: 33\n",
172 call("a commit with subject, no body sob and bug\n\nSigned-off-by: me@you.too\nBug: 33\n"));
175 public void testACommitWithSubjectBug_NonFooterLineAndSob()
176 throws Exception {
177 assertEquals(
178 "a commit with subject bug, non-footer line and sob\n\nBug: 33\nmore text\nSigned-off-by: me@you.too\n\nChange-Id: Ia8500eab2304e6e5eac6ae488ff44d5d850d118a\n",
179 call("a commit with subject bug, non-footer line and sob\n\nBug: 33\nmore text\nSigned-off-by: me@you.too\n"));
182 public void testACommitWithSubject_NonFooterAndBugAndSob() throws Exception {
183 assertEquals(
184 "a commit with subject, non-footer and bug and sob\n\nmore text (two empty lines after bug)\nBug: 33\n\n\nChange-Id: Idac75ccbad2ab6727b8612e344df5190d87891dd\nSigned-off-by: me@you.too\n",
185 call("a commit with subject, non-footer and bug and sob\n\nmore text (two empty lines after bug)\nBug: 33\n\n\nSigned-off-by: me@you.too\n"));
188 public void testACommitWithSubjectBodyBugBrackersAndSob() throws Exception {
189 assertEquals(
190 "a commit with subject body, bug. brackers and sob\n\nText\n\nBug: 33\nChange-Id: I90ecb589bef766302532c3e00915e10114b00f62\n[bracket]\nSigned-off-by: me@you.too\n",
191 call("a commit with subject body, bug. brackers and sob\n\nText\n\nBug: 33\n[bracket]\nSigned-off-by: me@you.too\n\n"));
194 public void testACommitWithSubjectBodyBugLineWithASpaceAndSob()
195 throws Exception {
196 assertEquals(
197 "a commit with subject body, bug. line with a space and sob\n\nText\n\nBug: 33\nChange-Id: I864e2218bdee033c8ce9a7f923af9e0d5dc16863\n \nSigned-off-by: me@you.too\n",
198 call("a commit with subject body, bug. line with a space and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n"));
201 public void testACommitWithSubjectBodyBugEmptyLineAndSob() throws Exception {
202 assertEquals(
203 "a commit with subject body, bug. empty line and sob\n\nText\n\nBug: 33\nChange-Id: I33f119f533313883e6ada3df600c4f0d4db23a76\n \nSigned-off-by: me@you.too\n",
204 call("a commit with subject body, bug. empty line and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n"));
207 public void testEmptyMessages() throws Exception {
208 // Empty input must not produce a change id.
209 hookDoesNotModify("");
210 hookDoesNotModify(" ");
211 hookDoesNotModify("\n");
212 hookDoesNotModify("\n\n");
213 hookDoesNotModify(" \n ");
215 hookDoesNotModify("#");
216 hookDoesNotModify("#\n");
217 hookDoesNotModify("# on branch master\n# Untracked files:\n");
218 hookDoesNotModify("\n# on branch master\n# Untracked files:\n");
219 hookDoesNotModify("\n\n# on branch master\n# Untracked files:\n");
221 hookDoesNotModify("\n# on branch master\ndiff --git a/src b/src\n"
222 + "new file mode 100644\nindex 0000000..c78b7f0\n");
225 public void testChangeIdAlreadySet() throws Exception {
226 // If a Change-Id is already present in the footer, the hook must
227 // not modify the message but instead must leave the identity alone.
229 hookDoesNotModify("a\n" + //
230 "\n" + //
231 "Change-Id: Iaeac9b4149291060228ef0154db2985a31111335\n");
232 hookDoesNotModify("fix: this thing\n" + //
233 "\n" + //
234 "Change-Id: I388bdaf52ed05b55e62a22d0a20d2c1ae0d33e7e\n");
235 hookDoesNotModify("fix-a-widget: this thing\n" + //
236 "\n" + //
237 "Change-Id: Id3bc5359d768a6400450283e12bdfb6cd135ea4b\n");
238 hookDoesNotModify("FIX: this thing\n" + //
239 "\n" + //
240 "Change-Id: I1b55098b5a2cce0b3f3da783dda50d5f79f873fa\n");
241 hookDoesNotModify("Fix-A-Widget: this thing\n" + //
242 "\n" + //
243 "Change-Id: I4f4e2e1e8568ddc1509baecb8c1270a1fb4b6da7\n");
246 public void testChangeIdAlreadySetWithReplacement() throws Exception {
247 // If a Change-Id is already present in the footer, the hook
248 // replaces the Change-Id with the new value..
250 assertEquals("a\n" + //
251 "\n" + //
252 "Change-Id: Ifa324efa85bfb3c8696a46a0f67fa70c35be5f5f\n",
253 call("a\n" + //
254 "\n" + //
255 "Change-Id: Iaeac9b4149291060228ef0154db2985a31111335\n",
256 true));
257 assertEquals("fix: this thing\n" + //
258 "\n" + //
259 "Change-Id: Ib63e4990a06412a3f24bd93bb160e98ac1bd412b\n",
260 call("fix: this thing\n" + //
261 "\n" + //
262 "Change-Id: I388bdaf52ed05b55e62a22d0a20d2c1ae0d33e7e\n",
263 true));
264 assertEquals("fix-a-widget: this thing\n" + //
265 "\n" + //
266 "Change-Id: If0444e4d0cabcf41b3d3b46b7e9a7a64a82117af\n",
267 call("fix-a-widget: this thing\n" + //
268 "\n" + //
269 "Change-Id: Id3bc5359d768a6400450283e12bdfb6cd135ea4b\n",
270 true));
271 assertEquals("FIX: this thing\n" + //
272 "\n" + //
273 "Change-Id: Iba5a3b2d5e5df46448f6daf362b6bfa775c6491d\n",
274 call("FIX: this thing\n" + //
275 "\n" + //
276 "Change-Id: I1b55098b5a2cce0b3f3da783dda50d5f79f873fa\n",
277 true));
278 assertEquals("Fix-A-Widget: this thing\n" + //
279 "\n" + //
280 "Change-Id: I2573d47c62c42429fbe424d70cfba931f8f87848\n",
281 call("Fix-A-Widget: this thing\n" + //
282 "\n" + //
283 "Change-Id: I4f4e2e1e8568ddc1509baecb8c1270a1fb4b6da7\n",
284 true));
287 public void testTimeAltersId() throws Exception {
288 assertEquals("a\n" + //
289 "\n" + //
290 "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n",//
291 call("a\n"));
293 tick();
294 assertEquals("a\n" + //
295 "\n" + //
296 "Change-Id: I3251906b99dda598a58a6346d8126237ee1ea800\n",//
297 call("a\n"));
299 tick();
300 assertEquals("a\n" + //
301 "\n" + //
302 "Change-Id: I69adf9208d828f41a3d7e41afbca63aff37c0c5c\n",//
303 call("a\n"));
306 /** Increment the {@link #author} and {@link #committer} times. */
307 protected void tick() {
308 final long delta = TimeUnit.MILLISECONDS.convert(5 * 60,
309 TimeUnit.SECONDS);
310 final long now = author.getWhen().getTime() + delta;
312 author = new PersonIdent(author, now, tz);
313 committer = new PersonIdent(committer, now, tz);
316 public void testFirstParentAltersId() throws Exception {
317 assertEquals("a\n" + //
318 "\n" + //
319 "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n",//
320 call("a\n"));
322 parentId1 = parentId2;
323 assertEquals("a\n" + //
324 "\n" + //
325 "Change-Id: I51e86482bde7f92028541aaf724d3a3f996e7ea2\n",//
326 call("a\n"));
329 public void testDirCacheAltersId() throws Exception {
330 assertEquals("a\n" + //
331 "\n" + //
332 "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n",//
333 call("a\n"));
335 treeId1 = treeId2;
336 assertEquals("a\n" + //
337 "\n" + //
338 "Change-Id: If56597ea9759f23b070677ea6f064c60c38da631\n",//
339 call("a\n"));
342 public void testSingleLineMessages() throws Exception {
343 assertEquals("a\n" + //
344 "\n" + //
345 "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n",//
346 call("a\n"));
348 assertEquals("fix: this thing\n" + //
349 "\n" + //
350 "Change-Id: I0f13d0e6c739ca3ae399a05a93792e80feb97f37\n",//
351 call("fix: this thing\n"));
352 assertEquals("fix-a-widget: this thing\n" + //
353 "\n" + //
354 "Change-Id: I1a1a0c751e4273d532e4046a501a612b9b8a775e\n",//
355 call("fix-a-widget: this thing\n"));
357 assertEquals("FIX: this thing\n" + //
358 "\n" + //
359 "Change-Id: If816d944c57d3893b60cf10c65931fead1290d97\n",//
360 call("FIX: this thing\n"));
361 assertEquals("Fix-A-Widget: this thing\n" + //
362 "\n" + //
363 "Change-Id: I3e18d00cbda2ba1f73aeb63ed8c7d57d7fd16c76\n",//
364 call("Fix-A-Widget: this thing\n"));
367 public void testMultiLineMessagesWithoutFooter() throws Exception {
368 assertEquals("a\n" + //
369 "\n" + //
370 "b\n" + //
371 "\n" + //
372 "Change-Id: Id0b4f42d3d6fc1569595c9b97cb665e738486f5d\n",//
373 call("a\n" + "\n" + "b\n"));
375 assertEquals("a\n" + //
376 "\n" + //
377 "b\nc\nd\ne\n" + //
378 "\n" + //
379 "Change-Id: I7d237b20058a0f46cc3f5fabc4a0476877289d75\n",//
380 call("a\n" + "\n" + "b\nc\nd\ne\n"));
382 assertEquals("a\n" + //
383 "\n" + //
384 "b\nc\nd\ne\n" + //
385 "\n" + //
386 "f\ng\nh\n" + //
387 "\n" + //
388 "Change-Id: I382e662f47bf164d6878b7fe61637873ab7fa4e8\n",//
389 call("a\n" + "\n" + "b\nc\nd\ne\n" + "\n" + "f\ng\nh\n"));
392 public void testSingleLineMessagesWithSignedOffBy() throws Exception {
393 assertEquals("a\n" + //
394 "\n" + //
395 "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n" + //
396 SOB1,//
397 call("a\n" + "\n" + SOB1));
399 assertEquals("a\n" + //
400 "\n" + //
401 "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n" + //
402 SOB1 + //
403 SOB2,//
404 call("a\n" + "\n" + SOB1 + SOB2));
407 public void testMultiLineMessagesWithSignedOffBy() throws Exception {
408 assertEquals("a\n" + //
409 "\n" + //
410 "b\nc\nd\ne\n" + //
411 "\n" + //
412 "f\ng\nh\n" + //
413 "\n" + //
414 "Change-Id: I382e662f47bf164d6878b7fe61637873ab7fa4e8\n" + //
415 SOB1,//
416 call("a\n" + "\n" + "b\nc\nd\ne\n" + "\n" + "f\ng\nh\n" + "\n"
417 + SOB1));
419 assertEquals("a\n" + //
420 "\n" + //
421 "b\nc\nd\ne\n" + //
422 "\n" + //
423 "f\ng\nh\n" + //
424 "\n" + //
425 "Change-Id: I382e662f47bf164d6878b7fe61637873ab7fa4e8\n" + //
426 SOB1 + //
427 SOB2,//
428 call("a\n" + //
429 "\n" + //
430 "b\nc\nd\ne\n" + //
431 "\n" + //
432 "f\ng\nh\n" + //
433 "\n" + //
434 SOB1 + //
435 SOB2));
437 assertEquals("a\n" + //
438 "\n" + //
439 "b: not a footer\nc\nd\ne\n" + //
440 "\n" + //
441 "f\ng\nh\n" + //
442 "\n" + //
443 "Change-Id: I8869aabd44b3017cd55d2d7e0d546a03e3931ee2\n" + //
444 SOB1 + //
445 SOB2,//
446 call("a\n" + //
447 "\n" + //
448 "b: not a footer\nc\nd\ne\n" + //
449 "\n" + //
450 "f\ng\nh\n" + //
451 "\n" + //
452 SOB1 + //
453 SOB2));
456 public void testNoteInMiddle() throws Exception {
457 assertEquals("a\n" + //
458 "\n" + //
459 "NOTE: This\n" + //
460 "does not fix it.\n" + //
461 "\n" + //
462 "Change-Id: I988a127969a6ee5e58db546aab74fc46e66847f8\n", //
463 call("a\n" + //
464 "\n" + //
465 "NOTE: This\n" + //
466 "does not fix it.\n"));
469 public void testKernelStyleFooter() throws Exception {
470 assertEquals("a\n" + //
471 "\n" + //
472 "Change-Id: I1bd787f9e7590a2ac82b02c404c955ffb21877c4\n" + //
473 SOB1 + //
474 "[ja: Fixed\n" + //
475 " the indentation]\n" + //
476 SOB2, //
477 call("a\n" + //
478 "\n" + //
479 SOB1 + //
480 "[ja: Fixed\n" + //
481 " the indentation]\n" + //
482 SOB2));
485 public void testChangeIdAfterBugOrIssue() throws Exception {
486 assertEquals("a\n" + //
487 "\n" + //
488 "Bug: 42\n" + //
489 "Change-Id: I8c0321227c4324e670b9ae8cf40eccc87af21b1b\n" + //
490 SOB1,//
491 call("a\n" + //
492 "\n" + //
493 "Bug: 42\n" + //
494 SOB1));
496 assertEquals("a\n" + //
497 "\n" + //
498 "Issue: 42\n" + //
499 "Change-Id: Ie66e07d89ae5b114c0975b49cf326e90331dd822\n" + //
500 SOB1,//
501 call("a\n" + //
502 "\n" + //
503 "Issue: 42\n" + //
504 SOB1));
507 public void notestCommitDashV() throws Exception {
508 assertEquals("a\n" + //
509 "\n" + //
510 "Change-Id: I7fc3876fee63c766a2063df97fbe04a2dddd8d7c\n" + //
511 SOB1 + //
512 SOB2, //
513 call("a\n" + //
514 "\n" + //
515 SOB1 + //
516 SOB2 + //
517 "\n" + //
518 "# on branch master\n" + //
519 "diff --git a/src b/src\n" + //
520 "new file mode 100644\n" + //
521 "index 0000000..c78b7f0\n"));
524 public void testWithEndingURL() throws Exception {
525 assertEquals("a\n" + //
526 "\n" + //
527 "http://example.com/ fixes this\n" + //
528 "\n" + //
529 "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n", //
530 call("a\n" + //
531 "\n" + //
532 "http://example.com/ fixes this\n"));
533 assertEquals("a\n" + //
534 "\n" + //
535 "https://example.com/ fixes this\n" + //
536 "\n" + //
537 "Change-Id: I62b9039e2fc0dce274af55e8f99312a8a80a805d\n", //
538 call("a\n" + //
539 "\n" + //
540 "https://example.com/ fixes this\n"));
541 assertEquals("a\n" + //
542 "\n" + //
543 "ftp://example.com/ fixes this\n" + //
544 "\n" + //
545 "Change-Id: I71b05dc1f6b9a5540a53a693e64d58b65a8910e8\n", //
546 call("a\n" + //
547 "\n" + //
548 "ftp://example.com/ fixes this\n"));
549 assertEquals("a\n" + //
550 "\n" + //
551 "git://example.com/ fixes this\n" + //
552 "\n" + //
553 "Change-Id: Id34e942baa68d790633737d815ddf11bac9183e5\n", //
554 call("a\n" + //
555 "\n" + //
556 "git://example.com/ fixes this\n"));
559 private void hookDoesNotModify(final String in) throws Exception {
560 assertEquals(in, call(in));
563 private String call(final String body) throws Exception {
564 return call(body, false);
567 private String call(final String body, boolean replaceExisting) throws Exception {
568 ObjectId computeChangeId = ChangeIdUtil.computeChangeId(treeId1,
569 parentId1, author, committer, body);
570 if (computeChangeId == null)
571 return body;
572 return ChangeIdUtil.insertId(body, computeChangeId, replaceExisting);