private boolean isAdd(List<DiffEntry> files) { String oldPath = ((FollowFilter) pathFilter).getPath(); for (DiffEntry ent : files) { if (ent.getChangeType() == ADD && ent.getNewPath().equals(oldPath)) return true; } return false; }
private void formatOldNewPaths(ByteArrayOutputStream o, DiffEntry ent) throws IOException { if (ent.oldId.equals(ent.newId)) return; final String oldp; final String newp; switch (ent.getChangeType()) { case ADD: oldp = DiffEntry.DEV_NULL; newp = quotePath(newPrefix + ent.getNewPath()); break; case DELETE: oldp = quotePath(oldPrefix + ent.getOldPath()); newp = DiffEntry.DEV_NULL; break; default: oldp = quotePath(oldPrefix + ent.getOldPath()); newp = quotePath(newPrefix + ent.getNewPath()); break; } o.write(encode("--- " + oldp + "\n")); // $NON-NLS-1$ //$NON-NLS-2$ o.write(encode("+++ " + newp + "\n")); // $NON-NLS-1$ //$NON-NLS-2$ }
private List<DiffEntry> updateFollowFilter(List<DiffEntry> files) { String oldPath = ((FollowFilter) pathFilter).getPath(); for (DiffEntry ent : files) { if (isRename(ent) && ent.getNewPath().equals(oldPath)) { pathFilter = FollowFilter.create(ent.getOldPath()); return Collections.singletonList(ent); } } return Collections.emptyList(); }
private FormatResult createFormatResult(DiffEntry ent) throws IOException, CorruptObjectException, MissingObjectException { final FormatResult res = new FormatResult(); ByteArrayOutputStream buf = new ByteArrayOutputStream(); final EditList editList; final FileHeader.PatchType type; formatHeader(buf, ent); if (ent.getOldMode() == GITLINK || ent.getNewMode() == GITLINK) { formatOldNewPaths(buf, ent); writeGitLinkDiffText(buf, ent); editList = new EditList(); type = PatchType.UNIFIED; } else { assertHaveRepository(); byte[] aRaw = open(OLD, ent); byte[] bRaw = open(NEW, ent); if (aRaw == BINARY || bRaw == BINARY // || RawText.isBinary(aRaw) || RawText.isBinary(bRaw)) { formatOldNewPaths(buf, ent); buf.write(encodeASCII("Binary files differ\n")); // $NON-NLS-1$ editList = new EditList(); type = PatchType.BINARY; } else { res.a = new RawText(aRaw); res.b = new RawText(bRaw); editList = diff(res.a, res.b); type = PatchType.UNIFIED; switch (ent.getChangeType()) { case RENAME: case COPY: if (!editList.isEmpty()) formatOldNewPaths(buf, ent); break; default: formatOldNewPaths(buf, ent); break; } } } res.header = new FileHeader(buf.toByteArray(), editList, type); return res; }
/** * @param o the stream the formatter will write line data to * @param ent the DiffEntry to create the FileHeader for * @throws IOException writing to the supplied stream failed. */ protected void formatIndexLine(OutputStream o, DiffEntry ent) throws IOException { o.write( encodeASCII( "index " // //$NON-NLS-1$ + format(ent.getOldId()) // + ".." // //$NON-NLS-1$ + format(ent.getNewId()))); if (ent.getOldMode().equals(ent.getNewMode())) { o.write(' '); ent.getNewMode().copyTo(o); } o.write('\n'); }
public String toString() { try { updateDiffInfo(); Iterator iter = getDifferences().iterator(); StringBuffer sb = new StringBuffer(); while (iter.hasNext()) { DiffEntry de = (DiffEntry) iter.next(); sb.append(de.toString()); } return sb.toString(); } catch (IntrospectionException e) { return e.getMessage(); } }
private void writeGitLinkDiffText(OutputStream o, DiffEntry ent) throws IOException { if (ent.getOldMode() == GITLINK) { o.write( encodeASCII( "-Subproject commit " + ent.getOldId().name() // $NON-NLS-1$ + "\n")); //$NON-NLS-1$ } if (ent.getNewMode() == GITLINK) { o.write( encodeASCII( "+Subproject commit " + ent.getNewId().name() // $NON-NLS-1$ + "\n")); //$NON-NLS-1$ } }
private byte[] open(DiffEntry.Side side, DiffEntry entry) throws IOException { if (entry.getMode(side) == FileMode.MISSING) return EMPTY; if (entry.getMode(side).getObjectType() != Constants.OBJ_BLOB) return EMPTY; if (isBinary()) return BINARY; AbbreviatedObjectId id = entry.getId(side); if (!id.isComplete()) { Collection<ObjectId> ids = reader.resolve(id); if (ids.size() == 1) { id = AbbreviatedObjectId.fromObjectId(ids.iterator().next()); switch (side) { case OLD: entry.oldId = id; break; case NEW: entry.newId = id; break; } } else if (ids.size() == 0) throw new MissingObjectException(id, Constants.OBJ_BLOB); else throw new AmbiguousObjectException(id, ids); } try { ObjectLoader ldr = source.open(side, entry); return ldr.getBytes(binaryFileThreshold); } catch (LargeObjectException.ExceedsLimit overLimit) { return BINARY; } catch (LargeObjectException.ExceedsByteArrayLimit overLimit) { return BINARY; } catch (LargeObjectException.OutOfMemory tooBig) { return BINARY; } catch (LargeObjectException tooBig) { tooBig.setObjectId(id.toObjectId()); throw tooBig; } }
/** * 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; }
private void formatHeader(ByteArrayOutputStream o, DiffEntry ent) throws IOException { final ChangeType type = ent.getChangeType(); final String oldp = ent.getOldPath(); final String newp = ent.getNewPath(); final FileMode oldMode = ent.getOldMode(); final FileMode newMode = ent.getNewMode(); formatGitDiffFirstHeaderLine(o, type, oldp, newp); switch (type) { case ADD: o.write(encodeASCII("new file mode ")); // $NON-NLS-1$ newMode.copyTo(o); o.write('\n'); break; case DELETE: o.write(encodeASCII("deleted file mode ")); // $NON-NLS-1$ oldMode.copyTo(o); o.write('\n'); break; case RENAME: o.write( encodeASCII("similarity index " + ent.getScore() + "%")); // $NON-NLS-1$ //$NON-NLS-2$ o.write('\n'); o.write(encode("rename from " + quotePath(oldp))); // $NON-NLS-1$ o.write('\n'); o.write(encode("rename to " + quotePath(newp))); // $NON-NLS-1$ o.write('\n'); break; case COPY: o.write( encodeASCII("similarity index " + ent.getScore() + "%")); // $NON-NLS-1$ //$NON-NLS-2$ o.write('\n'); o.write(encode("copy from " + quotePath(oldp))); // $NON-NLS-1$ o.write('\n'); o.write(encode("copy to " + quotePath(newp))); // $NON-NLS-1$ o.write('\n'); if (!oldMode.equals(newMode)) { o.write(encodeASCII("new file mode ")); // $NON-NLS-1$ newMode.copyTo(o); o.write('\n'); } break; case MODIFY: if (0 < ent.getScore()) { o.write( encodeASCII( "dissimilarity index " //$NON-NLS-1$ + (100 - ent.getScore()) + "%")); //$NON-NLS-1$ o.write('\n'); } break; } if ((type == MODIFY || type == RENAME) && !oldMode.equals(newMode)) { o.write(encodeASCII("old mode ")); // $NON-NLS-1$ oldMode.copyTo(o); o.write('\n'); o.write(encodeASCII("new mode ")); // $NON-NLS-1$ newMode.copyTo(o); o.write('\n'); } if (!ent.getOldId().equals(ent.getNewId())) { formatIndexLine(o, ent); } }
private static boolean isRename(DiffEntry ent) { return ent.getChangeType() == RENAME || ent.getChangeType() == COPY; }