JGit pgm: Format blame output to match canonical git

Canonical git shows the zero-Id for lines without commit, and
uses the current time stamp for such lines.

Also consider lines without commit when calculating the field
widths.

Change-Id: If0bee9b3e7f90861ad0f387f68e52ecc4a53dfd7
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/BlameTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/BlameTest.java
index 732c54e..6da1e46 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/BlameTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/BlameTest.java
@@ -48,6 +48,7 @@
 import org.eclipse.jgit.api.MergeResult;
 import org.eclipse.jgit.lib.CLIRepositoryTestCase;
 import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.junit.Rule;
 import org.junit.Test;
@@ -90,7 +91,7 @@ public void testBlameStaged() throws Exception {
 			git.add().addFilepattern("inIndex.txt").call();
 		}
 		assertStringArrayEquals(
-				"         (Not Committed Yet          1) index",
+				"00000000 (Not Committed Yet 2009-08-15 20:12:58 -0330 1) index",
 				execute("git blame inIndex.txt"));
 	}
 
@@ -136,22 +137,24 @@ public void testBlameMergeConflict() throws Exception {
 			writeTrashFile("file",
 					"Conflicting change from side branch\n");
 			git.add().addFilepattern("file").call();
-			RevCommit side = git.commit().setMessage("side commit").call();
+			RevCommit side = git.commit().setMessage("side commit")
+					.setCommitter(new PersonIdent("gitter", "")).call();
 			git.checkout().setName(Constants.MASTER).call();
 			writeTrashFile("file", "Change on master branch\n");
 			git.add().addFilepattern("file").call();
-			git.commit().setMessage("Commit conflict on master").call();
+			git.commit().setMessage("Commit conflict on master")
+					.setCommitter(new PersonIdent("gitter", "")).call();
 			MergeResult result = git.merge()
 					.include("side", side).call();
 			assertTrue("Expected conflict on 'file'",
 					result.getConflicts().containsKey("file"));
 		}
 		String[] expected = {
-				"         (Not Committed Yet                            1) <<<<<<< HEAD",
-				"7a918de5 (GIT_COMMITTER_NAME 2009-08-15 20:12:58 -0330 2) Change on master branch",
-				"         (Not Committed Yet                            3) =======",
-				"beb52f68 (GIT_COMMITTER_NAME 2009-08-15 20:12:58 -0330 4) Conflicting change from side branch",
-				"         (Not Committed Yet                            5) >>>>>>> side" };
+				"00000000 (Not Committed Yet 2009-08-15 20:12:58 -0330 1) <<<<<<< HEAD",
+				"0f5b671c (gitter            2009-08-15 20:12:58 -0330 2) Change on master branch",
+				"00000000 (Not Committed Yet 2009-08-15 20:12:58 -0330 3) =======",
+				"ae78cff6 (gitter            2009-08-15 20:12:58 -0330 4) Conflicting change from side branch",
+				"00000000 (Not Committed Yet 2009-08-15 20:12:58 -0330 5) >>>>>>> side" };
 		assertArrayOfLinesEquals(expected, execute("git blame file"));
 	}
 }
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java
index f85d8d4..1a4c111 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java
@@ -133,6 +133,9 @@ void ignoreAllSpace(@SuppressWarnings("unused") boolean on) {
 
 	private BlameResult blame;
 
+	/** Used to get a current time stamp for lines without commit. */
+	private final PersonIdent dummyDate = new PersonIdent("", ""); //$NON-NLS-1$ //$NON-NLS-2$
+
 	/** {@inheritDoc} */
 	@Override
 	protected void run() {
@@ -214,6 +217,10 @@ protected void run() {
 					authorWidth = Math.max(authorWidth, author(line).length());
 					dateWidth = Math.max(dateWidth, date(line).length());
 					pathWidth = Math.max(pathWidth, path(line).length());
+				} else if (c == null) {
+					authorWidth = Math.max(authorWidth, author(line).length());
+					dateWidth = Math.max(dateWidth, date(line).length());
+					pathWidth = Math.max(pathWidth, path(line).length());
 				}
 				while (line + 1 < end
 						&& sameCommit(blame.getSourceCommit(line + 1), c)) {
@@ -351,10 +358,12 @@ private String author(int line) {
 	}
 
 	private String date(int line) {
-		if (blame.getSourceCommit(line) == null)
-			return ""; //$NON-NLS-1$
-
-		PersonIdent author = blame.getSourceAuthor(line);
+		PersonIdent author;
+		if (blame.getSourceCommit(line) == null) {
+			author = dummyDate;
+		} else {
+			author = blame.getSourceAuthor(line);
+		}
 		if (author == null)
 			return ""; //$NON-NLS-1$
 
@@ -372,28 +381,37 @@ private String abbreviate(ObjectReader reader, RevCommit commit)
 		if (r != null)
 			return r;
 
-		if (showBlankBoundary && commit.getParentCount() == 0)
-			commit = null;
-
 		if (commit == null) {
-			int len = showLongRevision ? OBJECT_ID_STRING_LENGTH : (abbrev + 1);
-			StringBuilder b = new StringBuilder(len);
-			for (int i = 0; i < len; i++)
-				b.append(' ');
-			r = b.toString();
-
-		} else if (!root && commit.getParentCount() == 0) {
-			if (showLongRevision)
-				r = "^" + commit.name().substring(0, OBJECT_ID_STRING_LENGTH - 1); //$NON-NLS-1$
-			else
-				r = "^" + reader.abbreviate(commit, abbrev).name(); //$NON-NLS-1$
+			if (showLongRevision) {
+				r = ObjectId.zeroId().name();
+			} else {
+				r = ObjectId.zeroId().abbreviate(abbrev + 1).name();
+			}
 		} else {
-			if (showLongRevision)
-				r = commit.name();
-			else
-				r = reader.abbreviate(commit, abbrev + 1).name();
-		}
+			if (showBlankBoundary && commit.getParentCount() == 0)
+				commit = null;
 
+			if (commit == null) {
+				int len = showLongRevision ? OBJECT_ID_STRING_LENGTH
+						: (abbrev + 1);
+				StringBuilder b = new StringBuilder(len);
+				for (int i = 0; i < len; i++)
+					b.append(' ');
+				r = b.toString();
+
+			} else if (!root && commit.getParentCount() == 0) {
+				if (showLongRevision)
+					r = "^" + commit.name().substring(0, //$NON-NLS-1$
+							OBJECT_ID_STRING_LENGTH - 1);
+				else
+					r = "^" + reader.abbreviate(commit, abbrev).name(); //$NON-NLS-1$
+			} else {
+				if (showLongRevision)
+					r = commit.name();
+				else
+					r = reader.abbreviate(commit, abbrev + 1).name();
+			}
+		}
 		abbreviatedCommits.put(commit, r);
 		return r;
 	}