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
44
45
46
47 package org.eclipse.jgit.lib;
48
49 import static org.junit.Assert.assertEquals;
50 import static org.junit.Assert.assertFalse;
51 import static org.junit.Assert.assertTrue;
52
53 import java.io.File;
54 import java.io.FileNotFoundException;
55 import java.io.IOException;
56 import java.util.Arrays;
57 import java.util.Collections;
58 import java.util.HashSet;
59 import java.util.TreeSet;
60
61 import org.eclipse.jgit.api.Git;
62 import org.eclipse.jgit.api.MergeResult;
63 import org.eclipse.jgit.api.MergeResult.MergeStatus;
64 import org.eclipse.jgit.api.errors.GitAPIException;
65 import org.eclipse.jgit.dircache.DirCache;
66 import org.eclipse.jgit.dircache.DirCacheBuilder;
67 import org.eclipse.jgit.dircache.DirCacheEditor;
68 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
69 import org.eclipse.jgit.dircache.DirCacheEntry;
70 import org.eclipse.jgit.junit.RepositoryTestCase;
71 import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
72 import org.eclipse.jgit.lib.IndexDiff.StageState;
73 import org.eclipse.jgit.merge.MergeStrategy;
74 import org.eclipse.jgit.revwalk.RevCommit;
75 import org.eclipse.jgit.storage.file.FileBasedConfig;
76 import org.eclipse.jgit.treewalk.FileTreeIterator;
77 import org.eclipse.jgit.util.IO;
78 import org.junit.Test;
79
80 public class IndexDiffTest extends RepositoryTestCase {
81
82 static PathEdit add(final Repository db, final File workdir,
83 final String path) throws FileNotFoundException, IOException {
84 ObjectInserter inserter = db.newObjectInserter();
85 final File f = new File(workdir, path);
86 final ObjectId id = inserter.insert(Constants.OBJ_BLOB,
87 IO.readFully(f));
88 return new PathEdit(path) {
89 @Override
90 public void apply(DirCacheEntry ent) {
91 ent.setFileMode(FileMode.REGULAR_FILE);
92 ent.setLength(f.length());
93 ent.setObjectId(id);
94 }
95 };
96 }
97
98 @Test
99 public void testAdded() throws IOException {
100 writeTrashFile("file1", "file1");
101 writeTrashFile("dir/subfile", "dir/subfile");
102 ObjectId tree = insertTree(new TreeFormatter());
103
104 DirCache index = db.lockDirCache();
105 DirCacheEditor editor = index.editor();
106 editor.add(add(db, trash, "file1"));
107 editor.add(add(db, trash, "dir/subfile"));
108 editor.commit();
109 FileTreeIterator iterator = new FileTreeIterator(db);
110 IndexDiff diff = new IndexDiff(db, tree, iterator);
111 diff.diff();
112 assertEquals(2, diff.getAdded().size());
113 assertTrue(diff.getAdded().contains("file1"));
114 assertTrue(diff.getAdded().contains("dir/subfile"));
115 assertEquals(0, diff.getChanged().size());
116 assertEquals(0, diff.getModified().size());
117 assertEquals(0, diff.getRemoved().size());
118 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
119 }
120
121 @Test
122 public void testMissing() throws Exception {
123 File file2 = writeTrashFile("file2", "file2");
124 File file3 = writeTrashFile("dir/file3", "dir/file3");
125 Git git = Git.wrap(db);
126 git.add().addFilepattern("file2").addFilepattern("dir/file3").call();
127 git.commit().setMessage("commit").call();
128 assertTrue(file2.delete());
129 assertTrue(file3.delete());
130 IndexDiff diff = new IndexDiff(db, Constants.HEAD,
131 new FileTreeIterator(db));
132 diff.diff();
133 assertEquals(2, diff.getMissing().size());
134 assertTrue(diff.getMissing().contains("file2"));
135 assertTrue(diff.getMissing().contains("dir/file3"));
136 assertEquals(0, diff.getChanged().size());
137 assertEquals(0, diff.getModified().size());
138 assertEquals(0, diff.getAdded().size());
139 assertEquals(0, diff.getRemoved().size());
140 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
141 }
142
143 @Test
144 public void testRemoved() throws IOException {
145 writeTrashFile("file2", "file2");
146 writeTrashFile("dir/file3", "dir/file3");
147
148 TreeFormatter dir = new TreeFormatter();
149 dir.append("file3", FileMode.REGULAR_FILE, ObjectId.fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b"));
150
151 TreeFormatter tree = new TreeFormatter();
152 tree.append("file2", FileMode.REGULAR_FILE, ObjectId.fromString("30d67d4672d5c05833b7192cc77a79eaafb5c7ad"));
153 tree.append("dir", FileMode.TREE, insertTree(dir));
154 ObjectId treeId = insertTree(tree);
155
156 FileTreeIterator iterator = new FileTreeIterator(db);
157 IndexDiff diff = new IndexDiff(db, treeId, iterator);
158 diff.diff();
159 assertEquals(2, diff.getRemoved().size());
160 assertTrue(diff.getRemoved().contains("file2"));
161 assertTrue(diff.getRemoved().contains("dir/file3"));
162 assertEquals(0, diff.getChanged().size());
163 assertEquals(0, diff.getModified().size());
164 assertEquals(0, diff.getAdded().size());
165 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
166 }
167
168 @Test
169 public void testModified() throws IOException, GitAPIException {
170
171 writeTrashFile("file2", "file2");
172 writeTrashFile("dir/file3", "dir/file3");
173
174 try (Git git = new Git(db)) {
175 git.add().addFilepattern("file2").addFilepattern("dir/file3").call();
176 }
177
178 writeTrashFile("dir/file3", "changed");
179
180 TreeFormatter dir = new TreeFormatter();
181 dir.append("file3", FileMode.REGULAR_FILE, ObjectId.fromString("0123456789012345678901234567890123456789"));
182
183 TreeFormatter tree = new TreeFormatter();
184 tree.append("dir", FileMode.TREE, insertTree(dir));
185 tree.append("file2", FileMode.REGULAR_FILE, ObjectId.fromString("0123456789012345678901234567890123456789"));
186 ObjectId treeId = insertTree(tree);
187
188 FileTreeIterator iterator = new FileTreeIterator(db);
189 IndexDiff diff = new IndexDiff(db, treeId, iterator);
190 diff.diff();
191 assertEquals(2, diff.getChanged().size());
192 assertTrue(diff.getChanged().contains("file2"));
193 assertTrue(diff.getChanged().contains("dir/file3"));
194 assertEquals(1, diff.getModified().size());
195 assertTrue(diff.getModified().contains("dir/file3"));
196 assertEquals(0, diff.getAdded().size());
197 assertEquals(0, diff.getRemoved().size());
198 assertEquals(0, diff.getMissing().size());
199 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
200 }
201
202 @Test
203 public void testConflicting() throws Exception {
204 try (Git git = new Git(db)) {
205 writeTrashFile("a", "1\na\n3\n");
206 writeTrashFile("b", "1\nb\n3\n");
207 git.add().addFilepattern("a").addFilepattern("b").call();
208 RevCommit initialCommit = git.commit().setMessage("initial").call();
209
210
211 createBranch(initialCommit, "refs/heads/side");
212 checkoutBranch("refs/heads/side");
213 writeTrashFile("a", "1\na(side)\n3\n");
214 writeTrashFile("b", "1\nb\n3\n(side)");
215 git.add().addFilepattern("a").addFilepattern("b").call();
216 RevCommit secondCommit = git.commit().setMessage("side").call();
217
218
219 checkoutBranch("refs/heads/master");
220 writeTrashFile("a", "1\na(main)\n3\n");
221 git.add().addFilepattern("a").call();
222 git.commit().setMessage("main").call();
223
224
225 MergeResult result = git.merge().include(secondCommit.getId())
226 .setStrategy(MergeStrategy.RESOLVE).call();
227 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
228 }
229
230 FileTreeIterator iterator = new FileTreeIterator(db);
231 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
232 diff.diff();
233
234 assertEquals("[b]",
235 new TreeSet<>(diff.getChanged()).toString());
236 assertEquals("[]", diff.getAdded().toString());
237 assertEquals("[]", diff.getRemoved().toString());
238 assertEquals("[]", diff.getMissing().toString());
239 assertEquals("[]", diff.getModified().toString());
240 assertEquals("[a]", diff.getConflicting().toString());
241 assertEquals(StageState.BOTH_MODIFIED,
242 diff.getConflictingStageStates().get("a"));
243 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
244 }
245
246 @Test
247 public void testConflictingDeletedAndModified() throws Exception {
248 try (Git git = new Git(db)) {
249 writeTrashFile("a", "1\na\n3\n");
250 writeTrashFile("b", "1\nb\n3\n");
251 git.add().addFilepattern("a").addFilepattern("b").call();
252 RevCommit initialCommit = git.commit().setMessage("initial").call();
253
254
255 createBranch(initialCommit, "refs/heads/side");
256 checkoutBranch("refs/heads/side");
257 git.rm().addFilepattern("a").call();
258 RevCommit secondCommit = git.commit().setMessage("side").call();
259
260
261 checkoutBranch("refs/heads/master");
262 writeTrashFile("a", "1\na(main)\n3\n");
263 git.add().addFilepattern("a").call();
264 git.commit().setMessage("main").call();
265
266
267 MergeResult result = git.merge().include(secondCommit.getId())
268 .setStrategy(MergeStrategy.RESOLVE).call();
269 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
270 }
271
272 FileTreeIterator iterator = new FileTreeIterator(db);
273 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
274 diff.diff();
275
276 assertEquals("[]", new TreeSet<>(diff.getChanged()).toString());
277 assertEquals("[]", diff.getAdded().toString());
278 assertEquals("[]", diff.getRemoved().toString());
279 assertEquals("[]", diff.getMissing().toString());
280 assertEquals("[]", diff.getModified().toString());
281 assertEquals("[a]", diff.getConflicting().toString());
282 assertEquals(StageState.DELETED_BY_THEM,
283 diff.getConflictingStageStates().get("a"));
284 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
285 }
286
287 @Test
288 public void testConflictingFromMultipleCreations() throws Exception {
289 try (Git git = new Git(db)) {
290 writeTrashFile("a", "1\na\n3\n");
291 git.add().addFilepattern("a").call();
292 RevCommit initialCommit = git.commit().setMessage("initial").call();
293
294 createBranch(initialCommit, "refs/heads/side");
295 checkoutBranch("refs/heads/side");
296
297 writeTrashFile("b", "1\nb(side)\n3\n");
298 git.add().addFilepattern("b").call();
299 RevCommit secondCommit = git.commit().setMessage("side").call();
300
301 checkoutBranch("refs/heads/master");
302
303 writeTrashFile("b", "1\nb(main)\n3\n");
304 git.add().addFilepattern("b").call();
305 git.commit().setMessage("main").call();
306
307 MergeResult result = git.merge().include(secondCommit.getId())
308 .setStrategy(MergeStrategy.RESOLVE).call();
309 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
310 }
311
312 FileTreeIterator iterator = new FileTreeIterator(db);
313 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
314 diff.diff();
315
316 assertEquals("[]", new TreeSet<>(diff.getChanged()).toString());
317 assertEquals("[]", diff.getAdded().toString());
318 assertEquals("[]", diff.getRemoved().toString());
319 assertEquals("[]", diff.getMissing().toString());
320 assertEquals("[]", diff.getModified().toString());
321 assertEquals("[b]", diff.getConflicting().toString());
322 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
323 }
324
325 @Test
326 public void testUnchangedSimple() throws IOException, GitAPIException {
327 writeTrashFile("a.b", "a.b");
328 writeTrashFile("a.c", "a.c");
329 writeTrashFile("a=c", "a=c");
330 writeTrashFile("a=d", "a=d");
331 try (Git git = new Git(db)) {
332 git.add().addFilepattern("a.b").call();
333 git.add().addFilepattern("a.c").call();
334 git.add().addFilepattern("a=c").call();
335 git.add().addFilepattern("a=d").call();
336 }
337
338 TreeFormatter tree = new TreeFormatter();
339
340 tree.append("a.b", FileMode.REGULAR_FILE, ObjectId.fromString("f6f28df96c2b40c951164286e08be7c38ec74851"));
341 tree.append("a.c", FileMode.REGULAR_FILE, ObjectId.fromString("6bc0e647512d2a0bef4f26111e484dc87df7f5ca"));
342 tree.append("a=c", FileMode.REGULAR_FILE, ObjectId.fromString("06022365ddbd7fb126761319633bf73517770714"));
343 tree.append("a=d", FileMode.REGULAR_FILE, ObjectId.fromString("fa6414df3da87840700e9eeb7fc261dd77ccd5c2"));
344 ObjectId treeId = insertTree(tree);
345
346 FileTreeIterator iterator = new FileTreeIterator(db);
347 IndexDiff diff = new IndexDiff(db, treeId, iterator);
348 diff.diff();
349 assertEquals(0, diff.getChanged().size());
350 assertEquals(0, diff.getAdded().size());
351 assertEquals(0, diff.getRemoved().size());
352 assertEquals(0, diff.getMissing().size());
353 assertEquals(0, diff.getModified().size());
354 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
355 }
356
357
358
359
360
361
362
363
364 @Test
365 public void testUnchangedComplex() throws IOException, GitAPIException {
366 writeTrashFile("a.b", "a.b");
367 writeTrashFile("a.c", "a.c");
368 writeTrashFile("a/b.b/b", "a/b.b/b");
369 writeTrashFile("a/b", "a/b");
370 writeTrashFile("a/c", "a/c");
371 writeTrashFile("a=c", "a=c");
372 writeTrashFile("a=d", "a=d");
373 try (Git git = new Git(db)) {
374 git.add().addFilepattern("a.b").addFilepattern("a.c")
375 .addFilepattern("a/b.b/b").addFilepattern("a/b")
376 .addFilepattern("a/c").addFilepattern("a=c")
377 .addFilepattern("a=d").call();
378 }
379
380
381
382 TreeFormatter bb = new TreeFormatter();
383 bb.append("b", FileMode.REGULAR_FILE, ObjectId.fromString("8d840bd4e2f3a48ff417c8e927d94996849933fd"));
384
385 TreeFormatter a = new TreeFormatter();
386 a.append("b", FileMode.REGULAR_FILE, ObjectId
387 .fromString("db89c972fc57862eae378f45b74aca228037d415"));
388 a.append("b.b", FileMode.TREE, insertTree(bb));
389 a.append("c", FileMode.REGULAR_FILE, ObjectId.fromString("52ad142a008aeb39694bafff8e8f1be75ed7f007"));
390
391 TreeFormatter tree = new TreeFormatter();
392 tree.append("a.b", FileMode.REGULAR_FILE, ObjectId.fromString("f6f28df96c2b40c951164286e08be7c38ec74851"));
393 tree.append("a.c", FileMode.REGULAR_FILE, ObjectId.fromString("6bc0e647512d2a0bef4f26111e484dc87df7f5ca"));
394 tree.append("a", FileMode.TREE, insertTree(a));
395 tree.append("a=c", FileMode.REGULAR_FILE, ObjectId.fromString("06022365ddbd7fb126761319633bf73517770714"));
396 tree.append("a=d", FileMode.REGULAR_FILE, ObjectId.fromString("fa6414df3da87840700e9eeb7fc261dd77ccd5c2"));
397 ObjectId treeId = insertTree(tree);
398
399 FileTreeIterator iterator = new FileTreeIterator(db);
400 IndexDiff diff = new IndexDiff(db, treeId, iterator);
401 diff.diff();
402 assertEquals(0, diff.getChanged().size());
403 assertEquals(0, diff.getAdded().size());
404 assertEquals(0, diff.getRemoved().size());
405 assertEquals(0, diff.getMissing().size());
406 assertEquals(0, diff.getModified().size());
407 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
408 }
409
410 private ObjectId insertTree(TreeFormatter tree) throws IOException {
411 try (ObjectInserter oi = db.newObjectInserter()) {
412 ObjectId id = oi.insert(tree);
413 oi.flush();
414 return id;
415 }
416 }
417
418
419
420
421
422
423
424 @Test
425 public void testRemovedUntracked() throws Exception{
426 String path = "file";
427 try (Git git = new Git(db)) {
428 writeTrashFile(path, "content");
429 git.add().addFilepattern(path).call();
430 git.commit().setMessage("commit").call();
431 }
432 removeFromIndex(path);
433 FileTreeIterator iterator = new FileTreeIterator(db);
434 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
435 diff.diff();
436 assertTrue(diff.getRemoved().contains(path));
437 assertTrue(diff.getUntracked().contains(path));
438 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
439 }
440
441
442
443
444
445 @Test
446 public void testUntrackedFolders() throws Exception {
447 try (Git git = new Git(db)) {
448 IndexDiff diff = new IndexDiff(db, Constants.HEAD,
449 new FileTreeIterator(db));
450 diff.diff();
451 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
452
453 writeTrashFile("readme", "");
454 writeTrashFile("src/com/A.java", "");
455 writeTrashFile("src/com/B.java", "");
456 writeTrashFile("src/org/A.java", "");
457 writeTrashFile("src/org/B.java", "");
458 writeTrashFile("target/com/A.java", "");
459 writeTrashFile("target/com/B.java", "");
460 writeTrashFile("target/org/A.java", "");
461 writeTrashFile("target/org/B.java", "");
462
463 git.add().addFilepattern("src").addFilepattern("readme").call();
464 git.commit().setMessage("initial").call();
465
466 diff = new IndexDiff(db, Constants.HEAD,
467 new FileTreeIterator(db));
468 diff.diff();
469 assertEquals(new HashSet<>(Arrays.asList("target")),
470 diff.getUntrackedFolders());
471
472 writeTrashFile("src/tst/A.java", "");
473 writeTrashFile("src/tst/B.java", "");
474
475 diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
476 diff.diff();
477 assertEquals(new HashSet<>(Arrays.asList("target", "src/tst")),
478 diff.getUntrackedFolders());
479
480 git.rm().addFilepattern("src/com/B.java").addFilepattern("src/org")
481 .call();
482 git.commit().setMessage("second").call();
483 writeTrashFile("src/org/C.java", "");
484
485 diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
486 diff.diff();
487 assertEquals(
488 new HashSet<>(Arrays.asList("src/org", "src/tst",
489 "target")),
490 diff.getUntrackedFolders());
491 }
492 }
493
494
495
496
497
498
499
500 @Test
501 public void testUntrackedNotIgnoredFolders() throws Exception {
502 try (Git git = new Git(db)) {
503 IndexDiff diff = new IndexDiff(db, Constants.HEAD,
504 new FileTreeIterator(db));
505 diff.diff();
506 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
507
508 writeTrashFile("readme", "");
509 writeTrashFile("sr/com/X.java", "");
510 writeTrashFile("src/com/A.java", "");
511 writeTrashFile("src/org/B.java", "");
512 writeTrashFile("srcs/org/Y.java", "");
513 writeTrashFile("target/com/A.java", "");
514 writeTrashFile("target/org/B.java", "");
515 writeTrashFile(".gitignore", "/target\n/sr");
516
517 git.add().addFilepattern("readme").addFilepattern(".gitignore")
518 .addFilepattern("srcs/").call();
519 git.commit().setMessage("initial").call();
520
521 diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
522 diff.diff();
523 assertEquals(new HashSet<>(Arrays.asList("src")),
524 diff.getUntrackedFolders());
525 assertEquals(new HashSet<>(Arrays.asList("sr", "target")),
526 diff.getIgnoredNotInIndex());
527
528 git.add().addFilepattern("src").call();
529 writeTrashFile("sr/com/X1.java", "");
530 writeTrashFile("src/tst/A.java", "");
531 writeTrashFile("src/tst/B.java", "");
532 writeTrashFile("srcs/com/Y1.java", "");
533 deleteTrashFile(".gitignore");
534
535 diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
536 diff.diff();
537 assertEquals(
538 new HashSet<>(Arrays.asList("srcs/com", "sr", "src/tst",
539 "target")),
540 diff.getUntrackedFolders());
541 }
542 }
543
544 @Test
545 public void testAssumeUnchanged() throws Exception {
546 try (Git git = new Git(db)) {
547 String path = "file";
548 writeTrashFile(path, "content");
549 git.add().addFilepattern(path).call();
550 String path2 = "file2";
551 writeTrashFile(path2, "content");
552 String path3 = "file3";
553 writeTrashFile(path3, "some content");
554 git.add().addFilepattern(path2).addFilepattern(path3).call();
555 git.commit().setMessage("commit").call();
556 assumeUnchanged(path2);
557 assumeUnchanged(path3);
558 writeTrashFile(path, "more content");
559 deleteTrashFile(path3);
560
561 FileTreeIterator iterator = new FileTreeIterator(db);
562 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
563 diff.diff();
564 assertEquals(2, diff.getAssumeUnchanged().size());
565 assertEquals(1, diff.getModified().size());
566 assertEquals(0, diff.getChanged().size());
567 assertTrue(diff.getAssumeUnchanged().contains("file2"));
568 assertTrue(diff.getAssumeUnchanged().contains("file3"));
569 assertTrue(diff.getModified().contains("file"));
570
571 git.add().addFilepattern(".").call();
572
573 iterator = new FileTreeIterator(db);
574 diff = new IndexDiff(db, Constants.HEAD, iterator);
575 diff.diff();
576 assertEquals(2, diff.getAssumeUnchanged().size());
577 assertEquals(0, diff.getModified().size());
578 assertEquals(1, diff.getChanged().size());
579 assertTrue(diff.getAssumeUnchanged().contains("file2"));
580 assertTrue(diff.getAssumeUnchanged().contains("file3"));
581 assertTrue(diff.getChanged().contains("file"));
582 assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
583 }
584 }
585
586 @Test
587 public void testStageState() throws IOException {
588 final int base = DirCacheEntry.STAGE_1;
589 final int ours = DirCacheEntry.STAGE_2;
590 final int theirs = DirCacheEntry.STAGE_3;
591 verifyStageState(StageState.BOTH_DELETED, base);
592 verifyStageState(StageState.DELETED_BY_THEM, ours, base);
593 verifyStageState(StageState.DELETED_BY_US, base, theirs);
594 verifyStageState(StageState.BOTH_MODIFIED, base, ours, theirs);
595 verifyStageState(StageState.ADDED_BY_US, ours);
596 verifyStageState(StageState.BOTH_ADDED, ours, theirs);
597 verifyStageState(StageState.ADDED_BY_THEM, theirs);
598
599 assertTrue(StageState.BOTH_DELETED.hasBase());
600 assertFalse(StageState.BOTH_DELETED.hasOurs());
601 assertFalse(StageState.BOTH_DELETED.hasTheirs());
602 assertFalse(StageState.BOTH_ADDED.hasBase());
603 assertTrue(StageState.BOTH_ADDED.hasOurs());
604 assertTrue(StageState.BOTH_ADDED.hasTheirs());
605 }
606
607 @Test
608 public void testStageState_mergeAndReset_bug() throws Exception {
609 try (Git git = new Git(db)) {
610 writeTrashFile("a", "content");
611 git.add().addFilepattern("a").call();
612 RevCommit initialCommit = git.commit().setMessage("initial commit")
613 .call();
614
615
616 final String branchName = Constants.R_HEADS + "branch";
617 createBranch(initialCommit, branchName);
618 checkoutBranch(branchName);
619 writeTrashFile("b", "second file content - branch");
620 git.add().addFilepattern("b").call();
621 RevCommit branchCommit = git.commit().setMessage("branch commit")
622 .call();
623
624
625 checkoutBranch(Constants.R_HEADS + Constants.MASTER);
626 writeTrashFile("b", "second file content - master");
627 git.add().addFilepattern("b").call();
628 git.commit().setMessage("master commit").call();
629
630
631 MergeResult result = git.merge().include(branchCommit).call();
632 assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
633
634 FileTreeIterator iterator = new FileTreeIterator(db);
635 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
636 diff.diff();
637
638 assertTrue(diff.getChanged().isEmpty());
639 assertTrue(diff.getAdded().isEmpty());
640 assertTrue(diff.getRemoved().isEmpty());
641 assertTrue(diff.getMissing().isEmpty());
642 assertTrue(diff.getModified().isEmpty());
643 assertEquals(1, diff.getConflicting().size());
644 assertTrue(diff.getConflicting().contains("b"));
645 assertEquals(StageState.BOTH_ADDED, diff.getConflictingStageStates()
646 .get("b"));
647 assertTrue(diff.getUntrackedFolders().isEmpty());
648
649
650 writeTrashFile("b", "second file content - master");
651
652
653 iterator = new FileTreeIterator(db);
654 diff = new IndexDiff(db, Constants.HEAD, iterator);
655 diff.diff();
656
657 assertTrue(diff.getChanged().isEmpty());
658 assertTrue(diff.getAdded().isEmpty());
659 assertTrue(diff.getRemoved().isEmpty());
660 assertTrue(diff.getMissing().isEmpty());
661 assertTrue(diff.getModified().isEmpty());
662 assertEquals(1, diff.getConflicting().size());
663 assertTrue(diff.getConflicting().contains("b"));
664 assertEquals(StageState.BOTH_ADDED, diff.getConflictingStageStates()
665 .get("b"));
666 assertTrue(diff.getUntrackedFolders().isEmpty());
667 }
668 }
669
670 @Test
671 public void testStageState_simulated_bug() throws Exception {
672 try (Git git = new Git(db)) {
673 writeTrashFile("a", "content");
674 git.add().addFilepattern("a").call();
675 RevCommit initialCommit = git.commit().setMessage("initial commit")
676 .call();
677
678
679 final String branchName = Constants.R_HEADS + "branch";
680 createBranch(initialCommit, branchName);
681 checkoutBranch(branchName);
682 writeTrashFile("b", "second file content - branch");
683 git.add().addFilepattern("b").call();
684 git.commit().setMessage("branch commit")
685 .call();
686
687
688 checkoutBranch(Constants.R_HEADS + Constants.MASTER);
689 writeTrashFile("b", "second file content - master");
690 git.add().addFilepattern("b").call();
691 git.commit().setMessage("master commit").call();
692
693
694 DirCacheBuilder builder = db.lockDirCache().builder();
695 DirCacheEntry entry = createEntry("a", FileMode.REGULAR_FILE, 0,
696 "content");
697 builder.add(entry);
698 entry = createEntry("b", FileMode.REGULAR_FILE, 2,
699 "second file content - master");
700 builder.add(entry);
701 entry = createEntry("b", FileMode.REGULAR_FILE, 3,
702 "second file content - branch");
703 builder.add(entry);
704 builder.commit();
705
706 FileTreeIterator iterator = new FileTreeIterator(db);
707 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
708 diff.diff();
709
710 assertTrue(diff.getChanged().isEmpty());
711 assertTrue(diff.getAdded().isEmpty());
712 assertTrue(diff.getRemoved().isEmpty());
713 assertTrue(diff.getMissing().isEmpty());
714 assertTrue(diff.getModified().isEmpty());
715 assertEquals(1, diff.getConflicting().size());
716 assertTrue(diff.getConflicting().contains("b"));
717 assertEquals(StageState.BOTH_ADDED, diff.getConflictingStageStates()
718 .get("b"));
719 assertTrue(diff.getUntrackedFolders().isEmpty());
720 }
721 }
722
723 @Test
724 public void testAutoCRLFInput() throws Exception {
725 try (Git git = new Git(db)) {
726 FileBasedConfig config = db.getConfig();
727
728
729 config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
730 ConfigConstants.CONFIG_KEY_AUTOCRLF, AutoCRLF.FALSE);
731 config.save();
732
733
734 writeTrashFile("crlf.txt", "this\r\ncontains\r\ncrlf\r\n");
735 git.add().addFilepattern("crlf.txt").call();
736 git.commit().setMessage("Add crlf.txt").call();
737
738
739 config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
740 ConfigConstants.CONFIG_KEY_AUTOCRLF, AutoCRLF.INPUT);
741 config.save();
742
743 FileTreeIterator iterator = new FileTreeIterator(db);
744 IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
745 diff.diff();
746
747 assertTrue(
748 "Expected no modified files, but there were: "
749 + diff.getModified(), diff.getModified().isEmpty());
750 }
751 }
752
753 private void verifyStageState(StageState expected, int... stages)
754 throws IOException {
755 DirCacheBuilder builder = db.lockDirCache().builder();
756 for (int stage : stages) {
757 DirCacheEntry entry = createEntry("a", FileMode.REGULAR_FILE,
758 stage, "content");
759 builder.add(entry);
760 }
761 builder.commit();
762
763 IndexDiff diff = new IndexDiff(db, Constants.HEAD,
764 new FileTreeIterator(db));
765 diff.diff();
766
767 assertEquals(
768 "Conflict for entries in stages " + Arrays.toString(stages),
769 expected, diff.getConflictingStageStates().get("a"));
770 }
771
772 private void removeFromIndex(String path) throws IOException {
773 final DirCache dirc = db.lockDirCache();
774 final DirCacheEditor edit = dirc.editor();
775 edit.add(new DirCacheEditor.DeletePath(path));
776 if (!edit.commit())
777 throw new IOException("could not commit");
778 }
779
780 private void assumeUnchanged(String path) throws IOException {
781 final DirCache dirc = db.lockDirCache();
782 final DirCacheEntry ent = dirc.getEntry(path);
783 if (ent != null)
784 ent.setAssumeValid(true);
785 dirc.write();
786 if (!dirc.commit())
787 throw new IOException("could not commit");
788 }
789
790 }