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 Git git = new Git(db);
76
77 String[] content = new String[] { "first", "second", "third" };
78
79 writeTrashFile("file.txt", join(content));
80 git.add().addFilepattern("file.txt").call();
81 RevCommit commit = git.commit().setMessage("create file").call();
82
83 BlameCommand command = new BlameCommand(db);
84 command.setFilePath("file.txt");
85 BlameResult lines = command.call();
86 assertNotNull(lines);
87 assertEquals(3, lines.getResultContents().size());
88
89 for (int i = 0; i < 3; i++) {
90 assertEquals(commit, lines.getSourceCommit(i));
91 assertEquals(i, lines.getSourceLine(i));
92 }
93 }
94
95 @Test
96 public void testTwoRevisions() throws Exception {
97 Git git = new Git(db);
98
99 String[] content1 = new String[] { "first", "second" };
100 writeTrashFile("file.txt", join(content1));
101 git.add().addFilepattern("file.txt").call();
102 RevCommit commit1 = git.commit().setMessage("create file").call();
103
104 String[] content2 = new String[] { "first", "second", "third" };
105 writeTrashFile("file.txt", join(content2));
106 git.add().addFilepattern("file.txt").call();
107 RevCommit commit2 = git.commit().setMessage("create file").call();
108
109 BlameCommand command = new BlameCommand(db);
110 command.setFilePath("file.txt");
111 BlameResult lines = command.call();
112 assertEquals(3, lines.getResultContents().size());
113
114 assertEquals(commit1, lines.getSourceCommit(0));
115 assertEquals(0, lines.getSourceLine(0));
116
117 assertEquals(commit1, lines.getSourceCommit(1));
118 assertEquals(1, lines.getSourceLine(1));
119
120 assertEquals(commit2, lines.getSourceCommit(2));
121 assertEquals(2, lines.getSourceLine(2));
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(final String sourcePath, final String destPath)
140 throws Exception {
141 Git git = new Git(db);
142
143 String[] content1 = new String[] { "a", "b", "c" };
144 writeTrashFile(sourcePath, join(content1));
145 git.add().addFilepattern(sourcePath).call();
146 RevCommit commit1 = git.commit().setMessage("create file").call();
147
148 writeTrashFile(destPath, join(content1));
149 git.add().addFilepattern(destPath).call();
150 git.rm().addFilepattern(sourcePath).call();
151 git.commit().setMessage("moving file").call();
152
153 String[] content2 = new String[] { "a", "b", "c2" };
154 writeTrashFile(destPath, join(content2));
155 git.add().addFilepattern(destPath).call();
156 RevCommit commit3 = git.commit().setMessage("editing file").call();
157
158 BlameCommand command = new BlameCommand(db);
159 command.setFollowFileRenames(true);
160 command.setFilePath(destPath);
161 BlameResult lines = command.call();
162
163 assertEquals(commit1, lines.getSourceCommit(0));
164 assertEquals(0, lines.getSourceLine(0));
165 assertEquals(sourcePath, lines.getSourcePath(0));
166
167 assertEquals(commit1, lines.getSourceCommit(1));
168 assertEquals(1, lines.getSourceLine(1));
169 assertEquals(sourcePath, lines.getSourcePath(1));
170
171 assertEquals(commit3, lines.getSourceCommit(2));
172 assertEquals(2, lines.getSourceLine(2));
173 assertEquals(destPath, lines.getSourcePath(2));
174 }
175
176 @Test
177 public void testTwoRenames() throws Exception {
178 Git git = new Git(db);
179
180
181 String[] content1 = new String[] { "a" };
182 writeTrashFile("file.txt", join(content1));
183 git.add().addFilepattern("file.txt").call();
184 RevCommit commit1 = git.commit().setMessage("create file").call();
185
186
187 writeTrashFile("file1.txt", join(content1));
188 git.add().addFilepattern("file1.txt").call();
189 git.rm().addFilepattern("file.txt").call();
190 git.commit().setMessage("moving file").call();
191
192
193 String[] content2 = new String[] { "a", "b" };
194 writeTrashFile("file1.txt", join(content2));
195 git.add().addFilepattern("file1.txt").call();
196 RevCommit commit3 = git.commit().setMessage("editing file").call();
197
198
199 writeTrashFile("file2.txt", join(content2));
200 git.add().addFilepattern("file2.txt").call();
201 git.rm().addFilepattern("file1.txt").call();
202 git.commit().setMessage("moving file again").call();
203
204 BlameCommand command = new BlameCommand(db);
205 command.setFollowFileRenames(true);
206 command.setFilePath("file2.txt");
207 BlameResult lines = command.call();
208
209 assertEquals(commit1, lines.getSourceCommit(0));
210 assertEquals(0, lines.getSourceLine(0));
211 assertEquals("file.txt", lines.getSourcePath(0));
212
213 assertEquals(commit3, lines.getSourceCommit(1));
214 assertEquals(1, lines.getSourceLine(1));
215 assertEquals("file1.txt", lines.getSourcePath(1));
216 }
217
218 @Test
219 public void testDeleteTrailingLines() throws Exception {
220 Git git = new Git(db);
221
222 String[] content1 = new String[] { "a", "b", "c", "d" };
223 String[] content2 = new String[] { "a", "b" };
224
225 writeTrashFile("file.txt", join(content2));
226 git.add().addFilepattern("file.txt").call();
227 RevCommit commit1 = git.commit().setMessage("create file").call();
228
229 writeTrashFile("file.txt", join(content1));
230 git.add().addFilepattern("file.txt").call();
231 git.commit().setMessage("edit file").call();
232
233 writeTrashFile("file.txt", join(content2));
234 git.add().addFilepattern("file.txt").call();
235 git.commit().setMessage("edit file").call();
236
237 BlameCommand command = new BlameCommand(db);
238
239 command.setFilePath("file.txt");
240 BlameResult lines = command.call();
241 assertEquals(content2.length, lines.getResultContents().size());
242
243 assertEquals(commit1, lines.getSourceCommit(0));
244 assertEquals(commit1, lines.getSourceCommit(1));
245
246 assertEquals(0, lines.getSourceLine(0));
247 assertEquals(1, lines.getSourceLine(1));
248 }
249
250 @Test
251 public void testDeleteMiddleLines() throws Exception {
252 Git git = new Git(db);
253
254 String[] content1 = new String[] { "a", "b", "c", "d", "e" };
255 String[] content2 = new String[] { "a", "c", "e" };
256
257 writeTrashFile("file.txt", join(content2));
258 git.add().addFilepattern("file.txt").call();
259 RevCommit commit1 = git.commit().setMessage("edit file").call();
260
261 writeTrashFile("file.txt", join(content1));
262 git.add().addFilepattern("file.txt").call();
263 git.commit().setMessage("edit file").call();
264
265 writeTrashFile("file.txt", join(content2));
266 git.add().addFilepattern("file.txt").call();
267 git.commit().setMessage("edit file").call();
268
269 BlameCommand command = new BlameCommand(db);
270
271 command.setFilePath("file.txt");
272 BlameResult lines = command.call();
273 assertEquals(content2.length, lines.getResultContents().size());
274
275 assertEquals(commit1, lines.getSourceCommit(0));
276 assertEquals(0, lines.getSourceLine(0));
277
278 assertEquals(commit1, lines.getSourceCommit(1));
279 assertEquals(1, lines.getSourceLine(1));
280
281 assertEquals(commit1, lines.getSourceCommit(2));
282 assertEquals(2, lines.getSourceLine(2));
283 }
284
285 @Test
286 public void testEditAllLines() throws Exception {
287 Git git = new Git(db);
288
289 String[] content1 = new String[] { "a", "1" };
290 String[] content2 = new String[] { "b", "2" };
291
292 writeTrashFile("file.txt", join(content1));
293 git.add().addFilepattern("file.txt").call();
294 git.commit().setMessage("edit file").call();
295
296 writeTrashFile("file.txt", join(content2));
297 git.add().addFilepattern("file.txt").call();
298 RevCommit commit2 = git.commit().setMessage("create file").call();
299
300 BlameCommand command = new BlameCommand(db);
301
302 command.setFilePath("file.txt");
303 BlameResult lines = command.call();
304 assertEquals(content2.length, lines.getResultContents().size());
305 assertEquals(commit2, lines.getSourceCommit(0));
306 assertEquals(commit2, lines.getSourceCommit(1));
307 }
308
309 @Test
310 public void testMiddleClearAllLines() throws Exception {
311 Git git = new Git(db);
312
313 String[] content1 = new String[] { "a", "b", "c" };
314
315 writeTrashFile("file.txt", join(content1));
316 git.add().addFilepattern("file.txt").call();
317 git.commit().setMessage("edit file").call();
318
319 writeTrashFile("file.txt", "");
320 git.add().addFilepattern("file.txt").call();
321 git.commit().setMessage("create file").call();
322
323 writeTrashFile("file.txt", join(content1));
324 git.add().addFilepattern("file.txt").call();
325 RevCommit commit3 = git.commit().setMessage("edit file").call();
326
327 BlameCommand command = new BlameCommand(db);
328
329 command.setFilePath("file.txt");
330 BlameResult lines = command.call();
331 assertEquals(content1.length, lines.getResultContents().size());
332 assertEquals(commit3, lines.getSourceCommit(0));
333 assertEquals(commit3, lines.getSourceCommit(1));
334 assertEquals(commit3, lines.getSourceCommit(2));
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 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 @Test
393 public void testConflictingMerge1() throws Exception {
394 Git git = new Git(db);
395
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 @Test
429 public void testConflictingMerge2() throws Exception {
430 Git git = new Git(db);
431
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 @Test
463 public void testWhitespaceMerge() throws Exception {
464 Git git = new Git(db);
465 RevCommit base = commitFile("file.txt", join("0", "1", "2"), "master");
466 RevCommit side = commitFile("file.txt", join("0", "1", " 2 side "),
467 "side");
468
469 checkoutBranch("refs/heads/master");
470 git.merge().setFastForward(FastForwardMode.NO_FF).include(side).call();
471
472
473
474 writeTrashFile("file.txt", join("0", "1", "2 side"));
475 RevCommit merge = git.commit().setAll(true).setMessage("merge")
476 .setAmend(true)
477 .call();
478
479 BlameCommand command = new BlameCommand(db);
480 command.setFilePath("file.txt")
481 .setTextComparator(RawTextComparator.WS_IGNORE_ALL)
482 .setStartCommit(merge.getId());
483 BlameResult lines = command.call();
484
485 assertEquals(3, lines.getResultContents().size());
486 assertEquals(base, lines.getSourceCommit(0));
487 assertEquals(base, lines.getSourceCommit(1));
488 assertEquals(side, lines.getSourceCommit(2));
489 }
490 }