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