/** * Push a candidate blob onto the generator's traversal stack. * * <p>Candidates should be pushed in history order from oldest-to-newest. Applications should push * the starting commit first, then the index revision (if the index is interesting), and finally * the working tree copy (if the working tree is interesting). * * @param description description of the blob revision, such as "Working Tree". * @param contents contents of the file. * @return {@code this} * @throws IOException the repository cannot be read. */ public BlameGenerator push(String description, RawText contents) throws IOException { if (description == null) description = JGitText.get().blameNotCommittedYet; BlobCandidate c = new BlobCandidate(description, resultPath); c.sourceText = contents; c.regionList = new Region(0, 0, contents.size()); remaining = contents.size(); push(c); return this; }
/** * Returns the list of lines in the specified source file annotated with the source commit * metadata. * * @param repository * @param blobPath * @param objectId * @return list of annotated lines */ public static List<AnnotatedLine> blame(Repository repository, String blobPath, String objectId) { List<AnnotatedLine> lines = new ArrayList<AnnotatedLine>(); try { ObjectId object; if (StringUtils.isEmpty(objectId)) { object = JGitUtils.getDefaultBranch(repository); } else { object = repository.resolve(objectId); } BlameCommand blameCommand = new BlameCommand(repository); blameCommand.setFilePath(blobPath); blameCommand.setStartCommit(object); BlameResult blameResult = blameCommand.call(); RawText rawText = blameResult.getResultContents(); int length = rawText.size(); for (int i = 0; i < length; i++) { RevCommit commit = blameResult.getSourceCommit(i); AnnotatedLine line = new AnnotatedLine(commit, i + 1, rawText.getString(i)); lines.add(line); } } catch (Throwable t) { try { error(t, repository, "failed to generate blame for {0} {1}!", blobPath, objectId); } catch (Exception e) { } } return lines; }
/** * Get list of hunks * * @throws java.io.IOException */ public List<Hunk> getHunks() throws IOException { List<Hunk> hunks = new ArrayList<>(); for (int curIdx = 0; curIdx < editList.size(); ) { Hunk hunk = new Hunk(); Edit curEdit = editList.get(curIdx); final int endIdx = findCombinedEnd(editList, curIdx); final Edit endEdit = editList.get(endIdx); int aCur = Math.max(0, curEdit.getBeginA() - context); int bCur = Math.max(0, curEdit.getBeginB() - context); final int aEnd = Math.min(a.size(), endEdit.getEndA() + context); final int bEnd = Math.min(b.size(), endEdit.getEndB() + context); hunk.beginA = aCur; hunk.endA = aEnd; hunk.beginB = bCur; hunk.endB = bEnd; while (aCur < aEnd || bCur < bEnd) { if (aCur < curEdit.getBeginA() || endIdx + 1 < curIdx) { hunk.lines.add(new DiffLine(this, DiffLineType.CONTEXT, aCur, bCur, a.getString(aCur))); isEndOfLineMissing = checkEndOfLineMissing(a, aCur); aCur++; bCur++; } else if (aCur < curEdit.getEndA()) { hunk.lines.add(new DiffLine(this, DiffLineType.REMOVE, aCur, bCur, a.getString(aCur))); isEndOfLineMissing = checkEndOfLineMissing(a, aCur); aCur++; } else if (bCur < curEdit.getEndB()) { hunk.lines.add(new DiffLine(this, DiffLineType.ADD, aCur, bCur, b.getString(bCur))); isEndOfLineMissing = checkEndOfLineMissing(a, aCur); bCur++; } if (end(curEdit, aCur, bCur) && ++curIdx < editList.size()) curEdit = editList.get(curIdx); } hunks.add(hunk); } return hunks; }
private int findLine(int b, String regex) { String re = regex.substring(1, regex.length() - 1); if (!re.startsWith("^")) // $NON-NLS-1$ re = ".*" + re; // $NON-NLS-1$ if (!re.endsWith("$")) // $NON-NLS-1$ re = re + ".*"; // $NON-NLS-1$ Pattern p = Pattern.compile(re); RawText text = blame.getResultContents(); for (int line = b; line < text.size(); line++) { if (p.matcher(text.getString(line)).matches()) return line; } return b; }
private boolean checkEndOfLineMissing(final RawText text, final int line) { return line + 1 == text.size() && text.isMissingNewlineAtEnd(); }