You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BlameTest.java 4.2KB

Make blame work correctly on merge conflicts When a conflicting file was blamed, JGit would not identify lines coming from the merge parents. The main cause for this was that Blame and BlameCommand simply added the first DirCacheEntry found for a file to its queue of candidates (blobs or commits) to consider. In case of a conflict this typically is the merge base commit, and comparing a auto-merged contents against that base would yield incorrect results. Such cases have to be handled specially. The candidate to be considered by the blame must use the working tree contents, but at the same time behave like a merge commit/candidate with HEAD and the MERGE_HEADs as parents. Canonical git does something very similar, see [1]. Implement that and add tests. I first did this for the JGit pgm Blame command. When I then tried to do the same in BlameCommand, I noticed that the latter also included some fancy but incomplete CR-LF handling. In order to be able to use the new BlameGenerator.prepareHead() also in BlameCommand this CR-LF handling was also moved into BlameGenerator and corrected in doing so. (Just considering the git config settings was not good enough, CR-LF behavior can also be influenced by .gitattributes, and even by whether the file in the index has CR-LF. To correctly determine CR-LF handling for check-in one needs to do a TreeWalk with at least a FileTreeIterator and a DirCacheIterator.) [1] https://github.com/git/git/blob/v2.22.0/blame.c#L174 Bug: 434330 Change-Id: I9d763dd6ba478b0b6ebf9456049d6301f478ef7c Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
4 years ago
Make blame work correctly on merge conflicts When a conflicting file was blamed, JGit would not identify lines coming from the merge parents. The main cause for this was that Blame and BlameCommand simply added the first DirCacheEntry found for a file to its queue of candidates (blobs or commits) to consider. In case of a conflict this typically is the merge base commit, and comparing a auto-merged contents against that base would yield incorrect results. Such cases have to be handled specially. The candidate to be considered by the blame must use the working tree contents, but at the same time behave like a merge commit/candidate with HEAD and the MERGE_HEADs as parents. Canonical git does something very similar, see [1]. Implement that and add tests. I first did this for the JGit pgm Blame command. When I then tried to do the same in BlameCommand, I noticed that the latter also included some fancy but incomplete CR-LF handling. In order to be able to use the new BlameGenerator.prepareHead() also in BlameCommand this CR-LF handling was also moved into BlameGenerator and corrected in doing so. (Just considering the git config settings was not good enough, CR-LF behavior can also be influenced by .gitattributes, and even by whether the file in the index has CR-LF. To correctly determine CR-LF handling for check-in one needs to do a TreeWalk with at least a FileTreeIterator and a DirCacheIterator.) [1] https://github.com/git/git/blob/v2.22.0/blame.c#L174 Bug: 434330 Change-Id: I9d763dd6ba478b0b6ebf9456049d6301f478ef7c Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
4 years ago
Make blame work correctly on merge conflicts When a conflicting file was blamed, JGit would not identify lines coming from the merge parents. The main cause for this was that Blame and BlameCommand simply added the first DirCacheEntry found for a file to its queue of candidates (blobs or commits) to consider. In case of a conflict this typically is the merge base commit, and comparing a auto-merged contents against that base would yield incorrect results. Such cases have to be handled specially. The candidate to be considered by the blame must use the working tree contents, but at the same time behave like a merge commit/candidate with HEAD and the MERGE_HEADs as parents. Canonical git does something very similar, see [1]. Implement that and add tests. I first did this for the JGit pgm Blame command. When I then tried to do the same in BlameCommand, I noticed that the latter also included some fancy but incomplete CR-LF handling. In order to be able to use the new BlameGenerator.prepareHead() also in BlameCommand this CR-LF handling was also moved into BlameGenerator and corrected in doing so. (Just considering the git config settings was not good enough, CR-LF behavior can also be influenced by .gitattributes, and even by whether the file in the index has CR-LF. To correctly determine CR-LF handling for check-in one needs to do a TreeWalk with at least a FileTreeIterator and a DirCacheIterator.) [1] https://github.com/git/git/blob/v2.22.0/blame.c#L174 Bug: 434330 Change-Id: I9d763dd6ba478b0b6ebf9456049d6301f478ef7c Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
4 years ago
Make blame work correctly on merge conflicts When a conflicting file was blamed, JGit would not identify lines coming from the merge parents. The main cause for this was that Blame and BlameCommand simply added the first DirCacheEntry found for a file to its queue of candidates (blobs or commits) to consider. In case of a conflict this typically is the merge base commit, and comparing a auto-merged contents against that base would yield incorrect results. Such cases have to be handled specially. The candidate to be considered by the blame must use the working tree contents, but at the same time behave like a merge commit/candidate with HEAD and the MERGE_HEADs as parents. Canonical git does something very similar, see [1]. Implement that and add tests. I first did this for the JGit pgm Blame command. When I then tried to do the same in BlameCommand, I noticed that the latter also included some fancy but incomplete CR-LF handling. In order to be able to use the new BlameGenerator.prepareHead() also in BlameCommand this CR-LF handling was also moved into BlameGenerator and corrected in doing so. (Just considering the git config settings was not good enough, CR-LF behavior can also be influenced by .gitattributes, and even by whether the file in the index has CR-LF. To correctly determine CR-LF handling for check-in one needs to do a TreeWalk with at least a FileTreeIterator and a DirCacheIterator.) [1] https://github.com/git/git/blob/v2.22.0/blame.c#L174 Bug: 434330 Change-Id: I9d763dd6ba478b0b6ebf9456049d6301f478ef7c Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
4 years ago
Make blame work correctly on merge conflicts When a conflicting file was blamed, JGit would not identify lines coming from the merge parents. The main cause for this was that Blame and BlameCommand simply added the first DirCacheEntry found for a file to its queue of candidates (blobs or commits) to consider. In case of a conflict this typically is the merge base commit, and comparing a auto-merged contents against that base would yield incorrect results. Such cases have to be handled specially. The candidate to be considered by the blame must use the working tree contents, but at the same time behave like a merge commit/candidate with HEAD and the MERGE_HEADs as parents. Canonical git does something very similar, see [1]. Implement that and add tests. I first did this for the JGit pgm Blame command. When I then tried to do the same in BlameCommand, I noticed that the latter also included some fancy but incomplete CR-LF handling. In order to be able to use the new BlameGenerator.prepareHead() also in BlameCommand this CR-LF handling was also moved into BlameGenerator and corrected in doing so. (Just considering the git config settings was not good enough, CR-LF behavior can also be influenced by .gitattributes, and even by whether the file in the index has CR-LF. To correctly determine CR-LF handling for check-in one needs to do a TreeWalk with at least a FileTreeIterator and a DirCacheIterator.) [1] https://github.com/git/git/blob/v2.22.0/blame.c#L174 Bug: 434330 Change-Id: I9d763dd6ba478b0b6ebf9456049d6301f478ef7c Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
4 years ago
Make blame work correctly on merge conflicts When a conflicting file was blamed, JGit would not identify lines coming from the merge parents. The main cause for this was that Blame and BlameCommand simply added the first DirCacheEntry found for a file to its queue of candidates (blobs or commits) to consider. In case of a conflict this typically is the merge base commit, and comparing a auto-merged contents against that base would yield incorrect results. Such cases have to be handled specially. The candidate to be considered by the blame must use the working tree contents, but at the same time behave like a merge commit/candidate with HEAD and the MERGE_HEADs as parents. Canonical git does something very similar, see [1]. Implement that and add tests. I first did this for the JGit pgm Blame command. When I then tried to do the same in BlameCommand, I noticed that the latter also included some fancy but incomplete CR-LF handling. In order to be able to use the new BlameGenerator.prepareHead() also in BlameCommand this CR-LF handling was also moved into BlameGenerator and corrected in doing so. (Just considering the git config settings was not good enough, CR-LF behavior can also be influenced by .gitattributes, and even by whether the file in the index has CR-LF. To correctly determine CR-LF handling for check-in one needs to do a TreeWalk with at least a FileTreeIterator and a DirCacheIterator.) [1] https://github.com/git/git/blob/v2.22.0/blame.c#L174 Bug: 434330 Change-Id: I9d763dd6ba478b0b6ebf9456049d6301f478ef7c Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
4 years ago
Make blame work correctly on merge conflicts When a conflicting file was blamed, JGit would not identify lines coming from the merge parents. The main cause for this was that Blame and BlameCommand simply added the first DirCacheEntry found for a file to its queue of candidates (blobs or commits) to consider. In case of a conflict this typically is the merge base commit, and comparing a auto-merged contents against that base would yield incorrect results. Such cases have to be handled specially. The candidate to be considered by the blame must use the working tree contents, but at the same time behave like a merge commit/candidate with HEAD and the MERGE_HEADs as parents. Canonical git does something very similar, see [1]. Implement that and add tests. I first did this for the JGit pgm Blame command. When I then tried to do the same in BlameCommand, I noticed that the latter also included some fancy but incomplete CR-LF handling. In order to be able to use the new BlameGenerator.prepareHead() also in BlameCommand this CR-LF handling was also moved into BlameGenerator and corrected in doing so. (Just considering the git config settings was not good enough, CR-LF behavior can also be influenced by .gitattributes, and even by whether the file in the index has CR-LF. To correctly determine CR-LF handling for check-in one needs to do a TreeWalk with at least a FileTreeIterator and a DirCacheIterator.) [1] https://github.com/git/git/blob/v2.22.0/blame.c#L174 Bug: 434330 Change-Id: I9d763dd6ba478b0b6ebf9456049d6301f478ef7c Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
4 years ago
Make blame work correctly on merge conflicts When a conflicting file was blamed, JGit would not identify lines coming from the merge parents. The main cause for this was that Blame and BlameCommand simply added the first DirCacheEntry found for a file to its queue of candidates (blobs or commits) to consider. In case of a conflict this typically is the merge base commit, and comparing a auto-merged contents against that base would yield incorrect results. Such cases have to be handled specially. The candidate to be considered by the blame must use the working tree contents, but at the same time behave like a merge commit/candidate with HEAD and the MERGE_HEADs as parents. Canonical git does something very similar, see [1]. Implement that and add tests. I first did this for the JGit pgm Blame command. When I then tried to do the same in BlameCommand, I noticed that the latter also included some fancy but incomplete CR-LF handling. In order to be able to use the new BlameGenerator.prepareHead() also in BlameCommand this CR-LF handling was also moved into BlameGenerator and corrected in doing so. (Just considering the git config settings was not good enough, CR-LF behavior can also be influenced by .gitattributes, and even by whether the file in the index has CR-LF. To correctly determine CR-LF handling for check-in one needs to do a TreeWalk with at least a FileTreeIterator and a DirCacheIterator.) [1] https://github.com/git/git/blob/v2.22.0/blame.c#L174 Bug: 434330 Change-Id: I9d763dd6ba478b0b6ebf9456049d6301f478ef7c Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * Copyright (C) 2019 Thomas Wolf <thomas.wolf@paranor.ch> and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.pgm;
  11. import static org.junit.Assert.assertThrows;
  12. import static org.junit.Assert.assertTrue;
  13. import org.eclipse.jgit.api.Git;
  14. import org.eclipse.jgit.api.MergeResult;
  15. import org.eclipse.jgit.lib.CLIRepositoryTestCase;
  16. import org.eclipse.jgit.lib.Constants;
  17. import org.eclipse.jgit.lib.PersonIdent;
  18. import org.eclipse.jgit.revwalk.RevCommit;
  19. import org.junit.Test;
  20. public class BlameTest extends CLIRepositoryTestCase {
  21. @Test
  22. public void testBlameNoHead() throws Exception {
  23. try (Git git = new Git(db)) {
  24. writeTrashFile("inIndex.txt", "index");
  25. git.add().addFilepattern("inIndex.txt").call();
  26. }
  27. assertThrows("no such ref: HEAD", Die.class,
  28. () -> execute("git blame inIndex.txt"));
  29. }
  30. @Test
  31. public void testBlameCommitted() throws Exception {
  32. try (Git git = new Git(db)) {
  33. git.commit().setMessage("initial commit").call();
  34. writeTrashFile("committed.txt", "committed");
  35. git.add().addFilepattern("committed.txt").call();
  36. git.commit().setMessage("commit").call();
  37. }
  38. assertStringArrayEquals(
  39. "1ad3399c (GIT_COMMITTER_NAME 2009-08-15 20:12:58 -0330 1) committed",
  40. execute("git blame committed.txt"));
  41. }
  42. @Test
  43. public void testBlameStaged() throws Exception {
  44. try (Git git = new Git(db)) {
  45. git.commit().setMessage("initial commit").call();
  46. writeTrashFile("inIndex.txt", "index");
  47. git.add().addFilepattern("inIndex.txt").call();
  48. }
  49. assertStringArrayEquals(
  50. "00000000 (Not Committed Yet 2009-08-15 20:12:58 -0330 1) index",
  51. execute("git blame inIndex.txt"));
  52. }
  53. @Test
  54. public void testBlameUnstaged() throws Exception {
  55. try (Git git = new Git(db)) {
  56. git.commit().setMessage("initial commit").call();
  57. }
  58. writeTrashFile("onlyInWorkingTree.txt", "not in repo");
  59. assertThrows("no such path 'onlyInWorkingTree.txt' in HEAD", Die.class,
  60. () -> execute("git blame onlyInWorkingTree.txt"));
  61. }
  62. @Test
  63. public void testBlameNonExisting() throws Exception {
  64. try (Git git = new Git(db)) {
  65. git.commit().setMessage("initial commit").call();
  66. }
  67. assertThrows("no such path 'does_not_exist.txt' in HEAD", Die.class,
  68. () -> execute("git blame does_not_exist.txt"));
  69. }
  70. @Test
  71. public void testBlameNonExistingInSubdir() throws Exception {
  72. try (Git git = new Git(db)) {
  73. git.commit().setMessage("initial commit").call();
  74. }
  75. assertThrows("no such path 'sub/does_not_exist.txt' in HEAD", Die.class,
  76. () -> execute("git blame sub/does_not_exist.txt"));
  77. }
  78. @Test
  79. public void testBlameMergeConflict() throws Exception {
  80. try (Git git = new Git(db)) {
  81. writeTrashFile("file", "Origin\n");
  82. git.add().addFilepattern("file").call();
  83. git.commit().setMessage("initial commit").call();
  84. git.checkout().setCreateBranch(true)
  85. .setName("side").call();
  86. writeTrashFile("file",
  87. "Conflicting change from side branch\n");
  88. git.add().addFilepattern("file").call();
  89. RevCommit side = git.commit().setMessage("side commit")
  90. .setCommitter(new PersonIdent("gitter", "")).call();
  91. git.checkout().setName(Constants.MASTER).call();
  92. writeTrashFile("file", "Change on master branch\n");
  93. git.add().addFilepattern("file").call();
  94. git.commit().setMessage("Commit conflict on master")
  95. .setCommitter(new PersonIdent("gitter", "")).call();
  96. MergeResult result = git.merge()
  97. .include("side", side).call();
  98. assertTrue("Expected conflict on 'file'",
  99. result.getConflicts().containsKey("file"));
  100. }
  101. String[] expected = {
  102. "00000000 (Not Committed Yet 2009-08-15 20:12:58 -0330 1) <<<<<<< HEAD",
  103. "0f5b671c (gitter 2009-08-15 20:12:58 -0330 2) Change on master branch",
  104. "00000000 (Not Committed Yet 2009-08-15 20:12:58 -0330 3) =======",
  105. "ae78cff6 (gitter 2009-08-15 20:12:58 -0330 4) Conflicting change from side branch",
  106. "00000000 (Not Committed Yet 2009-08-15 20:12:58 -0330 5) >>>>>>> side" };
  107. assertArrayOfLinesEquals(expected, execute("git blame file"));
  108. }
  109. }