Guest User

Untitled

a guest
Oct 24th, 2017
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.79 KB | None | 0 0
  1. import org.eclipse.jgit.api.errors.GitAPIException;
  2. import org.eclipse.jgit.api.errors.JGitInternalException;
  3. import org.eclipse.jgit.blame.BlameGenerator;
  4. import org.eclipse.jgit.blame.BlameResult;
  5. import org.eclipse.jgit.diff.*;
  6. import org.eclipse.jgit.lib.*;
  7. import org.eclipse.jgit.patch.FileHeader;
  8. import org.eclipse.jgit.revwalk.RevCommit;
  9. import org.eclipse.jgit.revwalk.RevTree;
  10. import org.eclipse.jgit.revwalk.RevWalk;
  11. import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
  12. import org.eclipse.jgit.treewalk.AbstractTreeIterator;
  13. import org.eclipse.jgit.treewalk.CanonicalTreeParser;
  14. import org.eclipse.jgit.util.io.DisabledOutputStream;
  15.  
  16. import java.io.File;
  17. import java.io.IOException;
  18. import java.util.ArrayList;
  19. import java.util.List;
  20. import java.util.regex.Matcher;
  21. import java.util.regex.Pattern;
  22.  
  23. public class GitSegmentHistory {
  24.  
  25. private static final String PROJECT_SAVE_TMX = "omegat/project_save.tmx";
  26. private static final Pattern SEGMENT_TEXT_PATTERN = Pattern.compile("(?:<seg>)(.+?)(?:</seg>)");
  27.  
  28. private final Repository repo;
  29.  
  30. /**
  31. * Constructor
  32. * @param repoPath local path to repository
  33. * @throws IOException
  34. */
  35. public GitSegmentHistory(String repoPath) throws IOException {
  36. this.repo = new FileRepositoryBuilder()
  37. .setGitDir(new File(repoPath + "/.git"))
  38. .build();
  39. }
  40.  
  41. /**
  42. * Do `git blame` on project TMX searching for specific line starting with specified commit.
  43. *
  44. * @param lineNumber line to search (zero based)
  45. * @param startCommit starting commit
  46. * @return blame result containing searched line
  47. * @throws GitAPIException
  48. */
  49. private BlameResult blameLine(int lineNumber, ObjectId startCommit) throws GitAPIException {
  50.  
  51. try (BlameGenerator gen = new BlameGenerator(repo, PROJECT_SAVE_TMX)) {
  52.  
  53. gen.push(null, startCommit);
  54. BlameResult result = BlameResult.create(gen);
  55. while (true) {
  56. result.computeNext();
  57. if (result.hasSourceData(lineNumber)) break;
  58. }
  59. return result;
  60. } catch (IOException e) {
  61. throw new JGitInternalException(e.getMessage(), e);
  62. }
  63. }
  64.  
  65. private AbstractTreeIterator prepareTreeParser(ObjectId commitId) throws IOException {
  66.  
  67. try (RevWalk walk = new RevWalk(repo)) {
  68. RevCommit commit = walk.parseCommit(commitId);
  69. RevTree tree = walk.parseTree(commit.getTree().getId());
  70.  
  71. CanonicalTreeParser treeParser = new CanonicalTreeParser();
  72. try (ObjectReader reader = repo.newObjectReader()) {
  73. treeParser.reset(reader, tree.getId());
  74. }
  75.  
  76. walk.dispose();
  77.  
  78. return treeParser;
  79. }
  80. }
  81.  
  82. /**
  83. * Extract text from TMX line.
  84. * @param text TMX text line
  85. * @return clean text
  86. */
  87. private String extractText(String text) {
  88. Matcher matcher = SEGMENT_TEXT_PATTERN.matcher(text);
  89. if (matcher.find()) {
  90. text = matcher.group(1);
  91. }
  92. text = text.replaceAll("<", "<").replaceAll(">", ">");
  93. return text;
  94. }
  95.  
  96.  
  97. /**
  98. * Find segment revisions.
  99. * @param line line number (zero based)
  100. * @return
  101. */
  102. public List<SegmentRevision> findSegmentRevisions(int line) throws IOException, GitAPIException {
  103. List<SegmentRevision> result = new ArrayList<>();
  104.  
  105. BlameResult br;
  106. ObjectId commitId = repo.resolve("HEAD");
  107.  
  108. while (true) {
  109. // Extract line change details
  110. br = blameLine(line, commitId);
  111. String text = br.getResultContents().getString(line);
  112. text = extractText(text);
  113. String author = br.getSourceAuthor(line).getName();
  114. RevCommit commit = br.getSourceCommit(line);
  115. int time = commit.getCommitTime();
  116. SegmentRevision sr = new SegmentRevision(author, time, text);
  117. result.add(sr);
  118.  
  119. // Change line/commitId for previous revision
  120. line = br.getSourceLine(line);
  121. commitId = commit.getParent(0).getId();
  122.  
  123. // Check if this commit was the first one for this segment
  124. RevCommit prevCommit = commit.getParent(0);
  125. EditList edits;
  126.  
  127. try (DiffFormatter formatter = new DiffFormatter(DisabledOutputStream.INSTANCE)) {
  128. formatter.setRepository(repo);
  129. AbstractTreeIterator thisTreeIterator, thatTreeIterator;
  130. thisTreeIterator = prepareTreeParser(commit.getId());
  131. thatTreeIterator = prepareTreeParser(prevCommit.getId());
  132. List<DiffEntry> entries = formatter.scan(thatTreeIterator, thisTreeIterator);
  133. FileHeader fileHeader = formatter.toFileHeader(entries.get(0));
  134. edits = fileHeader.toEditList();
  135. }
  136.  
  137. boolean firstCommit = true;
  138. for (Edit e : edits) {
  139. if (e.getBeginB() <= line && e.getEndB() >= line) {
  140. switch (e.getType()) {
  141. case INSERT:
  142. firstCommit = true;
  143. break;
  144. case REPLACE:
  145. firstCommit = false;
  146. break;
  147. default:
  148. // Should not happen
  149. }
  150. break; // Break for-loop
  151. }
  152. }
  153.  
  154. if (firstCommit) {
  155. break; // Break while-loop
  156. }
  157.  
  158. }
  159.  
  160. return result;
  161. }
  162.  
  163. public static AbstractTreeIterator prepareTreeParser(Repository repository, String objectId) throws IOException {
  164. // from the commit we can build the tree which allows us to construct the TreeParser
  165. //noinspection Duplicates
  166. try (RevWalk walk = new RevWalk(repository)) {
  167. RevCommit commit = walk.parseCommit(repository.resolve(objectId));
  168. RevTree tree = walk.parseTree(commit.getTree().getId());
  169.  
  170. CanonicalTreeParser treeParser = new CanonicalTreeParser();
  171. try (ObjectReader reader = repository.newObjectReader()) {
  172. treeParser.reset(reader, tree.getId());
  173. }
  174.  
  175. walk.dispose();
  176.  
  177. return treeParser;
  178. }
  179. }
  180.  
  181.  
  182. /**
  183. * Just testing here
  184. * @param args
  185. * @throws IOException
  186. * @throws GitAPIException
  187. */
  188. public static void main(String[] args) throws IOException, GitAPIException {
  189.  
  190. String repoDir = "/home/user/omegat-projects/project/.repositories/git-repo-dir";
  191. int line = 123;
  192.  
  193. GitSegmentHistory gsh = new GitSegmentHistory(repoDir);
  194. List<SegmentRevision> revisions = gsh.findSegmentRevisions(line);
  195. for (SegmentRevision item : revisions) {
  196. System.out.println(item);
  197. }
  198. }
  199. }
Add Comment
Please, Sign In to add comment