/** * Set the repository the formatter can load object contents from. * * <p>Once a repository has been set, the formatter must be released to ensure the internal * ObjectReader is able to release its resources. * * @param repository source repository holding referenced objects. */ public void setRepository(Repository repository) { if (reader != null) reader.release(); db = repository; reader = db.newObjectReader(); ContentSource cs = ContentSource.create(reader); source = new ContentSource.Pair(cs, cs); DiffConfig dc = db.getConfig().get(DiffConfig.KEY); if (dc.isNoPrefix()) { setOldPrefix(""); // $NON-NLS-1$ setNewPrefix(""); // $NON-NLS-1$ } setDetectRenames(dc.isRenameDetectionEnabled()); diffAlgorithm = DiffAlgorithm.getAlgorithm( db.getConfig() .getEnum( ConfigConstants.CONFIG_DIFF_SECTION, null, ConfigConstants.CONFIG_KEY_ALGORITHM, SupportedAlgorithm.HISTOGRAM)); }
public void buildCompositeCommits() throws IOException { revWalk = new RevWalk(repository); ByteArrayOutputStream diffTexts = new ByteArrayOutputStream(); DiffFormatter df = new DiffFormatter(diffTexts); df.setRepository(repository); df.setDiffComparator(RawTextComparator.WS_IGNORE_ALL); df.setContext(0); df.setDiffAlgorithm(DiffAlgorithm.getAlgorithm(SupportedAlgorithm.HISTOGRAM)); df.setDetectRenames(true); for (int idx = 0; idx < _commits.size(); idx++) { RevCommit commit = revWalk.parseCommit(_commits.get(idx)); int p_count = commit.getParentCount(); if (p_count == 0) { throw new RuntimeException("commit with no parent ?!?!"); } RevCommit p = revWalk.parseCommit(commit.getParent(0).getId()); List<DiffEntry> diffs = df.scan(p.getTree(), commit.getTree()); for (DiffEntry d : diffs) { CompositeDiff cd = new CompositeDiff(d, commit); if (ParsingUtils.isSourceFile(d.getOldPath()) || ParsingUtils.isSourceFile(d.getNewPath())) { extractCodeEdits(diffTexts, df, d, cd); } _diffs.add(cd); } } revWalk.release(); }
/** * Determine the differences between two trees. * * <p>No output is created, instead only the file paths that are different are returned. Callers * may choose to format these paths themselves, or convert them into {@link FileHeader} instances * with a complete edit list by calling {@link #toFileHeader(DiffEntry)}. * * @param a the old (or previous) side. * @param b the new (or updated) side. * @return the paths that are different. * @throws IOException trees cannot be read or file contents cannot be read. */ public List<DiffEntry> scan(AbstractTreeIterator a, AbstractTreeIterator b) throws IOException { assertHaveRepository(); TreeWalk walk = new TreeWalk(reader); walk.addTree(a); walk.addTree(b); walk.setRecursive(true); TreeFilter filter = getDiffTreeFilterFor(a, b); if (pathFilter instanceof FollowFilter) { walk.setFilter( AndTreeFilter.create(PathFilter.create(((FollowFilter) pathFilter).getPath()), filter)); } else { walk.setFilter(AndTreeFilter.create(pathFilter, filter)); } source = new ContentSource.Pair(source(a), source(b)); List<DiffEntry> files = DiffEntry.scan(walk); if (pathFilter instanceof FollowFilter && isAdd(files)) { // The file we are following was added here, find where it // came from so we can properly show the rename or copy, // then continue digging backwards. // a.reset(); b.reset(); walk.reset(); walk.addTree(a); walk.addTree(b); walk.setFilter(filter); if (renameDetector == null) setDetectRenames(true); files = updateFollowFilter(detectRenames(DiffEntry.scan(walk))); } else if (renameDetector != null) files = detectRenames(files); return files; }
public static List<PathChangeModel> getFilesInCommit(Repository repository, RevCommit commit) { List<PathChangeModel> list = new ArrayList<PathChangeModel>(); if (!hasCommits(repository)) { return list; } RevWalk rw = new RevWalk(repository); try { if (commit == null) { ObjectId object = getDefaultBranch(repository); commit = rw.parseCommit(object); } if (commit.getParentCount() == 0) { TreeWalk tw = new TreeWalk(repository); tw.reset(); tw.setRecursive(true); tw.addTree(commit.getTree()); while (tw.next()) { list.add( new PathChangeModel( tw.getPathString(), tw.getPathString(), 0, tw.getRawMode(0), commit.getId().getName(), ChangeType.ADD)); } tw.release(); } else { RevCommit parent = rw.parseCommit(commit.getParent(0).getId()); DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE); df.setRepository(repository); df.setDiffComparator(RawTextComparator.DEFAULT); df.setDetectRenames(true); List<DiffEntry> diffs = df.scan(parent.getTree(), commit.getTree()); for (DiffEntry diff : diffs) { if (diff.getChangeType().equals(ChangeType.DELETE)) { list.add( new PathChangeModel( diff.getOldPath(), diff.getOldPath(), 0, diff.getNewMode().getBits(), commit.getId().getName(), diff.getChangeType())); } else { list.add( new PathChangeModel( diff.getNewPath(), diff.getNewPath(), 0, diff.getNewMode().getBits(), commit.getId().getName(), diff.getChangeType())); } } } } catch (Throwable t) { // todo Logger.error(t, t.getMessage()); } finally { rw.dispose(); } return list; }
protected String doDiff(Git git, String objectId, String baseObjectId, String path) { Repository r = git.getRepository(); /* RevCommit commit = JGitUtils.getCommit(r, objectId); ObjectId current; if (isNotBlank(objectId)) { current = BlobUtils.getId(r, objectId, blobPath); } else { current = CommitUtils.getHead(r).getId(); } ObjectId previous; if (isNotBlank(baseObjectId)) { previous = BlobUtils.getId(r, baseObjectId, blobPath); } else { RevCommit revCommit = CommitUtils.getCommit(r, current); RevCommit[] parents = revCommit.getParents(); if (parents.length == 0) { throw new IllegalArgumentException("No parent commits!"); } else { previous = parents[0]; } } Collection<Edit> changes = BlobUtils.diff(r, previous, current); // no idea how to format Collection<Edit> :) */ RevCommit commit; if (Strings.isNotBlank(objectId)) { commit = CommitUtils.getCommit(r, objectId); } else { commit = CommitUtils.getHead(r); } RevCommit baseCommit = null; if (Strings.isNotBlank(baseObjectId)) { baseCommit = CommitUtils.getCommit(r, baseObjectId); } ByteArrayOutputStream buffer = new ByteArrayOutputStream(); RawTextComparator cmp = RawTextComparator.DEFAULT; DiffFormatter formatter = new DiffFormatter(buffer); formatter.setRepository(r); formatter.setDiffComparator(cmp); formatter.setDetectRenames(true); RevTree commitTree = commit.getTree(); RevTree baseTree; try { if (baseCommit == null) { if (commit.getParentCount() > 0) { final RevWalk rw = new RevWalk(r); RevCommit parent = rw.parseCommit(commit.getParent(0).getId()); rw.dispose(); baseTree = parent.getTree(); } else { // FIXME initial commit. no parent?! baseTree = commitTree; } } else { baseTree = baseCommit.getTree(); } List<DiffEntry> diffEntries = formatter.scan(baseTree, commitTree); if (path != null && path.length() > 0) { for (DiffEntry diffEntry : diffEntries) { if (diffEntry.getNewPath().equalsIgnoreCase(path)) { formatter.format(diffEntry); break; } } } else { formatter.format(diffEntries); } formatter.flush(); return buffer.toString(); } catch (IOException e) { throw new RuntimeIOException(e); } }
/** * Returns the diff between two commits for the specified file. * * @param repository * @param baseCommit if base commit is null the diff is to the primary parent of the commit. * @param commit * @param path if the path is specified, the diff is restricted to that file or folder. if * unspecified, the diff is for the entire commit. * @param outputType * @return the diff */ public static DiffOutput getDiff( Repository repository, RevCommit baseCommit, RevCommit commit, String path, DiffOutputType outputType) { DiffStat stat = null; String diff = null; try { final ByteArrayOutputStream os = new ByteArrayOutputStream(); RawTextComparator cmp = RawTextComparator.DEFAULT; DiffFormatter df; switch (outputType) { case HTML: df = new GitBlitDiffFormatter(os, commit.getName()); break; case PLAIN: default: df = new DiffFormatter(os); break; } df.setRepository(repository); df.setDiffComparator(cmp); df.setDetectRenames(true); RevTree commitTree = commit.getTree(); RevTree baseTree; if (baseCommit == null) { if (commit.getParentCount() > 0) { final RevWalk rw = new RevWalk(repository); RevCommit parent = rw.parseCommit(commit.getParent(0).getId()); rw.dispose(); baseTree = parent.getTree(); } else { // FIXME initial commit. no parent?! baseTree = commitTree; } } else { baseTree = baseCommit.getTree(); } List<DiffEntry> diffEntries = df.scan(baseTree, commitTree); if (path != null && path.length() > 0) { for (DiffEntry diffEntry : diffEntries) { if (diffEntry.getNewPath().equalsIgnoreCase(path)) { df.format(diffEntry); break; } } } else { df.format(diffEntries); } if (df instanceof GitBlitDiffFormatter) { // workaround for complex private methods in DiffFormatter diff = ((GitBlitDiffFormatter) df).getHtml(); stat = ((GitBlitDiffFormatter) df).getDiffStat(); } else { diff = os.toString(); } df.flush(); } catch (Throwable t) { try { error(t, repository, "failed to generate commit diff!"); } catch (Exception e) { } } return new DiffOutput(outputType, diff, stat); }