Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import org.eclipse.jgit.api.errors.GitAPIException;
- import org.eclipse.jgit.api.errors.JGitInternalException;
- import org.eclipse.jgit.blame.BlameGenerator;
- import org.eclipse.jgit.blame.BlameResult;
- import org.eclipse.jgit.diff.*;
- import org.eclipse.jgit.lib.*;
- import org.eclipse.jgit.patch.FileHeader;
- import org.eclipse.jgit.revwalk.RevCommit;
- import org.eclipse.jgit.revwalk.RevTree;
- import org.eclipse.jgit.revwalk.RevWalk;
- import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
- import org.eclipse.jgit.treewalk.AbstractTreeIterator;
- import org.eclipse.jgit.treewalk.CanonicalTreeParser;
- import org.eclipse.jgit.util.io.DisabledOutputStream;
- import java.io.File;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- public class GitSegmentHistory {
- private static final String PROJECT_SAVE_TMX = "omegat/project_save.tmx";
- private static final Pattern SEGMENT_TEXT_PATTERN = Pattern.compile("(?:<seg>)(.+?)(?:</seg>)");
- private final Repository repo;
- /**
- * Constructor
- * @param repoPath local path to repository
- * @throws IOException
- */
- public GitSegmentHistory(String repoPath) throws IOException {
- this.repo = new FileRepositoryBuilder()
- .setGitDir(new File(repoPath + "/.git"))
- .build();
- }
- /**
- * Do `git blame` on project TMX searching for specific line starting with specified commit.
- *
- * @param lineNumber line to search (zero based)
- * @param startCommit starting commit
- * @return blame result containing searched line
- * @throws GitAPIException
- */
- private BlameResult blameLine(int lineNumber, ObjectId startCommit) throws GitAPIException {
- try (BlameGenerator gen = new BlameGenerator(repo, PROJECT_SAVE_TMX)) {
- gen.push(null, startCommit);
- BlameResult result = BlameResult.create(gen);
- while (true) {
- result.computeNext();
- if (result.hasSourceData(lineNumber)) break;
- }
- return result;
- } catch (IOException e) {
- throw new JGitInternalException(e.getMessage(), e);
- }
- }
- private AbstractTreeIterator prepareTreeParser(ObjectId commitId) throws IOException {
- try (RevWalk walk = new RevWalk(repo)) {
- RevCommit commit = walk.parseCommit(commitId);
- RevTree tree = walk.parseTree(commit.getTree().getId());
- CanonicalTreeParser treeParser = new CanonicalTreeParser();
- try (ObjectReader reader = repo.newObjectReader()) {
- treeParser.reset(reader, tree.getId());
- }
- walk.dispose();
- return treeParser;
- }
- }
- /**
- * Extract text from TMX line.
- * @param text TMX text line
- * @return clean text
- */
- private String extractText(String text) {
- Matcher matcher = SEGMENT_TEXT_PATTERN.matcher(text);
- if (matcher.find()) {
- text = matcher.group(1);
- }
- text = text.replaceAll("<", "<").replaceAll(">", ">");
- return text;
- }
- /**
- * Find segment revisions.
- * @param line line number (zero based)
- * @return
- */
- public List<SegmentRevision> findSegmentRevisions(int line) throws IOException, GitAPIException {
- List<SegmentRevision> result = new ArrayList<>();
- BlameResult br;
- ObjectId commitId = repo.resolve("HEAD");
- while (true) {
- // Extract line change details
- br = blameLine(line, commitId);
- String text = br.getResultContents().getString(line);
- text = extractText(text);
- String author = br.getSourceAuthor(line).getName();
- RevCommit commit = br.getSourceCommit(line);
- int time = commit.getCommitTime();
- SegmentRevision sr = new SegmentRevision(author, time, text);
- result.add(sr);
- // Change line/commitId for previous revision
- line = br.getSourceLine(line);
- commitId = commit.getParent(0).getId();
- // Check if this commit was the first one for this segment
- RevCommit prevCommit = commit.getParent(0);
- EditList edits;
- try (DiffFormatter formatter = new DiffFormatter(DisabledOutputStream.INSTANCE)) {
- formatter.setRepository(repo);
- AbstractTreeIterator thisTreeIterator, thatTreeIterator;
- thisTreeIterator = prepareTreeParser(commit.getId());
- thatTreeIterator = prepareTreeParser(prevCommit.getId());
- List<DiffEntry> entries = formatter.scan(thatTreeIterator, thisTreeIterator);
- FileHeader fileHeader = formatter.toFileHeader(entries.get(0));
- edits = fileHeader.toEditList();
- }
- boolean firstCommit = true;
- for (Edit e : edits) {
- if (e.getBeginB() <= line && e.getEndB() >= line) {
- switch (e.getType()) {
- case INSERT:
- firstCommit = true;
- break;
- case REPLACE:
- firstCommit = false;
- break;
- default:
- // Should not happen
- }
- break; // Break for-loop
- }
- }
- if (firstCommit) {
- break; // Break while-loop
- }
- }
- return result;
- }
- public static AbstractTreeIterator prepareTreeParser(Repository repository, String objectId) throws IOException {
- // from the commit we can build the tree which allows us to construct the TreeParser
- //noinspection Duplicates
- try (RevWalk walk = new RevWalk(repository)) {
- RevCommit commit = walk.parseCommit(repository.resolve(objectId));
- RevTree tree = walk.parseTree(commit.getTree().getId());
- CanonicalTreeParser treeParser = new CanonicalTreeParser();
- try (ObjectReader reader = repository.newObjectReader()) {
- treeParser.reset(reader, tree.getId());
- }
- walk.dispose();
- return treeParser;
- }
- }
- /**
- * Just testing here
- * @param args
- * @throws IOException
- * @throws GitAPIException
- */
- public static void main(String[] args) throws IOException, GitAPIException {
- String repoDir = "/home/user/omegat-projects/project/.repositories/git-repo-dir";
- int line = 123;
- GitSegmentHistory gsh = new GitSegmentHistory(repoDir);
- List<SegmentRevision> revisions = gsh.findSegmentRevisions(line);
- for (SegmentRevision item : revisions) {
- System.out.println(item);
- }
- }
- }
Add Comment
Please, Sign In to add comment