Handle diff formatting when there is nothing to compare with

DiffFormatter now suports either side being null and the log program
will output the diff for the first commit.

Bug: 395791
Change-Id: I378957b57e9ad1f7195ba416f402178453f0ebd3
This commit is contained in:
Robin Rosenberg 2014-06-29 22:31:26 +02:00
parent 71c18201c1
commit 89ad10ec27
3 changed files with 124 additions and 19 deletions

View File

@ -272,7 +272,7 @@ protected void show(final RevCommit c) throws Exception {
if (showNotes(c))
outw.println();
if (c.getParentCount() == 1 && (showNameAndStatusOnly || showPatch))
if (c.getParentCount() <= 1 && (showNameAndStatusOnly || showPatch))
showDiff(c);
outw.flush();
}
@ -345,7 +345,8 @@ private boolean showNotes(RevCommit c, NoteMap map, String label,
}
private void showDiff(RevCommit c) throws IOException {
final RevTree a = c.getParent(0).getTree();
final RevTree a = c.getParentCount() > 0 ? c.getParent(0).getTree()
: null;
final RevTree b = c.getTree();
if (showNameAndStatusOnly)

View File

@ -53,11 +53,13 @@
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.patch.FileHeader;
import org.eclipse.jgit.patch.HunkHeader;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.util.FileUtils;
@ -341,6 +343,82 @@ public void testDiff() throws Exception {
assertEquals(expected, actual);
}
@Test
public void testDiffRootNullToTree() throws Exception {
write(new File(db.getDirectory().getParent(), "test.txt"), "test");
File folder = new File(db.getDirectory().getParent(), "folder");
FileUtils.mkdir(folder);
write(new File(folder, "folder.txt"), "folder");
Git git = new Git(db);
git.add().addFilepattern(".").call();
RevCommit commit = git.commit().setMessage("Initial commit").call();
write(new File(folder, "folder.txt"), "folder change");
ByteArrayOutputStream os = new ByteArrayOutputStream();
DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os));
dfmt.setRepository(db);
dfmt.setPathFilter(PathFilter.create("folder"));
dfmt.format(null, commit.getTree().getId());
dfmt.flush();
String actual = os.toString("UTF-8");
String expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n"
+ "new file mode 100644\n"
+ "index 0000000..0119635\n"
+ "--- /dev/null\n"
+ "+++ b/folder/folder.txt\n"
+ "@@ -0,0 +1 @@\n"
+ "+folder\n"
+ "\\ No newline at end of file\n";
assertEquals(expected, actual);
}
@Test
public void testDiffRootTreeToNull() throws Exception {
write(new File(db.getDirectory().getParent(), "test.txt"), "test");
File folder = new File(db.getDirectory().getParent(), "folder");
FileUtils.mkdir(folder);
write(new File(folder, "folder.txt"), "folder");
Git git = new Git(db);
git.add().addFilepattern(".").call();
RevCommit commit = git.commit().setMessage("Initial commit").call();
write(new File(folder, "folder.txt"), "folder change");
ByteArrayOutputStream os = new ByteArrayOutputStream();
DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os));
dfmt.setRepository(db);
dfmt.setPathFilter(PathFilter.create("folder"));
dfmt.format(commit.getTree().getId(), null);
dfmt.flush();
String actual = os.toString("UTF-8");
String expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n"
+ "deleted file mode 100644\n"
+ "index 0119635..0000000\n"
+ "--- a/folder/folder.txt\n"
+ "+++ /dev/null\n"
+ "@@ -1 +0,0 @@\n"
+ "-folder\n"
+ "\\ No newline at end of file\n";
assertEquals(expected, actual);
}
@Test
public void testDiffNullToNull() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
DiffFormatter dfmt = new DiffFormatter(new SafeBufferedOutputStream(os));
dfmt.setRepository(db);
dfmt.format((AnyObjectId) null, null);
dfmt.flush();
String actual = os.toString("UTF-8");
String expected = "";
assertEquals(expected, actual);
}
private static String makeDiffHeader(String pathA, String pathB,
ObjectId aId,
ObjectId bId) {

View File

@ -67,6 +67,7 @@
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
@ -89,6 +90,7 @@
import org.eclipse.jgit.storage.pack.PackConfig;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
@ -391,11 +393,14 @@ public void release() {
* 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)}.
* <p>
* Either side may be null to indicate that the tree has beed added or
* removed. The diff will be computed against nothing.
*
* @param a
* the old (or previous) side.
* the old (or previous) side or null
* @param b
* the new (or updated) side.
* the new (or updated) side or null
* @return the paths that are different.
* @throws IOException
* trees cannot be read or file contents cannot be read.
@ -405,7 +410,9 @@ public List<DiffEntry> scan(AnyObjectId a, AnyObjectId b)
assertHaveRepository();
RevWalk rw = new RevWalk(reader);
return scan(rw.parseTree(a), rw.parseTree(b));
RevTree aTree = a != null ? rw.parseTree(a) : null;
RevTree bTree = b != null ? rw.parseTree(b) : null;
return scan(aTree, bTree);
}
/**
@ -415,11 +422,14 @@ public List<DiffEntry> scan(AnyObjectId a, AnyObjectId b)
* 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)}.
* <p>
* Either side may be null to indicate that the tree has beed added or
* removed. The diff will be computed against nothing.
*
* @param a
* the old (or previous) side.
* the old (or previous) side or null
* @param b
* the new (or updated) side.
* the new (or updated) side or null
* @return the paths that are different.
* @throws IOException
* trees cannot be read or file contents cannot be read.
@ -427,13 +437,19 @@ public List<DiffEntry> scan(AnyObjectId a, AnyObjectId b)
public List<DiffEntry> scan(RevTree a, RevTree b) throws IOException {
assertHaveRepository();
CanonicalTreeParser aParser = new CanonicalTreeParser();
CanonicalTreeParser bParser = new CanonicalTreeParser();
AbstractTreeIterator aIterator = makeIteratorFromTreeOrNull(a);
AbstractTreeIterator bIterator = makeIteratorFromTreeOrNull(b);
return scan(aIterator, bIterator);
}
aParser.reset(reader, a);
bParser.reset(reader, b);
return scan(aParser, bParser);
private AbstractTreeIterator makeIteratorFromTreeOrNull(RevTree tree)
throws IncorrectObjectTypeException, IOException {
if (tree != null) {
CanonicalTreeParser parser = new CanonicalTreeParser();
parser.reset(reader, tree);
return parser;
} else
return new EmptyTreeIterator();
}
/**
@ -553,11 +569,14 @@ private static boolean isRename(DiffEntry ent) {
*
* The patch is expressed as instructions to modify {@code a} to make it
* {@code b}.
* <p>
* Either side may be null to indicate that the tree has beed added or
* removed. The diff will be computed against nothing.
*
* @param a
* the old (or previous) side.
* the old (or previous) side or null
* @param b
* the new (or updated) side.
* the new (or updated) side or null
* @throws IOException
* trees cannot be read, file contents cannot be read, or the
* patch cannot be output.
@ -572,10 +591,14 @@ public void format(AnyObjectId a, AnyObjectId b) throws IOException {
* The patch is expressed as instructions to modify {@code a} to make it
* {@code b}.
*
* <p>
* Either side may be null to indicate that the tree has beed added or
* removed. The diff will be computed against nothing.
*
* @param a
* the old (or previous) side.
* the old (or previous) side or null
* @param b
* the new (or updated) side.
* the new (or updated) side or null
* @throws IOException
* trees cannot be read, file contents cannot be read, or the
* patch cannot be output.
@ -589,11 +612,14 @@ public void format(RevTree a, RevTree b) throws IOException {
*
* The patch is expressed as instructions to modify {@code a} to make it
* {@code b}.
* <p>
* Either side may be null to indicate that the tree has beed added or
* removed. The diff will be computed against nothing.
*
* @param a
* the old (or previous) side.
* the old (or previous) side or null
* @param b
* the new (or updated) side.
* the new (or updated) side or null
* @throws IOException
* trees cannot be read, file contents cannot be read, or the
* patch cannot be output.