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