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.

BlameCommand.java 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Copyright (C) 2011, 2019 GitHub Inc. 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.api;
  11. import java.io.IOException;
  12. import java.util.ArrayList;
  13. import java.util.Collection;
  14. import java.util.Collections;
  15. import org.eclipse.jgit.api.errors.GitAPIException;
  16. import org.eclipse.jgit.api.errors.JGitInternalException;
  17. import org.eclipse.jgit.blame.BlameGenerator;
  18. import org.eclipse.jgit.blame.BlameResult;
  19. import org.eclipse.jgit.diff.DiffAlgorithm;
  20. import org.eclipse.jgit.diff.RawTextComparator;
  21. import org.eclipse.jgit.lib.AnyObjectId;
  22. import org.eclipse.jgit.lib.ObjectId;
  23. import org.eclipse.jgit.lib.Repository;
  24. /**
  25. * Blame command for building a {@link org.eclipse.jgit.blame.BlameResult} for a
  26. * file path.
  27. */
  28. public class BlameCommand extends GitCommand<BlameResult> {
  29. private String path;
  30. private DiffAlgorithm diffAlgorithm;
  31. private RawTextComparator textComparator;
  32. private ObjectId startCommit;
  33. private Collection<ObjectId> reverseEndCommits;
  34. private Boolean followFileRenames;
  35. /**
  36. * Constructor for BlameCommand
  37. *
  38. * @param repo
  39. * the {@link org.eclipse.jgit.lib.Repository}
  40. */
  41. public BlameCommand(Repository repo) {
  42. super(repo);
  43. }
  44. /**
  45. * Set file path.
  46. *
  47. * @param filePath
  48. * file path (with <code>/</code> as separator)
  49. * @return this command
  50. */
  51. public BlameCommand setFilePath(String filePath) {
  52. this.path = filePath;
  53. return this;
  54. }
  55. /**
  56. * Set diff algorithm
  57. *
  58. * @param diffAlgorithm
  59. * a {@link org.eclipse.jgit.diff.DiffAlgorithm} object.
  60. * @return this command
  61. */
  62. public BlameCommand setDiffAlgorithm(DiffAlgorithm diffAlgorithm) {
  63. this.diffAlgorithm = diffAlgorithm;
  64. return this;
  65. }
  66. /**
  67. * Set raw text comparator
  68. *
  69. * @param textComparator
  70. * a {@link org.eclipse.jgit.diff.RawTextComparator}
  71. * @return this command
  72. */
  73. public BlameCommand setTextComparator(RawTextComparator textComparator) {
  74. this.textComparator = textComparator;
  75. return this;
  76. }
  77. /**
  78. * Set start commit id
  79. *
  80. * @param commit
  81. * id of a commit
  82. * @return this command
  83. */
  84. public BlameCommand setStartCommit(AnyObjectId commit) {
  85. this.startCommit = commit.toObjectId();
  86. return this;
  87. }
  88. /**
  89. * Enable (or disable) following file renames.
  90. * <p>
  91. * If true renames are followed using the standard FollowFilter behavior
  92. * used by RevWalk (which matches {@code git log --follow} in the C
  93. * implementation). This is not the same as copy/move detection as
  94. * implemented by the C implementation's of {@code git blame -M -C}.
  95. *
  96. * @param follow
  97. * enable following.
  98. * @return {@code this}
  99. */
  100. public BlameCommand setFollowFileRenames(boolean follow) {
  101. followFileRenames = Boolean.valueOf(follow);
  102. return this;
  103. }
  104. /**
  105. * Configure the command to compute reverse blame (history of deletes).
  106. *
  107. * @param start
  108. * oldest commit to traverse from. The result file will be loaded
  109. * from this commit's tree.
  110. * @param end
  111. * most recent commit to stop traversal at. Usually an active
  112. * branch tip, tag, or HEAD.
  113. * @return {@code this}
  114. * @throws java.io.IOException
  115. * the repository cannot be read.
  116. */
  117. public BlameCommand reverse(AnyObjectId start, AnyObjectId end)
  118. throws IOException {
  119. return reverse(start, Collections.singleton(end.toObjectId()));
  120. }
  121. /**
  122. * Configure the generator to compute reverse blame (history of deletes).
  123. *
  124. * @param start
  125. * oldest commit to traverse from. The result file will be loaded
  126. * from this commit's tree.
  127. * @param end
  128. * most recent commits to stop traversal at. Usually an active
  129. * branch tip, tag, or HEAD.
  130. * @return {@code this}
  131. * @throws java.io.IOException
  132. * the repository cannot be read.
  133. */
  134. public BlameCommand reverse(AnyObjectId start, Collection<ObjectId> end)
  135. throws IOException {
  136. startCommit = start.toObjectId();
  137. reverseEndCommits = new ArrayList<>(end);
  138. return this;
  139. }
  140. /**
  141. * {@inheritDoc}
  142. * <p>
  143. * Generate a list of lines with information about when the lines were
  144. * introduced into the file path.
  145. */
  146. @Override
  147. public BlameResult call() throws GitAPIException {
  148. checkCallable();
  149. try (BlameGenerator gen = new BlameGenerator(repo, path)) {
  150. if (diffAlgorithm != null)
  151. gen.setDiffAlgorithm(diffAlgorithm);
  152. if (textComparator != null)
  153. gen.setTextComparator(textComparator);
  154. if (followFileRenames != null)
  155. gen.setFollowFileRenames(followFileRenames.booleanValue());
  156. if (reverseEndCommits != null)
  157. gen.reverse(startCommit, reverseEndCommits);
  158. else if (startCommit != null)
  159. gen.push(null, startCommit);
  160. else {
  161. gen.prepareHead();
  162. }
  163. return gen.computeBlameResult();
  164. } catch (IOException e) {
  165. throw new JGitInternalException(e.getMessage(), e);
  166. }
  167. }
  168. }