From f66e89662c091e082bd1d2feb6ac91513ccff273 Mon Sep 17 00:00:00 2001
From: Rafael Cavazin <rafaelcavazin@gmail.com>
Date: Sun, 21 Jul 2013 09:59:00 -0400
Subject: [PATCH] Merge branch 'master' of https://github.com/gitblit/gitblit

---
 src/main/java/com/gitblit/utils/GitBlitDiffFormatter.java |  178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 178 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/gitblit/utils/GitBlitDiffFormatter.java b/src/main/java/com/gitblit/utils/GitBlitDiffFormatter.java
new file mode 100644
index 0000000..62966de
--- /dev/null
+++ b/src/main/java/com/gitblit/utils/GitBlitDiffFormatter.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.utils;
+
+import static org.eclipse.jgit.lib.Constants.encode;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.diff.RawText;
+import org.eclipse.jgit.util.RawParseUtils;
+
+/**
+ * Generates an html snippet of a diff in Gitblit's style.
+ * 
+ * @author James Moger
+ * 
+ */
+public class GitBlitDiffFormatter extends GitWebDiffFormatter {
+
+	private final OutputStream os;
+
+	private int left, right;
+
+	public GitBlitDiffFormatter(OutputStream os) {
+		super(os);
+		this.os = os;
+	}
+
+	/**
+	 * Output a hunk header
+	 * 
+	 * @param aStartLine
+	 *            within first source
+	 * @param aEndLine
+	 *            within first source
+	 * @param bStartLine
+	 *            within second source
+	 * @param bEndLine
+	 *            within second source
+	 * @throws IOException
+	 */
+	@Override
+	protected void writeHunkHeader(int aStartLine, int aEndLine, int bStartLine, int bEndLine)
+			throws IOException {
+		os.write("<tr><th>..</th><th>..</th><td class='hunk_header'>".getBytes());
+		os.write('@');
+		os.write('@');
+		writeRange('-', aStartLine + 1, aEndLine - aStartLine);
+		writeRange('+', bStartLine + 1, bEndLine - bStartLine);
+		os.write(' ');
+		os.write('@');
+		os.write('@');
+		os.write("</td></tr>\n".getBytes());
+		left = aStartLine + 1;
+		right = bStartLine + 1;
+	}
+
+	@Override
+	protected void writeLine(final char prefix, final RawText text, final int cur)
+			throws IOException {
+		os.write("<tr>".getBytes());
+		switch (prefix) {
+		case '+':
+			os.write(("<th></th><th>" + (right++) + "</th>").getBytes());
+			os.write("<td><div class=\"diff add2\">".getBytes());
+			break;
+		case '-':
+			os.write(("<th>" + (left++) + "</th><th></th>").getBytes());
+			os.write("<td><div class=\"diff remove2\">".getBytes());
+			break;
+		default:
+			os.write(("<th>" + (left++) + "</th><th>" + (right++) + "</th>").getBytes());
+			os.write("<td>".getBytes());
+			break;
+		}
+		os.write(prefix);
+		String line = text.getString(cur);
+		line = StringUtils.escapeForHtml(line, false);
+		os.write(encode(line));
+		switch (prefix) {
+		case '+':
+		case '-':
+			os.write("</div>".getBytes());
+			break;
+		default:
+			os.write("</td>".getBytes());
+		}
+		os.write("</tr>\n".getBytes());
+	}
+
+	/**
+	 * Workaround function for complex private methods in DiffFormatter. This
+	 * sets the html for the diff headers.
+	 * 
+	 * @return
+	 */
+	@Override
+	public String getHtml() {
+		ByteArrayOutputStream bos = (ByteArrayOutputStream) os;
+		String html = RawParseUtils.decode(bos.toByteArray());
+		String[] lines = html.split("\n");
+		StringBuilder sb = new StringBuilder();
+		boolean inFile = false;
+		String oldnull = "a/dev/null";
+		for (String line : lines) {
+			if (line.startsWith("index")) {
+				// skip index lines
+			} else if (line.startsWith("new file")) {
+				// skip new file lines
+			} else if (line.startsWith("\\ No newline")) {
+				// skip no new line
+			} else if (line.startsWith("---") || line.startsWith("+++")) {
+				// skip --- +++ lines
+			} else if (line.startsWith("diff")) {
+				line = StringUtils.convertOctal(line);
+				if (line.indexOf(oldnull) > -1) {
+					// a is null, use b
+					line = line.substring(("diff --git " + oldnull).length()).trim();
+					// trim b/
+					line = line.substring(2).trim();
+				} else {
+					// use a
+					line = line.substring("diff --git ".length()).trim();
+					line = line.substring(line.startsWith("\"a/") ? 3 : 2);					
+					line = line.substring(0, line.indexOf(" b/") > -1 ? line.indexOf(" b/") : line.indexOf("\"b/")).trim();
+				}
+				
+				if (line.charAt(0) == '"') {
+					line = line.substring(1);
+				}
+				if (line.charAt(line.length() - 1) == '"') {
+					line = line.substring(0, line.length() - 1);
+				}
+				if (inFile) {
+					sb.append("</tbody></table></div>\n");
+					inFile = false;
+				}
+				
+				sb.append(MessageFormat.format("<div class='header'><div class=\"diffHeader\" id=\"{0}\"><i class=\"icon-file\"></i> ", line)).append(line).append("</div></div>");
+				sb.append("<div class=\"diff\">");
+				sb.append("<table><tbody>");
+				inFile = true;
+			} else {
+				boolean gitLinkDiff = line.length() > 0 && line.substring(1).startsWith("Subproject commit");
+				if (gitLinkDiff) {
+					sb.append("<tr><th></th><th></th>");
+					if (line.charAt(0) == '+') {
+						sb.append("<td><div class=\"diff add2\">");
+					} else {
+						sb.append("<td><div class=\"diff remove2\">");
+					}
+				}
+				sb.append(line);
+				if (gitLinkDiff) {
+					sb.append("</div></td></tr>");
+				}
+			}
+		}
+		sb.append("</table></div>");
+		return sb.toString();
+	}
+}

--
Gitblit v1.9.1