1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.api;
44
45 import static org.junit.Assert.assertEquals;
46 import static org.junit.Assert.assertNotEquals;
47 import static org.junit.Assert.assertNotNull;
48 import static org.junit.Assert.assertNull;
49 import static org.junit.Assert.assertSame;
50 import static org.junit.Assert.assertTrue;
51 import static org.junit.Assert.fail;
52
53 import java.io.File;
54 import java.util.Date;
55 import java.util.List;
56 import java.util.TimeZone;
57 import java.util.concurrent.atomic.AtomicInteger;
58
59 import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus;
60 import org.eclipse.jgit.api.errors.CanceledException;
61 import org.eclipse.jgit.api.errors.EmptyCommitException;
62 import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
63 import org.eclipse.jgit.diff.DiffEntry;
64 import org.eclipse.jgit.dircache.DirCache;
65 import org.eclipse.jgit.dircache.DirCacheBuilder;
66 import org.eclipse.jgit.dircache.DirCacheEntry;
67 import org.eclipse.jgit.junit.RepositoryTestCase;
68 import org.eclipse.jgit.lib.CommitBuilder;
69 import org.eclipse.jgit.lib.ConfigConstants;
70 import org.eclipse.jgit.lib.Constants;
71 import org.eclipse.jgit.lib.FileMode;
72 import org.eclipse.jgit.lib.GpgSigner;
73 import org.eclipse.jgit.lib.ObjectId;
74 import org.eclipse.jgit.lib.PersonIdent;
75 import org.eclipse.jgit.lib.RefUpdate;
76 import org.eclipse.jgit.lib.RefUpdate.Result;
77 import org.eclipse.jgit.lib.ReflogEntry;
78 import org.eclipse.jgit.lib.Repository;
79 import org.eclipse.jgit.lib.StoredConfig;
80 import org.eclipse.jgit.revwalk.RevCommit;
81 import org.eclipse.jgit.storage.file.FileBasedConfig;
82 import org.eclipse.jgit.submodule.SubmoduleWalk;
83 import org.eclipse.jgit.transport.CredentialsProvider;
84 import org.eclipse.jgit.treewalk.TreeWalk;
85 import org.eclipse.jgit.treewalk.filter.TreeFilter;
86 import org.eclipse.jgit.util.FS;
87 import org.junit.Ignore;
88 import org.junit.Test;
89
90
91
92
93 public class CommitCommandTest extends RepositoryTestCase {
94
95 @Test
96 public void testExecutableRetention() throws Exception {
97 StoredConfig config = db.getConfig();
98 config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
99 ConfigConstants.CONFIG_KEY_FILEMODE, true);
100 config.save();
101
102 FS executableFs = new FS() {
103
104 @Override
105 public boolean supportsExecute() {
106 return true;
107 }
108
109 @Override
110 public boolean setExecute(File f, boolean canExec) {
111 return true;
112 }
113
114 @Override
115 public ProcessBuilder runInShell(String cmd, String[] args) {
116 return null;
117 }
118
119 @Override
120 public boolean retryFailedLockFileCommit() {
121 return false;
122 }
123
124 @Override
125 public FS newInstance() {
126 return this;
127 }
128
129 @Override
130 protected File discoverGitExe() {
131 return null;
132 }
133
134 @Override
135 public boolean canExecute(File f) {
136 return true;
137 }
138
139 @Override
140 public boolean isCaseSensitive() {
141 return true;
142 }
143 };
144
145 Git git = Git.open(db.getDirectory(), executableFs);
146 String path = "a.txt";
147 writeTrashFile(path, "content");
148 git.add().addFilepattern(path).call();
149 RevCommit commit1 = git.commit().setMessage("commit").call();
150 TreeWalk walk = TreeWalk.forPath(db, path, commit1.getTree());
151 assertNotNull(walk);
152 assertEquals(FileMode.EXECUTABLE_FILE, walk.getFileMode(0));
153
154 FS nonExecutableFs = new FS() {
155
156 @Override
157 public boolean supportsExecute() {
158 return false;
159 }
160
161 @Override
162 public boolean setExecute(File f, boolean canExec) {
163 return false;
164 }
165
166 @Override
167 public ProcessBuilder runInShell(String cmd, String[] args) {
168 return null;
169 }
170
171 @Override
172 public boolean retryFailedLockFileCommit() {
173 return false;
174 }
175
176 @Override
177 public FS newInstance() {
178 return this;
179 }
180
181 @Override
182 protected File discoverGitExe() {
183 return null;
184 }
185
186 @Override
187 public boolean canExecute(File f) {
188 return false;
189 }
190
191 @Override
192 public boolean isCaseSensitive() {
193 return true;
194 }
195 };
196
197 config = db.getConfig();
198 config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
199 ConfigConstants.CONFIG_KEY_FILEMODE, false);
200 config.save();
201
202 Git git2 = Git.open(db.getDirectory(), nonExecutableFs);
203 writeTrashFile(path, "content2");
204 RevCommit commit2 = git2.commit().setOnly(path).setMessage("commit2")
205 .call();
206 walk = TreeWalk.forPath(db, path, commit2.getTree());
207 assertNotNull(walk);
208 assertEquals(FileMode.EXECUTABLE_FILE, walk.getFileMode(0));
209 }
210
211 @Test
212 public void commitNewSubmodule() throws Exception {
213 try (Git git = new Git(db)) {
214 writeTrashFile("file.txt", "content");
215 git.add().addFilepattern("file.txt").call();
216 RevCommit commit = git.commit().setMessage("create file").call();
217
218 SubmoduleAddCommand command = new SubmoduleAddCommand(db);
219 String path = "sub";
220 command.setPath(path);
221 String uri = db.getDirectory().toURI().toString();
222 command.setURI(uri);
223 Repository repo = command.call();
224 assertNotNull(repo);
225 addRepoToClose(repo);
226
227 SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
228 assertTrue(generator.next());
229 assertEquals(path, generator.getPath());
230 assertEquals(commit, generator.getObjectId());
231 assertEquals(uri, generator.getModulesUrl());
232 assertEquals(path, generator.getModulesPath());
233 assertEquals(uri, generator.getConfigUrl());
234 try (Repository subModRepo = generator.getRepository()) {
235 assertNotNull(subModRepo);
236 }
237 assertEquals(commit, repo.resolve(Constants.HEAD));
238
239 RevCommit submoduleCommit = git.commit().setMessage("submodule add")
240 .setOnly(path).call();
241 assertNotNull(submoduleCommit);
242 try (TreeWalk walk = new TreeWalk(db)) {
243 walk.addTree(commit.getTree());
244 walk.addTree(submoduleCommit.getTree());
245 walk.setFilter(TreeFilter.ANY_DIFF);
246 List<DiffEntry> diffs = DiffEntry.scan(walk);
247 assertEquals(1, diffs.size());
248 DiffEntry subDiff = diffs.get(0);
249 assertEquals(FileMode.MISSING, subDiff.getOldMode());
250 assertEquals(FileMode.GITLINK, subDiff.getNewMode());
251 assertEquals(ObjectId.zeroId(), subDiff.getOldId().toObjectId());
252 assertEquals(commit, subDiff.getNewId().toObjectId());
253 assertEquals(path, subDiff.getNewPath());
254 }
255 }
256 }
257
258 @Test
259 public void commitSubmoduleUpdate() throws Exception {
260 try (Git git = new Git(db)) {
261 writeTrashFile("file.txt", "content");
262 git.add().addFilepattern("file.txt").call();
263 RevCommit commit = git.commit().setMessage("create file").call();
264 writeTrashFile("file.txt", "content2");
265 git.add().addFilepattern("file.txt").call();
266 RevCommit commit2 = git.commit().setMessage("edit file").call();
267
268 SubmoduleAddCommand command = new SubmoduleAddCommand(db);
269 String path = "sub";
270 command.setPath(path);
271 String uri = db.getDirectory().toURI().toString();
272 command.setURI(uri);
273 Repository repo = command.call();
274 assertNotNull(repo);
275 addRepoToClose(repo);
276
277 SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
278 assertTrue(generator.next());
279 assertEquals(path, generator.getPath());
280 assertEquals(commit2, generator.getObjectId());
281 assertEquals(uri, generator.getModulesUrl());
282 assertEquals(path, generator.getModulesPath());
283 assertEquals(uri, generator.getConfigUrl());
284 try (Repository subModRepo = generator.getRepository()) {
285 assertNotNull(subModRepo);
286 }
287 assertEquals(commit2, repo.resolve(Constants.HEAD));
288
289 RevCommit submoduleAddCommit = git.commit().setMessage("submodule add")
290 .setOnly(path).call();
291 assertNotNull(submoduleAddCommit);
292
293 RefUpdate update = repo.updateRef(Constants.HEAD);
294 update.setNewObjectId(commit);
295 assertEquals(Result.FORCED, update.forceUpdate());
296
297 RevCommit submoduleEditCommit = git.commit()
298 .setMessage("submodule add").setOnly(path).call();
299 assertNotNull(submoduleEditCommit);
300 try (TreeWalk walk = new TreeWalk(db)) {
301 walk.addTree(submoduleAddCommit.getTree());
302 walk.addTree(submoduleEditCommit.getTree());
303 walk.setFilter(TreeFilter.ANY_DIFF);
304 List<DiffEntry> diffs = DiffEntry.scan(walk);
305 assertEquals(1, diffs.size());
306 DiffEntry subDiff = diffs.get(0);
307 assertEquals(FileMode.GITLINK, subDiff.getOldMode());
308 assertEquals(FileMode.GITLINK, subDiff.getNewMode());
309 assertEquals(commit2, subDiff.getOldId().toObjectId());
310 assertEquals(commit, subDiff.getNewId().toObjectId());
311 assertEquals(path, subDiff.getNewPath());
312 assertEquals(path, subDiff.getOldPath());
313 }
314 }
315 }
316
317 @Ignore("very flaky when run with Hudson")
318 @Test
319 public void commitUpdatesSmudgedEntries() throws Exception {
320 try (Git git = new Git(db)) {
321 File file1 = writeTrashFile("file1.txt", "content1");
322 assertTrue(file1.setLastModified(file1.lastModified() - 5000));
323 File file2 = writeTrashFile("file2.txt", "content2");
324 assertTrue(file2.setLastModified(file2.lastModified() - 5000));
325 File file3 = writeTrashFile("file3.txt", "content3");
326 assertTrue(file3.setLastModified(file3.lastModified() - 5000));
327
328 assertNotNull(git.add().addFilepattern("file1.txt")
329 .addFilepattern("file2.txt").addFilepattern("file3.txt").call());
330 RevCommit commit = git.commit().setMessage("add files").call();
331 assertNotNull(commit);
332
333 DirCache cache = DirCache.read(db.getIndexFile(), db.getFS());
334 int file1Size = cache.getEntry("file1.txt").getLength();
335 int file2Size = cache.getEntry("file2.txt").getLength();
336 int file3Size = cache.getEntry("file3.txt").getLength();
337 ObjectId file2Id = cache.getEntry("file2.txt").getObjectId();
338 ObjectId file3Id = cache.getEntry("file3.txt").getObjectId();
339 assertTrue(file1Size > 0);
340 assertTrue(file2Size > 0);
341 assertTrue(file3Size > 0);
342
343
344 cache = DirCache.lock(db.getIndexFile(), db.getFS());
345 cache.getEntry("file1.txt").setLength(0);
346 cache.getEntry("file2.txt").setLength(0);
347 cache.getEntry("file3.txt").setLength(0);
348 cache.write();
349 assertTrue(cache.commit());
350
351
352 cache = DirCache.read(db.getIndexFile(), db.getFS());
353 assertEquals(0, cache.getEntry("file1.txt").getLength());
354 assertEquals(0, cache.getEntry("file2.txt").getLength());
355 assertEquals(0, cache.getEntry("file3.txt").getLength());
356
357 long indexTime = db.getIndexFile().lastModified();
358 db.getIndexFile().setLastModified(indexTime - 5000);
359
360 write(file1, "content4");
361 assertTrue(file1.setLastModified(file1.lastModified() + 2500));
362 assertNotNull(git.commit().setMessage("edit file").setOnly("file1.txt")
363 .call());
364
365 cache = db.readDirCache();
366 assertEquals(file1Size, cache.getEntry("file1.txt").getLength());
367 assertEquals(file2Size, cache.getEntry("file2.txt").getLength());
368 assertEquals(file3Size, cache.getEntry("file3.txt").getLength());
369 assertEquals(file2Id, cache.getEntry("file2.txt").getObjectId());
370 assertEquals(file3Id, cache.getEntry("file3.txt").getObjectId());
371 }
372 }
373
374 @Ignore("very flaky when run with Hudson")
375 @Test
376 public void commitIgnoresSmudgedEntryWithDifferentId() throws Exception {
377 try (Git git = new Git(db)) {
378 File file1 = writeTrashFile("file1.txt", "content1");
379 assertTrue(file1.setLastModified(file1.lastModified() - 5000));
380 File file2 = writeTrashFile("file2.txt", "content2");
381 assertTrue(file2.setLastModified(file2.lastModified() - 5000));
382
383 assertNotNull(git.add().addFilepattern("file1.txt")
384 .addFilepattern("file2.txt").call());
385 RevCommit commit = git.commit().setMessage("add files").call();
386 assertNotNull(commit);
387
388 DirCache cache = DirCache.read(db.getIndexFile(), db.getFS());
389 int file1Size = cache.getEntry("file1.txt").getLength();
390 int file2Size = cache.getEntry("file2.txt").getLength();
391 assertTrue(file1Size > 0);
392 assertTrue(file2Size > 0);
393
394 writeTrashFile("file2.txt", "content3");
395 assertNotNull(git.add().addFilepattern("file2.txt").call());
396 writeTrashFile("file2.txt", "content4");
397
398
399 cache = DirCache.lock(db.getIndexFile(), db.getFS());
400 cache.getEntry("file1.txt").setLength(0);
401 cache.getEntry("file2.txt").setLength(0);
402 cache.write();
403 assertTrue(cache.commit());
404
405
406 cache = db.readDirCache();
407 assertEquals(0, cache.getEntry("file1.txt").getLength());
408 assertEquals(0, cache.getEntry("file2.txt").getLength());
409
410 long indexTime = db.getIndexFile().lastModified();
411 db.getIndexFile().setLastModified(indexTime - 5000);
412
413 write(file1, "content5");
414 assertTrue(file1.setLastModified(file1.lastModified() + 1000));
415
416 assertNotNull(git.commit().setMessage("edit file").setOnly("file1.txt")
417 .call());
418
419 cache = db.readDirCache();
420 assertEquals(file1Size, cache.getEntry("file1.txt").getLength());
421 assertEquals(0, cache.getEntry("file2.txt").getLength());
422 }
423 }
424
425 @Test
426 public void commitAfterSquashMerge() throws Exception {
427 try (Git git = new Git(db)) {
428 writeTrashFile("file1", "file1");
429 git.add().addFilepattern("file1").call();
430 RevCommit first = git.commit().setMessage("initial commit").call();
431
432 assertTrue(new File(db.getWorkTree(), "file1").exists());
433 createBranch(first, "refs/heads/branch1");
434 checkoutBranch("refs/heads/branch1");
435
436 writeTrashFile("file2", "file2");
437 git.add().addFilepattern("file2").call();
438 git.commit().setMessage("second commit").call();
439 assertTrue(new File(db.getWorkTree(), "file2").exists());
440
441 checkoutBranch("refs/heads/master");
442
443 MergeResult result = git.merge()
444 .include(db.exactRef("refs/heads/branch1"))
445 .setSquash(true)
446 .call();
447
448 assertTrue(new File(db.getWorkTree(), "file1").exists());
449 assertTrue(new File(db.getWorkTree(), "file2").exists());
450 assertEquals(MergeResult.MergeStatus.FAST_FORWARD_SQUASHED,
451 result.getMergeStatus());
452
453
454 RevCommit squashedCommit = git.commit().call();
455
456 assertEquals(1, squashedCommit.getParentCount());
457 assertNull(db.readSquashCommitMsg());
458 assertEquals("commit: Squashed commit of the following:", db
459 .getReflogReader(Constants.HEAD).getLastEntry().getComment());
460 assertEquals("commit: Squashed commit of the following:", db
461 .getReflogReader(db.getBranch()).getLastEntry().getComment());
462 }
463 }
464
465 @Test
466 public void testReflogs() throws Exception {
467 try (Git git = new Git(db)) {
468 writeTrashFile("f", "1");
469 git.add().addFilepattern("f").call();
470 git.commit().setMessage("c1").call();
471 writeTrashFile("f", "2");
472 git.commit().setMessage("c2").setAll(true).setReflogComment(null)
473 .call();
474 writeTrashFile("f", "3");
475 git.commit().setMessage("c3").setAll(true)
476 .setReflogComment("testRl").call();
477
478 db.getReflogReader(Constants.HEAD).getReverseEntries();
479
480 assertEquals("testRl;commit (initial): c1;", reflogComments(
481 db.getReflogReader(Constants.HEAD).getReverseEntries()));
482 assertEquals("testRl;commit (initial): c1;", reflogComments(
483 db.getReflogReader(db.getBranch()).getReverseEntries()));
484 }
485 }
486
487 private static String reflogComments(List<ReflogEntry> entries) {
488 StringBuffer b = new StringBuffer();
489 for (ReflogEntry e : entries) {
490 b.append(e.getComment()).append(";");
491 }
492 return b.toString();
493 }
494
495 @Test(expected = WrongRepositoryStateException.class)
496 public void commitAmendOnInitialShouldFail() throws Exception {
497 try (Git git = new Git(db)) {
498 git.commit().setAmend(true).setMessage("initial commit").call();
499 }
500 }
501
502 @Test
503 public void commitAmendWithoutAuthorShouldSetOriginalAuthorAndAuthorTime()
504 throws Exception {
505 try (Git git = new Git(db)) {
506 writeTrashFile("file1", "file1");
507 git.add().addFilepattern("file1").call();
508
509 final String authorName = "First Author";
510 final String authorEmail = "author@example.org";
511 final Date authorDate = new Date(1349621117000L);
512 PersonIdent firstAuthor = new PersonIdent(authorName, authorEmail,
513 authorDate, TimeZone.getTimeZone("UTC"));
514 git.commit().setMessage("initial commit").setAuthor(firstAuthor).call();
515
516 RevCommit amended = git.commit().setAmend(true)
517 .setMessage("amend commit").call();
518
519 PersonIdent amendedAuthor = amended.getAuthorIdent();
520 assertEquals(authorName, amendedAuthor.getName());
521 assertEquals(authorEmail, amendedAuthor.getEmailAddress());
522 assertEquals(authorDate.getTime(), amendedAuthor.getWhen().getTime());
523 }
524 }
525
526 @Test
527 public void commitAmendWithAuthorShouldUseIt() throws Exception {
528 try (Git git = new Git(db)) {
529 writeTrashFile("file1", "file1");
530 git.add().addFilepattern("file1").call();
531 git.commit().setMessage("initial commit").call();
532
533 RevCommit amended = git.commit().setAmend(true)
534 .setAuthor("New Author", "newauthor@example.org")
535 .setMessage("amend commit").call();
536
537 PersonIdent amendedAuthor = amended.getAuthorIdent();
538 assertEquals("New Author", amendedAuthor.getName());
539 assertEquals("newauthor@example.org", amendedAuthor.getEmailAddress());
540 }
541 }
542
543 @Test
544 public void commitEmptyCommits() throws Exception {
545 try (Git git = new Git(db)) {
546
547 writeTrashFile("file1", "file1");
548 git.add().addFilepattern("file1").call();
549 RevCommit initial = git.commit().setMessage("initial commit")
550 .call();
551
552 RevCommit emptyFollowUp = git.commit()
553 .setAuthor("New Author", "newauthor@example.org")
554 .setMessage("no change").call();
555
556 assertNotEquals(initial.getId(), emptyFollowUp.getId());
557 assertEquals(initial.getTree().getId(),
558 emptyFollowUp.getTree().getId());
559
560 try {
561 git.commit().setAuthor("New Author", "newauthor@example.org")
562 .setMessage("again no change").setAllowEmpty(false)
563 .call();
564 fail("Didn't get the expected EmptyCommitException");
565 } catch (EmptyCommitException e) {
566
567 }
568
569
570 git.commit().setAuthor("New Author", "newauthor@example.org")
571 .setMessage("again no change").setOnly("file1")
572 .setAllowEmpty(true).call();
573 }
574 }
575
576 @Test
577 public void commitOnlyShouldCommitUnmergedPathAndNotAffectOthers()
578 throws Exception {
579 DirCache index = db.lockDirCache();
580 DirCacheBuilder builder = index.builder();
581 addUnmergedEntry("unmerged1", builder);
582 addUnmergedEntry("unmerged2", builder);
583 DirCacheEntry other = new DirCacheEntry("other");
584 other.setFileMode(FileMode.REGULAR_FILE);
585 builder.add(other);
586 builder.commit();
587
588 writeTrashFile("unmerged1", "unmerged1 data");
589 writeTrashFile("unmerged2", "unmerged2 data");
590 writeTrashFile("other", "other data");
591
592 assertEquals("[other, mode:100644]"
593 + "[unmerged1, mode:100644, stage:1]"
594 + "[unmerged1, mode:100644, stage:2]"
595 + "[unmerged1, mode:100644, stage:3]"
596 + "[unmerged2, mode:100644, stage:1]"
597 + "[unmerged2, mode:100644, stage:2]"
598 + "[unmerged2, mode:100644, stage:3]",
599 indexState(0));
600
601 try (Git git = new Git(db)) {
602 RevCommit commit = git.commit().setOnly("unmerged1")
603 .setMessage("Only one file").call();
604
605 assertEquals("[other, mode:100644]" + "[unmerged1, mode:100644]"
606 + "[unmerged2, mode:100644, stage:1]"
607 + "[unmerged2, mode:100644, stage:2]"
608 + "[unmerged2, mode:100644, stage:3]",
609 indexState(0));
610
611 try (TreeWalk walk = TreeWalk.forPath(db, "unmerged1", commit.getTree())) {
612 assertEquals(FileMode.REGULAR_FILE, walk.getFileMode(0));
613 }
614 }
615 }
616
617 @Test
618 public void commitOnlyShouldHandleIgnored() throws Exception {
619 try (Git git = new Git(db)) {
620 writeTrashFile("subdir/foo", "Hello World");
621 writeTrashFile("subdir/bar", "Hello World");
622 writeTrashFile(".gitignore", "bar");
623 git.add().addFilepattern("subdir").call();
624 git.commit().setOnly("subdir").setMessage("first commit").call();
625 assertEquals("[subdir/foo, mode:100644, content:Hello World]",
626 indexState(CONTENT));
627 }
628 }
629
630 @Test
631 public void commitWithAutoCrlfAndNonNormalizedIndex() throws Exception {
632 try (Git git = new Git(db)) {
633
634 FileBasedConfig config = db.getConfig();
635 config.setString("core", null, "autocrlf", "false");
636 config.save();
637 writeTrashFile("file.txt", "line 1\r\nline 2\r\n");
638 git.add().addFilepattern("file.txt").call();
639 git.commit().setMessage("Initial").call();
640 assertEquals(
641 "[file.txt, mode:100644, content:line 1\r\nline 2\r\n]",
642 indexState(CONTENT));
643 config.setString("core", null, "autocrlf", "true");
644 config.save();
645 writeTrashFile("file.txt", "line 1\r\nline 1.5\r\nline 2\r\n");
646 writeTrashFile("file2.txt", "new\r\nfile\r\n");
647 git.add().addFilepattern("file.txt").addFilepattern("file2.txt")
648 .call();
649 git.commit().setMessage("Second").call();
650 assertEquals(
651 "[file.txt, mode:100644, content:line 1\r\nline 1.5\r\nline 2\r\n]"
652 + "[file2.txt, mode:100644, content:new\nfile\n]",
653 indexState(CONTENT));
654 writeTrashFile("file2.txt", "new\r\nfile\r\ncontent\r\n");
655 git.add().addFilepattern("file2.txt").call();
656 git.commit().setMessage("Third").call();
657 assertEquals(
658 "[file.txt, mode:100644, content:line 1\r\nline 1.5\r\nline 2\r\n]"
659 + "[file2.txt, mode:100644, content:new\nfile\ncontent\n]",
660 indexState(CONTENT));
661 }
662 }
663
664 private void testConflictWithAutoCrlf(String baseLf, String lf)
665 throws Exception {
666 try (Git git = new Git(db)) {
667
668 FileBasedConfig config = db.getConfig();
669 config.setString("core", null, "autocrlf", "false");
670 config.save();
671 writeTrashFile("file.txt", "foo" + baseLf);
672 git.add().addFilepattern("file.txt").call();
673 git.commit().setMessage("Initial").call();
674
675 git.checkout().setCreateBranch(true).setName("side").call();
676 writeTrashFile("file.txt", "bar\r\n");
677 git.add().addFilepattern("file.txt").call();
678 RevCommit side = git.commit().setMessage("Side").call();
679
680 git.checkout().setName("master");
681 writeTrashFile("file.txt", "foob" + lf);
682 git.add().addFilepattern("file.txt").call();
683 git.commit().setMessage("Second").call();
684
685 config.setString("core", null, "autocrlf", "true");
686 config.save();
687
688 CherryPickResult pick = git.cherryPick().include(side).call();
689 assertEquals("Expected a cherry-pick conflict",
690 CherryPickStatus.CONFLICTING, pick.getStatus());
691 writeTrashFile("file.txt", "foobar\r\n");
692 git.add().addFilepattern("file.txt").call();
693 git.commit().setMessage("Second").call();
694 assertEquals("[file.txt, mode:100644, content:foobar" + lf + "]",
695 indexState(CONTENT));
696 }
697 }
698
699 @Test
700 public void commitConflictWithAutoCrlfBaseCrLfOursLf() throws Exception {
701 testConflictWithAutoCrlf("\r\n", "\n");
702 }
703
704 @Test
705 public void commitConflictWithAutoCrlfBaseLfOursLf() throws Exception {
706 testConflictWithAutoCrlf("\n", "\n");
707 }
708
709 @Test
710 public void commitConflictWithAutoCrlfBasCrLfOursCrLf() throws Exception {
711 testConflictWithAutoCrlf("\r\n", "\r\n");
712 }
713
714 @Test
715 public void commitConflictWithAutoCrlfBaseLfOursCrLf() throws Exception {
716 testConflictWithAutoCrlf("\n", "\r\n");
717 }
718
719 private static void addUnmergedEntry(String file, DirCacheBuilder builder) {
720 DirCacheEntry stage1 = new DirCacheEntry(file, DirCacheEntry.STAGE_1);
721 DirCacheEntry stage2 = new DirCacheEntry(file, DirCacheEntry.STAGE_2);
722 DirCacheEntry stage3 = new DirCacheEntry(file, DirCacheEntry.STAGE_3);
723 stage1.setFileMode(FileMode.REGULAR_FILE);
724 stage2.setFileMode(FileMode.REGULAR_FILE);
725 stage3.setFileMode(FileMode.REGULAR_FILE);
726 builder.add(stage1);
727 builder.add(stage2);
728 builder.add(stage3);
729 }
730
731 @Test
732 public void callSignerWithProperSigningKey() throws Exception {
733 try (Git git = new Git(db)) {
734 writeTrashFile("file1", "file1");
735 git.add().addFilepattern("file1").call();
736
737 String[] signingKey = new String[1];
738 PersonIdent[] signingCommitters = new PersonIdent[1];
739 AtomicInteger callCount = new AtomicInteger();
740 GpgSigner.setDefault(new GpgSigner() {
741 @Override
742 public void sign(CommitBuilder commit, String gpgSigningKey,
743 PersonIdent signingCommitter, CredentialsProvider credentialsProvider) {
744 signingKey[0] = gpgSigningKey;
745 signingCommitters[0] = signingCommitter;
746 callCount.incrementAndGet();
747 }
748
749 @Override
750 public boolean canLocateSigningKey(String gpgSigningKey,
751 PersonIdent signingCommitter,
752 CredentialsProvider credentialsProvider)
753 throws CanceledException {
754 return false;
755 }
756 });
757
758
759
760 git.commit().setCommitter(committer).setSign(Boolean.TRUE)
761 .setMessage("initial commit")
762 .call();
763 assertNull(signingKey[0]);
764 assertEquals(1, callCount.get());
765 assertSame(committer, signingCommitters[0]);
766
767 writeTrashFile("file2", "file2");
768 git.add().addFilepattern("file2").call();
769
770
771 String expectedConfigSigningKey = "config-" + System.nanoTime();
772 StoredConfig config = git.getRepository().getConfig();
773 config.setString("user", null, "signingKey",
774 expectedConfigSigningKey);
775 config.save();
776
777 git.commit().setCommitter(committer).setSign(Boolean.TRUE)
778 .setMessage("initial commit")
779 .call();
780 assertEquals(expectedConfigSigningKey, signingKey[0]);
781 assertEquals(2, callCount.get());
782 assertSame(committer, signingCommitters[0]);
783
784 writeTrashFile("file3", "file3");
785 git.add().addFilepattern("file3").call();
786
787
788 String expectedSigningKey = "my-" + System.nanoTime();
789 git.commit().setCommitter(committer).setSign(Boolean.TRUE)
790 .setSigningKey(expectedSigningKey)
791 .setMessage("initial commit").call();
792 assertEquals(expectedSigningKey, signingKey[0]);
793 assertEquals(3, callCount.get());
794 assertSame(committer, signingCommitters[0]);
795 }
796 }
797
798 @Test
799 public void callSignerOnlyWhenSigning() throws Exception {
800 try (Git git = new Git(db)) {
801 writeTrashFile("file1", "file1");
802 git.add().addFilepattern("file1").call();
803
804 AtomicInteger callCount = new AtomicInteger();
805 GpgSigner.setDefault(new GpgSigner() {
806 @Override
807 public void sign(CommitBuilder commit, String gpgSigningKey,
808 PersonIdent signingCommitter, CredentialsProvider credentialsProvider) {
809 callCount.incrementAndGet();
810 }
811
812 @Override
813 public boolean canLocateSigningKey(String gpgSigningKey,
814 PersonIdent signingCommitter,
815 CredentialsProvider credentialsProvider)
816 throws CanceledException {
817 return false;
818 }
819 });
820
821
822
823 git.commit().setMessage("initial commit").call();
824 assertEquals(0, callCount.get());
825
826 writeTrashFile("file2", "file2");
827 git.add().addFilepattern("file2").call();
828
829
830 git.commit().setSign(Boolean.TRUE).setMessage("commit").call();
831 assertEquals(1, callCount.get());
832
833 writeTrashFile("file3", "file3");
834 git.add().addFilepattern("file3").call();
835
836
837 StoredConfig config = git.getRepository().getConfig();
838 config.setBoolean("commit", null, "gpgSign", true);
839 config.save();
840
841 git.commit().setMessage("commit").call();
842 assertEquals(2, callCount.get());
843
844 writeTrashFile("file4", "file4");
845 git.add().addFilepattern("file4").call();
846
847
848 git.commit().setSign(Boolean.FALSE).setMessage("commit").call();
849 assertEquals(2, callCount.get());
850 }
851 }
852 }