Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

BlameCommandTest.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*
  2. * Copyright (C) 2011, GitHub Inc.
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.api;
  44. import static org.junit.Assert.assertEquals;
  45. import static org.junit.Assert.assertNotNull;
  46. import java.io.File;
  47. import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
  48. import org.eclipse.jgit.api.ResetCommand.ResetType;
  49. import org.eclipse.jgit.blame.BlameResult;
  50. import org.eclipse.jgit.diff.RawTextComparator;
  51. import org.eclipse.jgit.junit.RepositoryTestCase;
  52. import org.eclipse.jgit.lib.ConfigConstants;
  53. import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
  54. import org.eclipse.jgit.revwalk.RevCommit;
  55. import org.eclipse.jgit.storage.file.FileBasedConfig;
  56. import org.junit.Test;
  57. /**
  58. * Unit tests of {@link BlameCommand}
  59. */
  60. public class BlameCommandTest extends RepositoryTestCase {
  61. private static String join(String... lines) {
  62. StringBuilder joined = new StringBuilder();
  63. for (String line : lines)
  64. joined.append(line).append('\n');
  65. return joined.toString();
  66. }
  67. @Test
  68. public void testSingleRevision() throws Exception {
  69. Git git = new Git(db);
  70. String[] content = new String[] { "first", "second", "third" };
  71. writeTrashFile("file.txt", join(content));
  72. git.add().addFilepattern("file.txt").call();
  73. RevCommit commit = git.commit().setMessage("create file").call();
  74. BlameCommand command = new BlameCommand(db);
  75. command.setFilePath("file.txt");
  76. BlameResult lines = command.call();
  77. assertNotNull(lines);
  78. assertEquals(3, lines.getResultContents().size());
  79. for (int i = 0; i < 3; i++) {
  80. assertEquals(commit, lines.getSourceCommit(i));
  81. assertEquals(i, lines.getSourceLine(i));
  82. }
  83. }
  84. @Test
  85. public void testTwoRevisions() throws Exception {
  86. Git git = new Git(db);
  87. String[] content1 = new String[] { "first", "second" };
  88. writeTrashFile("file.txt", join(content1));
  89. git.add().addFilepattern("file.txt").call();
  90. RevCommit commit1 = git.commit().setMessage("create file").call();
  91. String[] content2 = new String[] { "first", "second", "third" };
  92. writeTrashFile("file.txt", join(content2));
  93. git.add().addFilepattern("file.txt").call();
  94. RevCommit commit2 = git.commit().setMessage("create file").call();
  95. BlameCommand command = new BlameCommand(db);
  96. command.setFilePath("file.txt");
  97. BlameResult lines = command.call();
  98. assertEquals(3, lines.getResultContents().size());
  99. assertEquals(commit1, lines.getSourceCommit(0));
  100. assertEquals(0, lines.getSourceLine(0));
  101. assertEquals(commit1, lines.getSourceCommit(1));
  102. assertEquals(1, lines.getSourceLine(1));
  103. assertEquals(commit2, lines.getSourceCommit(2));
  104. assertEquals(2, lines.getSourceLine(2));
  105. }
  106. @Test
  107. public void testRename() throws Exception {
  108. testRename("file1.txt", "file2.txt");
  109. }
  110. @Test
  111. public void testRenameInSubDir() throws Exception {
  112. testRename("subdir/file1.txt", "subdir/file2.txt");
  113. }
  114. @Test
  115. public void testMoveToOtherDir() throws Exception {
  116. testRename("subdir/file1.txt", "otherdir/file1.txt");
  117. }
  118. private void testRename(final String sourcePath, final String destPath)
  119. throws Exception {
  120. Git git = new Git(db);
  121. String[] content1 = new String[] { "a", "b", "c" };
  122. writeTrashFile(sourcePath, join(content1));
  123. git.add().addFilepattern(sourcePath).call();
  124. RevCommit commit1 = git.commit().setMessage("create file").call();
  125. writeTrashFile(destPath, join(content1));
  126. git.add().addFilepattern(destPath).call();
  127. git.rm().addFilepattern(sourcePath).call();
  128. git.commit().setMessage("moving file").call();
  129. String[] content2 = new String[] { "a", "b", "c2" };
  130. writeTrashFile(destPath, join(content2));
  131. git.add().addFilepattern(destPath).call();
  132. RevCommit commit3 = git.commit().setMessage("editing file").call();
  133. BlameCommand command = new BlameCommand(db);
  134. command.setFollowFileRenames(true);
  135. command.setFilePath(destPath);
  136. BlameResult lines = command.call();
  137. assertEquals(commit1, lines.getSourceCommit(0));
  138. assertEquals(0, lines.getSourceLine(0));
  139. assertEquals(sourcePath, lines.getSourcePath(0));
  140. assertEquals(commit1, lines.getSourceCommit(1));
  141. assertEquals(1, lines.getSourceLine(1));
  142. assertEquals(sourcePath, lines.getSourcePath(1));
  143. assertEquals(commit3, lines.getSourceCommit(2));
  144. assertEquals(2, lines.getSourceLine(2));
  145. assertEquals(destPath, lines.getSourcePath(2));
  146. }
  147. @Test
  148. public void testTwoRenames() throws Exception {
  149. Git git = new Git(db);
  150. // Commit 1: Add file.txt
  151. String[] content1 = new String[] { "a" };
  152. writeTrashFile("file.txt", join(content1));
  153. git.add().addFilepattern("file.txt").call();
  154. RevCommit commit1 = git.commit().setMessage("create file").call();
  155. // Commit 2: Rename to file1.txt
  156. writeTrashFile("file1.txt", join(content1));
  157. git.add().addFilepattern("file1.txt").call();
  158. git.rm().addFilepattern("file.txt").call();
  159. git.commit().setMessage("moving file").call();
  160. // Commit 3: Edit file1.txt
  161. String[] content2 = new String[] { "a", "b" };
  162. writeTrashFile("file1.txt", join(content2));
  163. git.add().addFilepattern("file1.txt").call();
  164. RevCommit commit3 = git.commit().setMessage("editing file").call();
  165. // Commit 4: Rename to file2.txt
  166. writeTrashFile("file2.txt", join(content2));
  167. git.add().addFilepattern("file2.txt").call();
  168. git.rm().addFilepattern("file1.txt").call();
  169. git.commit().setMessage("moving file again").call();
  170. BlameCommand command = new BlameCommand(db);
  171. command.setFollowFileRenames(true);
  172. command.setFilePath("file2.txt");
  173. BlameResult lines = command.call();
  174. assertEquals(commit1, lines.getSourceCommit(0));
  175. assertEquals(0, lines.getSourceLine(0));
  176. assertEquals("file.txt", lines.getSourcePath(0));
  177. assertEquals(commit3, lines.getSourceCommit(1));
  178. assertEquals(1, lines.getSourceLine(1));
  179. assertEquals("file1.txt", lines.getSourcePath(1));
  180. }
  181. @Test
  182. public void testDeleteTrailingLines() throws Exception {
  183. Git git = new Git(db);
  184. String[] content1 = new String[] { "a", "b", "c", "d" };
  185. String[] content2 = new String[] { "a", "b" };
  186. writeTrashFile("file.txt", join(content2));
  187. git.add().addFilepattern("file.txt").call();
  188. RevCommit commit1 = git.commit().setMessage("create file").call();
  189. writeTrashFile("file.txt", join(content1));
  190. git.add().addFilepattern("file.txt").call();
  191. git.commit().setMessage("edit file").call();
  192. writeTrashFile("file.txt", join(content2));
  193. git.add().addFilepattern("file.txt").call();
  194. git.commit().setMessage("edit file").call();
  195. BlameCommand command = new BlameCommand(db);
  196. command.setFilePath("file.txt");
  197. BlameResult lines = command.call();
  198. assertEquals(content2.length, lines.getResultContents().size());
  199. assertEquals(commit1, lines.getSourceCommit(0));
  200. assertEquals(commit1, lines.getSourceCommit(1));
  201. assertEquals(0, lines.getSourceLine(0));
  202. assertEquals(1, lines.getSourceLine(1));
  203. }
  204. @Test
  205. public void testDeleteMiddleLines() throws Exception {
  206. Git git = new Git(db);
  207. String[] content1 = new String[] { "a", "b", "c", "d", "e" };
  208. String[] content2 = new String[] { "a", "c", "e" };
  209. writeTrashFile("file.txt", join(content2));
  210. git.add().addFilepattern("file.txt").call();
  211. RevCommit commit1 = git.commit().setMessage("edit file").call();
  212. writeTrashFile("file.txt", join(content1));
  213. git.add().addFilepattern("file.txt").call();
  214. git.commit().setMessage("edit file").call();
  215. writeTrashFile("file.txt", join(content2));
  216. git.add().addFilepattern("file.txt").call();
  217. git.commit().setMessage("edit file").call();
  218. BlameCommand command = new BlameCommand(db);
  219. command.setFilePath("file.txt");
  220. BlameResult lines = command.call();
  221. assertEquals(content2.length, lines.getResultContents().size());
  222. assertEquals(commit1, lines.getSourceCommit(0));
  223. assertEquals(0, lines.getSourceLine(0));
  224. assertEquals(commit1, lines.getSourceCommit(1));
  225. assertEquals(1, lines.getSourceLine(1));
  226. assertEquals(commit1, lines.getSourceCommit(2));
  227. assertEquals(2, lines.getSourceLine(2));
  228. }
  229. @Test
  230. public void testEditAllLines() throws Exception {
  231. Git git = new Git(db);
  232. String[] content1 = new String[] { "a", "1" };
  233. String[] content2 = new String[] { "b", "2" };
  234. writeTrashFile("file.txt", join(content1));
  235. git.add().addFilepattern("file.txt").call();
  236. git.commit().setMessage("edit file").call();
  237. writeTrashFile("file.txt", join(content2));
  238. git.add().addFilepattern("file.txt").call();
  239. RevCommit commit2 = git.commit().setMessage("create file").call();
  240. BlameCommand command = new BlameCommand(db);
  241. command.setFilePath("file.txt");
  242. BlameResult lines = command.call();
  243. assertEquals(content2.length, lines.getResultContents().size());
  244. assertEquals(commit2, lines.getSourceCommit(0));
  245. assertEquals(commit2, lines.getSourceCommit(1));
  246. }
  247. @Test
  248. public void testMiddleClearAllLines() throws Exception {
  249. Git git = new Git(db);
  250. String[] content1 = new String[] { "a", "b", "c" };
  251. writeTrashFile("file.txt", join(content1));
  252. git.add().addFilepattern("file.txt").call();
  253. git.commit().setMessage("edit file").call();
  254. writeTrashFile("file.txt", "");
  255. git.add().addFilepattern("file.txt").call();
  256. git.commit().setMessage("create file").call();
  257. writeTrashFile("file.txt", join(content1));
  258. git.add().addFilepattern("file.txt").call();
  259. RevCommit commit3 = git.commit().setMessage("edit file").call();
  260. BlameCommand command = new BlameCommand(db);
  261. command.setFilePath("file.txt");
  262. BlameResult lines = command.call();
  263. assertEquals(content1.length, lines.getResultContents().size());
  264. assertEquals(commit3, lines.getSourceCommit(0));
  265. assertEquals(commit3, lines.getSourceCommit(1));
  266. assertEquals(commit3, lines.getSourceCommit(2));
  267. }
  268. @Test
  269. public void testCoreAutoCrlf1() throws Exception {
  270. testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.FALSE);
  271. }
  272. @Test
  273. public void testCoreAutoCrlf2() throws Exception {
  274. testCoreAutoCrlf(AutoCRLF.FALSE, AutoCRLF.FALSE);
  275. }
  276. @Test
  277. public void testCoreAutoCrlf3() throws Exception {
  278. testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.INPUT);
  279. }
  280. @Test
  281. public void testCoreAutoCrlf4() throws Exception {
  282. testCoreAutoCrlf(AutoCRLF.FALSE, AutoCRLF.INPUT);
  283. }
  284. @Test
  285. public void testCoreAutoCrlf5() throws Exception {
  286. testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.TRUE);
  287. }
  288. private void testCoreAutoCrlf(AutoCRLF modeForCommitting,
  289. AutoCRLF modeForReset) throws Exception {
  290. Git git = new Git(db);
  291. FileBasedConfig config = db.getConfig();
  292. config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
  293. ConfigConstants.CONFIG_KEY_AUTOCRLF, modeForCommitting);
  294. config.save();
  295. String joinedCrlf = "a\r\nb\r\nc\r\n";
  296. File trashFile = writeTrashFile("file.txt", joinedCrlf);
  297. git.add().addFilepattern("file.txt").call();
  298. RevCommit commit = git.commit().setMessage("create file").call();
  299. // re-create file from the repo
  300. trashFile.delete();
  301. config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
  302. ConfigConstants.CONFIG_KEY_AUTOCRLF, modeForReset);
  303. config.save();
  304. git.reset().setMode(ResetType.HARD).call();
  305. BlameCommand command = new BlameCommand(db);
  306. command.setFilePath("file.txt");
  307. BlameResult lines = command.call();
  308. assertEquals(3, lines.getResultContents().size());
  309. assertEquals(commit, lines.getSourceCommit(0));
  310. assertEquals(commit, lines.getSourceCommit(1));
  311. assertEquals(commit, lines.getSourceCommit(2));
  312. }
  313. @Test
  314. public void testConflictingMerge1() throws Exception {
  315. Git git = new Git(db);
  316. RevCommit base = commitFile("file.txt", join("0", "1", "2", "3", "4"),
  317. "master");
  318. git.checkout().setName("side").setCreateBranch(true)
  319. .setStartPoint(base).call();
  320. RevCommit side = commitFile("file.txt",
  321. join("0", "1 side", "2", "3 on side", "4"), "side");
  322. commitFile("file.txt", join("0", "1", "2"), "master");
  323. checkoutBranch("refs/heads/master");
  324. git.merge().include(side).call();
  325. // The merge results in a conflict, which we resolve using mostly the
  326. // side branch contents. Especially the "4" survives.
  327. RevCommit merge = commitFile("file.txt",
  328. join("0", "1 side", "2", "3 resolved", "4"), "master");
  329. BlameCommand command = new BlameCommand(db);
  330. command.setFilePath("file.txt");
  331. BlameResult lines = command.call();
  332. assertEquals(5, lines.getResultContents().size());
  333. assertEquals(base, lines.getSourceCommit(0));
  334. assertEquals(side, lines.getSourceCommit(1));
  335. assertEquals(base, lines.getSourceCommit(2));
  336. assertEquals(merge, lines.getSourceCommit(3));
  337. assertEquals(base, lines.getSourceCommit(4));
  338. }
  339. // this test inverts the order of the master and side commit and is
  340. // otherwise identical to testConflictingMerge1
  341. @Test
  342. public void testConflictingMerge2() throws Exception {
  343. Git git = new Git(db);
  344. RevCommit base = commitFile("file.txt", join("0", "1", "2", "3", "4"),
  345. "master");
  346. commitFile("file.txt", join("0", "1", "2"), "master");
  347. git.checkout().setName("side").setCreateBranch(true)
  348. .setStartPoint(base).call();
  349. RevCommit side = commitFile("file.txt",
  350. join("0", "1 side", "2", "3 on side", "4"), "side");
  351. checkoutBranch("refs/heads/master");
  352. git.merge().include(side).call();
  353. // The merge results in a conflict, which we resolve using mostly the
  354. // side branch contents. Especially the "4" survives.
  355. RevCommit merge = commitFile("file.txt",
  356. join("0", "1 side", "2", "3 resolved", "4"), "master");
  357. BlameCommand command = new BlameCommand(db);
  358. command.setFilePath("file.txt");
  359. BlameResult lines = command.call();
  360. assertEquals(5, lines.getResultContents().size());
  361. assertEquals(base, lines.getSourceCommit(0));
  362. assertEquals(side, lines.getSourceCommit(1));
  363. assertEquals(base, lines.getSourceCommit(2));
  364. assertEquals(merge, lines.getSourceCommit(3));
  365. assertEquals(base, lines.getSourceCommit(4));
  366. }
  367. @Test
  368. public void testWhitespaceMerge() throws Exception {
  369. Git git = new Git(db);
  370. RevCommit base = commitFile("file.txt", join("0", "1", "2"), "master");
  371. RevCommit side = commitFile("file.txt", join("0", "1", " 2 side "),
  372. "side");
  373. checkoutBranch("refs/heads/master");
  374. git.merge().setFastForward(FastForwardMode.NO_FF).include(side).call();
  375. // change whitespace, so the merge content is not identical to side, but
  376. // is the same when ignoring whitespace
  377. writeTrashFile("file.txt", join("0", "1", "2 side"));
  378. RevCommit merge = git.commit().setAll(true).setMessage("merge")
  379. .setAmend(true)
  380. .call();
  381. BlameCommand command = new BlameCommand(db);
  382. command.setFilePath("file.txt")
  383. .setTextComparator(RawTextComparator.WS_IGNORE_ALL)
  384. .setStartCommit(merge.getId());
  385. BlameResult lines = command.call();
  386. assertEquals(3, lines.getResultContents().size());
  387. assertEquals(base, lines.getSourceCommit(0));
  388. assertEquals(base, lines.getSourceCommit(1));
  389. assertEquals(side, lines.getSourceCommit(2));
  390. }
  391. }