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 StringBuilder b = new StringBuilder();
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 @Test
667 public void testDeletionConflictWithAutoCrlf() 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 File file = writeTrashFile("file.txt", "foo\r\n");
674 git.add().addFilepattern("file.txt").call();
675 git.commit().setMessage("Initial").call();
676
677 git.checkout().setCreateBranch(true).setName("side").call();
678 assertTrue(file.delete());
679 git.rm().addFilepattern("file.txt").call();
680 git.commit().setMessage("Side").call();
681
682 config.setString("core", null, "autocrlf", "true");
683 config.save();
684
685 git.checkout().setName("master").call();
686 writeTrashFile("file.txt", "foob\r\n");
687 git.add().addFilepattern("file.txt").call();
688 assertEquals("[file.txt, mode:100644, content:foob\r\n]",
689 indexState(CONTENT));
690 writeTrashFile("g", "file2.txt", "anything");
691 git.add().addFilepattern("g/file2.txt");
692 RevCommit master = git.commit().setMessage("Second").call();
693
694 git.checkout().setName("side").call();
695
696 CherryPickResult pick = git.cherryPick().include(master).call();
697 assertEquals("Expected a cherry-pick conflict",
698 CherryPickStatus.CONFLICTING, pick.getStatus());
699
700 git.add().addFilepattern("g/file2.txt").call();
701
702 writeTrashFile("file.txt", "foob\r\n");
703 git.add().addFilepattern("file.txt").call();
704 git.commit().setMessage("Cherry").call();
705
706
707 assertEquals(
708 "[file.txt, mode:100644, content:foob\n]"
709 + "[g/file2.txt, mode:100644, content:anything]",
710 indexState(CONTENT));
711 }
712 }
713
714 private void testConflictWithAutoCrlf(String baseLf, String lf)
715 throws Exception {
716 try (Git git = new Git(db)) {
717
718 FileBasedConfig config = db.getConfig();
719 config.setString("core", null, "autocrlf", "false");
720 config.save();
721 writeTrashFile("file.txt", "foo" + baseLf);
722 git.add().addFilepattern("file.txt").call();
723 git.commit().setMessage("Initial").call();
724
725 git.checkout().setCreateBranch(true).setName("side").call();
726 writeTrashFile("file.txt", "bar\r\n");
727 git.add().addFilepattern("file.txt").call();
728 RevCommit side = git.commit().setMessage("Side").call();
729
730 git.checkout().setName("master");
731 writeTrashFile("file.txt", "foob" + lf);
732 git.add().addFilepattern("file.txt").call();
733 git.commit().setMessage("Second").call();
734
735 config.setString("core", null, "autocrlf", "true");
736 config.save();
737
738 CherryPickResult pick = git.cherryPick().include(side).call();
739 assertEquals("Expected a cherry-pick conflict",
740 CherryPickStatus.CONFLICTING, pick.getStatus());
741 writeTrashFile("file.txt", "foobar\r\n");
742 git.add().addFilepattern("file.txt").call();
743 git.commit().setMessage("Second").call();
744 assertEquals("[file.txt, mode:100644, content:foobar" + lf + "]",
745 indexState(CONTENT));
746 }
747 }
748
749 @Test
750 public void commitConflictWithAutoCrlfBaseCrLfOursLf() throws Exception {
751 testConflictWithAutoCrlf("\r\n", "\n");
752 }
753
754 @Test
755 public void commitConflictWithAutoCrlfBaseLfOursLf() throws Exception {
756 testConflictWithAutoCrlf("\n", "\n");
757 }
758
759 @Test
760 public void commitConflictWithAutoCrlfBasCrLfOursCrLf() throws Exception {
761 testConflictWithAutoCrlf("\r\n", "\r\n");
762 }
763
764 @Test
765 public void commitConflictWithAutoCrlfBaseLfOursCrLf() throws Exception {
766 testConflictWithAutoCrlf("\n", "\r\n");
767 }
768
769 private static void addUnmergedEntry(String file, DirCacheBuilder builder) {
770 DirCacheEntry stage1 = new DirCacheEntry(file, DirCacheEntry.STAGE_1);
771 DirCacheEntry stage2 = new DirCacheEntry(file, DirCacheEntry.STAGE_2);
772 DirCacheEntry stage3 = new DirCacheEntry(file, DirCacheEntry.STAGE_3);
773 stage1.setFileMode(FileMode.REGULAR_FILE);
774 stage2.setFileMode(FileMode.REGULAR_FILE);
775 stage3.setFileMode(FileMode.REGULAR_FILE);
776 builder.add(stage1);
777 builder.add(stage2);
778 builder.add(stage3);
779 }
780
781 @Test
782 public void callSignerWithProperSigningKey() throws Exception {
783 try (Git git = new Git(db)) {
784 writeTrashFile("file1", "file1");
785 git.add().addFilepattern("file1").call();
786
787 String[] signingKey = new String[1];
788 PersonIdent[] signingCommitters = new PersonIdent[1];
789 AtomicInteger callCount = new AtomicInteger();
790 GpgSigner.setDefault(new GpgSigner() {
791 @Override
792 public void sign(CommitBuilder commit, String gpgSigningKey,
793 PersonIdent signingCommitter, CredentialsProvider credentialsProvider) {
794 signingKey[0] = gpgSigningKey;
795 signingCommitters[0] = signingCommitter;
796 callCount.incrementAndGet();
797 }
798
799 @Override
800 public boolean canLocateSigningKey(String gpgSigningKey,
801 PersonIdent signingCommitter,
802 CredentialsProvider credentialsProvider)
803 throws CanceledException {
804 return false;
805 }
806 });
807
808
809
810 git.commit().setCommitter(committer).setSign(Boolean.TRUE)
811 .setMessage("initial commit")
812 .call();
813 assertNull(signingKey[0]);
814 assertEquals(1, callCount.get());
815 assertSame(committer, signingCommitters[0]);
816
817 writeTrashFile("file2", "file2");
818 git.add().addFilepattern("file2").call();
819
820
821 String expectedConfigSigningKey = "config-" + System.nanoTime();
822 StoredConfig config = git.getRepository().getConfig();
823 config.setString("user", null, "signingKey",
824 expectedConfigSigningKey);
825 config.save();
826
827 git.commit().setCommitter(committer).setSign(Boolean.TRUE)
828 .setMessage("initial commit")
829 .call();
830 assertEquals(expectedConfigSigningKey, signingKey[0]);
831 assertEquals(2, callCount.get());
832 assertSame(committer, signingCommitters[0]);
833
834 writeTrashFile("file3", "file3");
835 git.add().addFilepattern("file3").call();
836
837
838 String expectedSigningKey = "my-" + System.nanoTime();
839 git.commit().setCommitter(committer).setSign(Boolean.TRUE)
840 .setSigningKey(expectedSigningKey)
841 .setMessage("initial commit").call();
842 assertEquals(expectedSigningKey, signingKey[0]);
843 assertEquals(3, callCount.get());
844 assertSame(committer, signingCommitters[0]);
845 }
846 }
847
848 @Test
849 public void callSignerOnlyWhenSigning() throws Exception {
850 try (Git git = new Git(db)) {
851 writeTrashFile("file1", "file1");
852 git.add().addFilepattern("file1").call();
853
854 AtomicInteger callCount = new AtomicInteger();
855 GpgSigner.setDefault(new GpgSigner() {
856 @Override
857 public void sign(CommitBuilder commit, String gpgSigningKey,
858 PersonIdent signingCommitter, CredentialsProvider credentialsProvider) {
859 callCount.incrementAndGet();
860 }
861
862 @Override
863 public boolean canLocateSigningKey(String gpgSigningKey,
864 PersonIdent signingCommitter,
865 CredentialsProvider credentialsProvider)
866 throws CanceledException {
867 return false;
868 }
869 });
870
871
872
873 git.commit().setMessage("initial commit").call();
874 assertEquals(0, callCount.get());
875
876 writeTrashFile("file2", "file2");
877 git.add().addFilepattern("file2").call();
878
879
880 git.commit().setSign(Boolean.TRUE).setMessage("commit").call();
881 assertEquals(1, callCount.get());
882
883 writeTrashFile("file3", "file3");
884 git.add().addFilepattern("file3").call();
885
886
887 StoredConfig config = git.getRepository().getConfig();
888 config.setBoolean("commit", null, "gpgSign", true);
889 config.save();
890
891 git.commit().setMessage("commit").call();
892 assertEquals(2, callCount.get());
893
894 writeTrashFile("file4", "file4");
895 git.add().addFilepattern("file4").call();
896
897
898 git.commit().setSign(Boolean.FALSE).setMessage("commit").call();
899 assertEquals(2, callCount.get());
900 }
901 }
902 }