Browse Source

Merge "Correct diff header formatting"

stable-0.9
Chris Aniszczyk 14 years ago committed by Code Review
parent
commit
097406ba5e
  1. 70
      org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java
  2. 249
      org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java

70
org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java

@ -77,6 +77,76 @@ public class DiffFormatterTest extends RepositoryTestCase {
df.setAbbreviationLength(8); df.setAbbreviationLength(8);
} }
public void testCreateFileHeader_Add() throws Exception {
ObjectId adId = blob("a\nd\n");
DiffEntry ent = DiffEntry.add("FOO", adId);
FileHeader fh = df.createFileHeader(ent);
String diffHeader = "diff --git a/FOO b/FOO\n" //
+ "new file mode " + REGULAR_FILE + "\n"
+ "index "
+ ObjectId.zeroId().abbreviate(8).name()
+ ".."
+ adId.abbreviate(8).name() + "\n" //
+ "--- /dev/null\n"//
+ "+++ b/FOO\n";
assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
assertEquals(0, fh.getStartOffset());
assertEquals(fh.getBuffer().length, fh.getEndOffset());
assertEquals(FileHeader.PatchType.UNIFIED, fh.getPatchType());
assertEquals(1, fh.getHunks().size());
HunkHeader hh = fh.getHunks().get(0);
assertEquals(1, hh.toEditList().size());
EditList el = hh.toEditList();
assertEquals(1, el.size());
Edit e = el.get(0);
assertEquals(0, e.getBeginA());
assertEquals(0, e.getEndA());
assertEquals(0, e.getBeginB());
assertEquals(2, e.getEndB());
assertEquals(Edit.Type.INSERT, e.getType());
}
public void testCreateFileHeader_Delete() throws Exception {
ObjectId adId = blob("a\nd\n");
DiffEntry ent = DiffEntry.delete("FOO", adId);
FileHeader fh = df.createFileHeader(ent);
String diffHeader = "diff --git a/FOO b/FOO\n" //
+ "deleted file mode " + REGULAR_FILE + "\n"
+ "index "
+ adId.abbreviate(8).name()
+ ".."
+ ObjectId.zeroId().abbreviate(8).name() + "\n" //
+ "--- a/FOO\n"//
+ "+++ /dev/null\n";
assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
assertEquals(0, fh.getStartOffset());
assertEquals(fh.getBuffer().length, fh.getEndOffset());
assertEquals(FileHeader.PatchType.UNIFIED, fh.getPatchType());
assertEquals(1, fh.getHunks().size());
HunkHeader hh = fh.getHunks().get(0);
assertEquals(1, hh.toEditList().size());
EditList el = hh.toEditList();
assertEquals(1, el.size());
Edit e = el.get(0);
assertEquals(0, e.getBeginA());
assertEquals(2, e.getEndA());
assertEquals(0, e.getBeginB());
assertEquals(0, e.getEndB());
assertEquals(Edit.Type.DELETE, e.getType());
}
public void testCreateFileHeader_Modify() throws Exception { public void testCreateFileHeader_Modify() throws Exception {
ObjectId adId = blob("a\nd\n"); ObjectId adId = blob("a\nd\n");
ObjectId abcdId = blob("a\nb\nc\nd\n"); ObjectId abcdId = blob("a\nb\nc\nd\n");

249
org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java

@ -44,6 +44,10 @@
package org.eclipse.jgit.diff; package org.eclipse.jgit.diff;
import static org.eclipse.jgit.diff.DiffEntry.ChangeType.ADD;
import static org.eclipse.jgit.diff.DiffEntry.ChangeType.DELETE;
import static org.eclipse.jgit.diff.DiffEntry.ChangeType.MODIFY;
import static org.eclipse.jgit.diff.DiffEntry.ChangeType.RENAME;
import static org.eclipse.jgit.lib.Constants.encode; import static org.eclipse.jgit.lib.Constants.encode;
import static org.eclipse.jgit.lib.Constants.encodeASCII; import static org.eclipse.jgit.lib.Constants.encodeASCII;
import static org.eclipse.jgit.lib.FileMode.GITLINK; import static org.eclipse.jgit.lib.FileMode.GITLINK;
@ -55,6 +59,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import org.eclipse.jgit.JGitText; import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.errors.AmbiguousObjectException; import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.MissingObjectException;
@ -90,6 +95,10 @@ public class DiffFormatter {
private int bigFileThreshold = 50 * 1024 * 1024; private int bigFileThreshold = 50 * 1024 * 1024;
private String oldPrefix = "a/";
private String newPrefix = "b/";
/** /**
* Create a new formatter with a default level of context. * Create a new formatter with a default level of context.
* *
@ -178,6 +187,32 @@ public class DiffFormatter {
this.bigFileThreshold = bigFileThreshold; this.bigFileThreshold = bigFileThreshold;
} }
/**
* Set the prefix applied in front of old file paths.
*
* @param prefix
* the prefix in front of old paths. Typically this is the
* standard string {@code "a/"}, but may be any prefix desired by
* the caller. Must not be null. Use the empty string to have no
* prefix at all.
*/
public void setOldPrefix(String prefix) {
oldPrefix = prefix;
}
/**
* Set the prefix applied in front of new file paths.
*
* @param prefix
* the prefix in front of new paths. Typically this is the
* standard string {@code "b/"}, but may be any prefix desired by
* the caller. Must not be null. Use the empty string to have no
* prefix at all.
*/
public void setNewPrefix(String prefix) {
newPrefix = prefix;
}
/** /**
* Flush the underlying output stream of this formatter. * Flush the underlying output stream of this formatter.
* *
@ -228,89 +263,6 @@ public class DiffFormatter {
} }
} }
private void writeDiffHeader(OutputStream o, DiffEntry ent)
throws IOException {
String oldName = quotePath("a/" + ent.getOldPath());
String newName = quotePath("b/" + ent.getNewPath());
o.write(encode("diff --git " + oldName + " " + newName + "\n"));
switch (ent.getChangeType()) {
case ADD:
o.write(encodeASCII("new file mode "));
ent.getNewMode().copyTo(o);
o.write('\n');
break;
case DELETE:
o.write(encodeASCII("deleted file mode "));
ent.getOldMode().copyTo(o);
o.write('\n');
break;
case RENAME:
o.write(encodeASCII("similarity index " + ent.getScore() + "%"));
o.write('\n');
o.write(encode("rename from " + quotePath(ent.getOldPath())));
o.write('\n');
o.write(encode("rename to " + quotePath(ent.getNewPath())));
o.write('\n');
break;
case COPY:
o.write(encodeASCII("similarity index " + ent.getScore() + "%"));
o.write('\n');
o.write(encode("copy from " + quotePath(ent.getOldPath())));
o.write('\n');
o.write(encode("copy to " + quotePath(ent.getNewPath())));
o.write('\n');
if (!ent.getOldMode().equals(ent.getNewMode())) {
o.write(encodeASCII("new file mode "));
ent.getNewMode().copyTo(o);
o.write('\n');
}
break;
case MODIFY:
int score = ent.getScore();
if (0 < score && score <= 100) {
o.write(encodeASCII("dissimilarity index " + (100 - score)
+ "%"));
o.write('\n');
}
break;
}
switch (ent.getChangeType()) {
case RENAME:
case MODIFY:
if (!ent.getOldMode().equals(ent.getNewMode())) {
o.write(encodeASCII("old mode "));
ent.getOldMode().copyTo(o);
o.write('\n');
o.write(encodeASCII("new mode "));
ent.getNewMode().copyTo(o);
o.write('\n');
}
}
o.write(encodeASCII("index " //
+ format(ent.getOldId()) //
+ ".." //
+ format(ent.getNewId())));
if (ent.getOldMode().equals(ent.getNewMode())) {
o.write(' ');
ent.getNewMode().copyTo(o);
}
o.write('\n');
o.write(encode("--- " + oldName + '\n'));
o.write(encode("+++ " + newName + '\n'));
}
private String format(AbbreviatedObjectId id) { private String format(AbbreviatedObjectId id) {
if (id.isComplete() && db != null) { if (id.isComplete() && db != null) {
ObjectReader reader = db.newObjectReader(); ObjectReader reader = db.newObjectReader();
@ -596,12 +548,14 @@ public class DiffFormatter {
final EditList editList; final EditList editList;
final FileHeader.PatchType type; final FileHeader.PatchType type;
writeDiffHeader(buf, ent); formatHeader(buf, ent);
if (ent.getOldMode() == GITLINK || ent.getNewMode() == GITLINK) { if (ent.getOldMode() == GITLINK || ent.getNewMode() == GITLINK) {
formatOldNewPaths(buf, ent);
writeGitLinkDiffText(buf, ent); writeGitLinkDiffText(buf, ent);
editList = new EditList(); editList = new EditList();
type = PatchType.UNIFIED; type = PatchType.UNIFIED;
} else { } else {
if (db == null) if (db == null)
throw new IllegalStateException( throw new IllegalStateException(
@ -616,14 +570,28 @@ public class DiffFormatter {
} }
if (RawText.isBinary(aRaw) || RawText.isBinary(bRaw)) { if (RawText.isBinary(aRaw) || RawText.isBinary(bRaw)) {
formatOldNewPaths(buf, ent);
buf.write(encodeASCII("Binary files differ\n")); buf.write(encodeASCII("Binary files differ\n"));
editList = new EditList(); editList = new EditList();
type = PatchType.BINARY; type = PatchType.BINARY;
} else { } else {
res.a = rawTextFactory.create(aRaw); res.a = rawTextFactory.create(aRaw);
res.b = rawTextFactory.create(bRaw); res.b = rawTextFactory.create(bRaw);
editList = new MyersDiff(res.a, res.b).getEdits(); editList = new MyersDiff(res.a, res.b).getEdits();
type = PatchType.UNIFIED; type = PatchType.UNIFIED;
switch (ent.getChangeType()) {
case RENAME:
case COPY:
if (!editList.isEmpty())
formatOldNewPaths(buf, ent);
break;
default:
formatOldNewPaths(buf, ent);
break;
}
} }
} }
@ -631,6 +599,119 @@ public class DiffFormatter {
return res; return res;
} }
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();
o.write(encodeASCII("diff --git "));
o.write(encode(quotePath(oldPrefix + (type == ADD ? newp : oldp))));
o.write(' ');
o.write(encode(quotePath(newPrefix + (type == DELETE ? oldp : newp))));
o.write('\n');
switch (type) {
case ADD:
o.write(encodeASCII("new file mode "));
newMode.copyTo(o);
o.write('\n');
break;
case DELETE:
o.write(encodeASCII("deleted file mode "));
oldMode.copyTo(o);
o.write('\n');
break;
case RENAME:
o.write(encodeASCII("similarity index " + ent.getScore() + "%"));
o.write('\n');
o.write(encode("rename from " + quotePath(oldp)));
o.write('\n');
o.write(encode("rename to " + quotePath(newp)));
o.write('\n');
break;
case COPY:
o.write(encodeASCII("similarity index " + ent.getScore() + "%"));
o.write('\n');
o.write(encode("copy from " + quotePath(oldp)));
o.write('\n');
o.write(encode("copy to " + quotePath(newp)));
o.write('\n');
if (!oldMode.equals(newMode)) {
o.write(encodeASCII("new file mode "));
newMode.copyTo(o);
o.write('\n');
}
break;
case MODIFY:
if (0 < ent.getScore()) {
o.write(encodeASCII("dissimilarity index "
+ (100 - ent.getScore()) + "%"));
o.write('\n');
}
break;
}
if ((type == MODIFY || type == RENAME) && !oldMode.equals(newMode)) {
o.write(encodeASCII("old mode "));
oldMode.copyTo(o);
o.write('\n');
o.write(encodeASCII("new mode "));
newMode.copyTo(o);
o.write('\n');
}
if (!ent.getOldId().equals(ent.getNewId())) {
o.write(encodeASCII("index " //
+ format(ent.getOldId()) //
+ ".." //
+ format(ent.getNewId())));
if (oldMode.equals(newMode)) {
o.write(' ');
newMode.copyTo(o);
}
o.write('\n');
}
}
private void formatOldNewPaths(ByteArrayOutputStream o, DiffEntry ent)
throws IOException {
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"));
o.write(encode("+++ " + newp + "\n"));
}
private int findCombinedEnd(final List<Edit> edits, final int i) { private int findCombinedEnd(final List<Edit> edits, final int i) {
int end = i + 1; int end = i + 1;
while (end < edits.size() while (end < edits.size()

Loading…
Cancel
Save