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.assertNotNull;
47
48 import java.io.File;
49
50 import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
51 import org.eclipse.jgit.api.ResetCommand.ResetType;
52 import org.eclipse.jgit.blame.BlameResult;
53 import org.eclipse.jgit.diff.RawTextComparator;
54 import org.eclipse.jgit.junit.RepositoryTestCase;
55 import org.eclipse.jgit.lib.ConfigConstants;
56 import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
57 import org.eclipse.jgit.revwalk.RevCommit;
58 import org.eclipse.jgit.storage.file.FileBasedConfig;
59 import org.junit.Test;
60
61
62
63
64 public class BlameCommandTest extends RepositoryTestCase {
65
66 private static String join(String... lines) {
67 StringBuilder joined = new StringBuilder();
68 for (String line : lines)
69 joined.append(line).append('\n');
70 return joined.toString();
71 }
72
73 @Test
74 public void testSingleRevision() throws Exception {
75 try (Git git = new Git(db)) {
76 String[] content = new String[] { "first", "second", "third" };
77
78 writeTrashFile("file.txt", join(content));
79 git.add().addFilepattern("file.txt").call();
80 RevCommit commit = git.commit().setMessage("create file").call();
81
82 BlameCommand command = new BlameCommand(db);
83 command.setFilePath("file.txt");
84 BlameResult lines = command.call();
85 assertNotNull(lines);
86 assertEquals(3, lines.getResultContents().size());
87
88 for (int i = 0; i < 3; i++) {
89 assertEquals(commit, lines.getSourceCommit(i));
90 assertEquals(i, lines.getSourceLine(i));
91 }
92 }
93 }
94
95 @Test
96 public void testTwoRevisions() throws Exception {
97 try (Git git = new Git(db)) {
98 String[] content1 = new String[] { "first", "second" };
99 writeTrashFile("file.txt", join(content1));
100 git.add().addFilepattern("file.txt").call();
101 RevCommit commit1 = git.commit().setMessage("create file").call();
102
103 String[] content2 = new String[] { "first", "second", "third" };
104 writeTrashFile("file.txt", join(content2));
105 git.add().addFilepattern("file.txt").call();
106 RevCommit commit2 = git.commit().setMessage("create file").call();
107
108 BlameCommand command = new BlameCommand(db);
109 command.setFilePath("file.txt");
110 BlameResult lines = command.call();
111 assertEquals(3, lines.getResultContents().size());
112
113 assertEquals(commit1, lines.getSourceCommit(0));
114 assertEquals(0, lines.getSourceLine(0));
115
116 assertEquals(commit1, lines.getSourceCommit(1));
117 assertEquals(1, lines.getSourceLine(1));
118
119 assertEquals(commit2, lines.getSourceCommit(2));
120 assertEquals(2, lines.getSourceLine(2));
121 }
122 }
123
124 @Test
125 public void testRename() throws Exception {
126 testRename("file1.txt", "file2.txt");
127 }
128
129 @Test
130 public void testRenameInSubDir() throws Exception {
131 testRename("subdir/file1.txt", "subdir/file2.txt");
132 }
133
134 @Test
135 public void testMoveToOtherDir() throws Exception {
136 testRename("subdir/file1.txt", "otherdir/file1.txt");
137 }
138
139 private void testRename(String sourcePath, String destPath)
140 throws Exception {
141 try (Git git = new Git(db)) {
142 String[] content1 = new String[] { "a", "b", "c" };
143 writeTrashFile(sourcePath, join(content1));
144 git.add().addFilepattern(sourcePath).call();
145 RevCommit commit1 = git.commit().setMessage("create file").call();
146
147 writeTrashFile(destPath, join(content1));
148 git.add().addFilepattern(destPath).call();
149 git.rm().addFilepattern(sourcePath).call();
150 git.commit().setMessage("moving file").call();
151
152 String[] content2 = new String[] { "a", "b", "c2" };
153 writeTrashFile(destPath, join(content2));
154 git.add().addFilepattern(destPath).call();
155 RevCommit commit3 = git.commit().setMessage("editing file").call();
156
157 BlameCommand command = new BlameCommand(db);
158 command.setFollowFileRenames(true);
159 command.setFilePath(destPath);
160 BlameResult lines = command.call();
161
162 assertEquals(commit1, lines.getSourceCommit(0));
163 assertEquals(0, lines.getSourceLine(0));
164 assertEquals(sourcePath, lines.getSourcePath(0));
165
166 assertEquals(commit1, lines.getSourceCommit(1));
167 assertEquals(1, lines.getSourceLine(1));
168 assertEquals(sourcePath, lines.getSourcePath(1));
169
170 assertEquals(commit3, lines.getSourceCommit(2));
171 assertEquals(2, lines.getSourceLine(2));
172 assertEquals(destPath, lines.getSourcePath(2));
173 }
174 }
175
176 @Test
177 public void testTwoRenames() throws Exception {
178 try (Git git = new Git(db)) {
179
180 String[] content1 = new String[] { "a" };
181 writeTrashFile("file.txt", join(content1));
182 git.add().addFilepattern("file.txt").call();
183 RevCommit commit1 = git.commit().setMessage("create file").call();
184
185
186 writeTrashFile("file1.txt", join(content1));
187 git.add().addFilepattern("file1.txt").call();
188 git.rm().addFilepattern("file.txt").call();
189 git.commit().setMessage("moving file").call();
190
191
192 String[] content2 = new String[] { "a", "b" };
193 writeTrashFile("file1.txt", join(content2));
194 git.add().addFilepattern("file1.txt").call();
195 RevCommit commit3 = git.commit().setMessage("editing file").call();
196
197
198 writeTrashFile("file2.txt", join(content2));
199 git.add().addFilepattern("file2.txt").call();
200 git.rm().addFilepattern("file1.txt").call();
201 git.commit().setMessage("moving file again").call();
202
203 BlameCommand command = new BlameCommand(db);
204 command.setFollowFileRenames(true);
205 command.setFilePath("file2.txt");
206 BlameResult lines = command.call();
207
208 assertEquals(commit1, lines.getSourceCommit(0));
209 assertEquals(0, lines.getSourceLine(0));
210 assertEquals("file.txt", lines.getSourcePath(0));
211
212 assertEquals(commit3, lines.getSourceCommit(1));
213 assertEquals(1, lines.getSourceLine(1));
214 assertEquals("file1.txt", lines.getSourcePath(1));
215 }
216 }
217
218 @Test
219 public void testDeleteTrailingLines() throws Exception {
220 try (Git git = new Git(db)) {
221 String[] content1 = new String[] { "a", "b", "c", "d" };
222 String[] content2 = new String[] { "a", "b" };
223
224 writeTrashFile("file.txt", join(content2));
225 git.add().addFilepattern("file.txt").call();
226 RevCommit commit1 = git.commit().setMessage("create file").call();
227
228 writeTrashFile("file.txt", join(content1));
229 git.add().addFilepattern("file.txt").call();
230 git.commit().setMessage("edit file").call();
231
232 writeTrashFile("file.txt", join(content2));
233 git.add().addFilepattern("file.txt").call();
234 git.commit().setMessage("edit file").call();
235
236 BlameCommand command = new BlameCommand(db);
237
238 command.setFilePath("file.txt");
239 BlameResult lines = command.call();
240 assertEquals(content2.length, lines.getResultContents().size());
241
242 assertEquals(commit1, lines.getSourceCommit(0));
243 assertEquals(commit1, lines.getSourceCommit(1));
244
245 assertEquals(0, lines.getSourceLine(0));
246 assertEquals(1, lines.getSourceLine(1));
247 }
248 }
249
250 @Test
251 public void testDeleteMiddleLines() throws Exception {
252 try (Git git = new Git(db)) {
253 String[] content1 = new String[] { "a", "b", "c", "d", "e" };
254 String[] content2 = new String[] { "a", "c", "e" };
255
256 writeTrashFile("file.txt", join(content2));
257 git.add().addFilepattern("file.txt").call();
258 RevCommit commit1 = git.commit().setMessage("edit file").call();
259
260 writeTrashFile("file.txt", join(content1));
261 git.add().addFilepattern("file.txt").call();
262 git.commit().setMessage("edit file").call();
263
264 writeTrashFile("file.txt", join(content2));
265 git.add().addFilepattern("file.txt").call();
266 git.commit().setMessage("edit file").call();
267
268 BlameCommand command = new BlameCommand(db);
269
270 command.setFilePath("file.txt");
271 BlameResult lines = command.call();
272 assertEquals(content2.length, lines.getResultContents().size());
273
274 assertEquals(commit1, lines.getSourceCommit(0));
275 assertEquals(0, lines.getSourceLine(0));
276
277 assertEquals(commit1, lines.getSourceCommit(1));
278 assertEquals(1, lines.getSourceLine(1));
279
280 assertEquals(commit1, lines.getSourceCommit(2));
281 assertEquals(2, lines.getSourceLine(2));
282 }
283 }
284
285 @Test
286 public void testEditAllLines() throws Exception {
287 try (Git git = new Git(db)) {
288 String[] content1 = new String[] { "a", "1" };
289 String[] content2 = new String[] { "b", "2" };
290
291 writeTrashFile("file.txt", join(content1));
292 git.add().addFilepattern("file.txt").call();
293 git.commit().setMessage("edit file").call();
294
295 writeTrashFile("file.txt", join(content2));
296 git.add().addFilepattern("file.txt").call();
297 RevCommit commit2 = git.commit().setMessage("create file").call();
298
299 BlameCommand command = new BlameCommand(db);
300
301 command.setFilePath("file.txt");
302 BlameResult lines = command.call();
303 assertEquals(content2.length, lines.getResultContents().size());
304 assertEquals(commit2, lines.getSourceCommit(0));
305 assertEquals(commit2, lines.getSourceCommit(1));
306 }
307 }
308
309 @Test
310 public void testMiddleClearAllLines() throws Exception {
311 try (Git git = new Git(db)) {
312 String[] content1 = new String[] { "a", "b", "c" };
313
314 writeTrashFile("file.txt", join(content1));
315 git.add().addFilepattern("file.txt").call();
316 git.commit().setMessage("edit file").call();
317
318 writeTrashFile("file.txt", "");
319 git.add().addFilepattern("file.txt").call();
320 git.commit().setMessage("create file").call();
321
322 writeTrashFile("file.txt", join(content1));
323 git.add().addFilepattern("file.txt").call();
324 RevCommit commit3 = git.commit().setMessage("edit file").call();
325
326 BlameCommand command = new BlameCommand(db);
327
328 command.setFilePath("file.txt");
329 BlameResult lines = command.call();
330 assertEquals(content1.length, lines.getResultContents().size());
331 assertEquals(commit3, lines.getSourceCommit(0));
332 assertEquals(commit3, lines.getSourceCommit(1));
333 assertEquals(commit3, lines.getSourceCommit(2));
334 }
335 }
336
337 @Test
338 public void testCoreAutoCrlf1() throws Exception {
339 testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.FALSE);
340 }
341
342 @Test
343 public void testCoreAutoCrlf2() throws Exception {
344 testCoreAutoCrlf(AutoCRLF.FALSE, AutoCRLF.FALSE);
345 }
346
347 @Test
348 public void testCoreAutoCrlf3() throws Exception {
349 testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.INPUT);
350 }
351
352 @Test
353 public void testCoreAutoCrlf4() throws Exception {
354 testCoreAutoCrlf(AutoCRLF.FALSE, AutoCRLF.INPUT);
355 }
356
357 @Test
358 public void testCoreAutoCrlf5() throws Exception {
359 testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.TRUE);
360 }
361
362 private void testCoreAutoCrlf(AutoCRLF modeForCommitting,
363 AutoCRLF modeForReset) throws Exception {
364 try (Git git = new Git(db)) {
365 FileBasedConfig config = db.getConfig();
366 config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
367 ConfigConstants.CONFIG_KEY_AUTOCRLF, modeForCommitting);
368 config.save();
369
370 String joinedCrlf = "a\r\nb\r\nc\r\n";
371 File trashFile = writeTrashFile("file.txt", joinedCrlf);
372 git.add().addFilepattern("file.txt").call();
373 RevCommit commit = git.commit().setMessage("create file").call();
374
375
376 trashFile.delete();
377 config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
378 ConfigConstants.CONFIG_KEY_AUTOCRLF, modeForReset);
379 config.save();
380 git.reset().setMode(ResetType.HARD).call();
381
382 BlameCommand command = new BlameCommand(db);
383 command.setFilePath("file.txt");
384 BlameResult lines = command.call();
385
386 assertEquals(3, lines.getResultContents().size());
387 assertEquals(commit, lines.getSourceCommit(0));
388 assertEquals(commit, lines.getSourceCommit(1));
389 assertEquals(commit, lines.getSourceCommit(2));
390 }
391 }
392
393 @Test
394 public void testConflictingMerge1() throws Exception {
395 try (Git git = new Git(db)) {
396 RevCommit base = commitFile("file.txt", join("0", "1", "2", "3", "4"),
397 "master");
398
399 git.checkout().setName("side").setCreateBranch(true)
400 .setStartPoint(base).call();
401 RevCommit side = commitFile("file.txt",
402 join("0", "1 side", "2", "3 on side", "4"), "side");
403
404 commitFile("file.txt", join("0", "1", "2"), "master");
405
406 checkoutBranch("refs/heads/master");
407 git.merge().include(side).call();
408
409
410
411 RevCommit merge = commitFile("file.txt",
412 join("0", "1 side", "2", "3 resolved", "4"), "master");
413
414 BlameCommand command = new BlameCommand(db);
415 command.setFilePath("file.txt");
416 BlameResult lines = command.call();
417
418 assertEquals(5, lines.getResultContents().size());
419 assertEquals(base, lines.getSourceCommit(0));
420 assertEquals(side, lines.getSourceCommit(1));
421 assertEquals(base, lines.getSourceCommit(2));
422 assertEquals(merge, lines.getSourceCommit(3));
423 assertEquals(base, lines.getSourceCommit(4));
424 }
425 }
426
427
428
429 @Test
430 public void testConflictingMerge2() throws Exception {
431 try (Git git = new Git(db)) {
432 RevCommit base = commitFile("file.txt", join("0", "1", "2", "3", "4"),
433 "master");
434
435 commitFile("file.txt", join("0", "1", "2"), "master");
436
437 git.checkout().setName("side").setCreateBranch(true)
438 .setStartPoint(base).call();
439 RevCommit side = commitFile("file.txt",
440 join("0", "1 side", "2", "3 on side", "4"), "side");
441
442 checkoutBranch("refs/heads/master");
443 git.merge().include(side).call();
444
445
446
447 RevCommit merge = commitFile("file.txt",
448 join("0", "1 side", "2", "3 resolved", "4"), "master");
449
450 BlameCommand command = new BlameCommand(db);
451 command.setFilePath("file.txt");
452 BlameResult lines = command.call();
453
454 assertEquals(5, lines.getResultContents().size());
455 assertEquals(base, lines.getSourceCommit(0));
456 assertEquals(side, lines.getSourceCommit(1));
457 assertEquals(base, lines.getSourceCommit(2));
458 assertEquals(merge, lines.getSourceCommit(3));
459 assertEquals(base, lines.getSourceCommit(4));
460 }
461 }
462
463 @Test
464 public void testWhitespaceMerge() throws Exception {
465 try (Git git = new Git(db)) {
466 RevCommit base = commitFile("file.txt", join("0", "1", "2"), "master");
467 RevCommit side = commitFile("file.txt", join("0", "1", " 2 side "),
468 "side");
469
470 checkoutBranch("refs/heads/master");
471 git.merge().setFastForward(FastForwardMode.NO_FF).include(side).call();
472
473
474
475 writeTrashFile("file.txt", join("0", "1", "2 side"));
476 RevCommit merge = git.commit().setAll(true).setMessage("merge")
477 .setAmend(true)
478 .call();
479
480 BlameCommand command = new BlameCommand(db);
481 command.setFilePath("file.txt")
482 .setTextComparator(RawTextComparator.WS_IGNORE_ALL)
483 .setStartCommit(merge.getId());
484 BlameResult lines = command.call();
485
486 assertEquals(3, lines.getResultContents().size());
487 assertEquals(base, lines.getSourceCommit(0));
488 assertEquals(base, lines.getSourceCommit(1));
489 assertEquals(side, lines.getSourceCommit(2));
490 }
491 }
492 }