web.datestampShortFormat = yyyy-MM-dd\r
web.datetimestampLongFormat = EEEE, MMMM d, yyyy h:mm a z\r
\r
+# Choose the diff presentation style: gitblt, gitweb, or plain\r
+web.diffStyle = gitblit\r
+\r
# Generates a line graph of repository activity over time on the Summary page.\r
# This is a real-time graph so generation may be expensive. \r
web.generateActivityGraph = true\r
import org.eclipse.jgit.storage.file.FileRepository;\r
\r
import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.JGitUtils.DiffOutputType;\r
import com.gitblit.wicket.models.PathModel.PathChangeModel;\r
import com.gitblit.wicket.models.RefModel;\r
import com.gitblit.wicket.models.TicketModel;\r
public void testCommitDiff() throws Exception {\r
Repository r = getRepository();\r
RevCommit commit = JGitUtils.getCommit(r, Constants.HEAD);\r
- String diff = JGitUtils.getCommitDiff(r, commit, false);\r
+ String diff = JGitUtils.getCommitDiff(r, commit, DiffOutputType.PLAIN);\r
r.close();\r
System.out.println(diff);\r
}\r
--- /dev/null
+package com.gitblit.utils;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+\r
+import org.eclipse.jgit.diff.RawText;\r
+\r
+public class GitBlitDiffFormatter extends GitWebDiffFormatter {\r
+\r
+ private final OutputStream os;\r
+\r
+ private int left = 0, right = 0;\r
+\r
+ public GitBlitDiffFormatter(OutputStream os) {\r
+ super(os);\r
+ this.os = os;\r
+ }\r
+\r
+ /**\r
+ * Output a hunk header\r
+ * \r
+ * @param aStartLine\r
+ * within first source\r
+ * @param aEndLine\r
+ * within first source\r
+ * @param bStartLine\r
+ * within second source\r
+ * @param bEndLine\r
+ * within second source\r
+ * @throws IOException\r
+ */\r
+ @Override\r
+ protected void writeHunkHeader(int aStartLine, int aEndLine, int bStartLine, int bEndLine) throws IOException {\r
+ os.write("<tr><th>..</th><th>..</th><td class='hunk_header'>".getBytes());\r
+ os.write('@');\r
+ os.write('@');\r
+ writeRange('-', aStartLine + 1, aEndLine - aStartLine);\r
+ writeRange('+', bStartLine + 1, bEndLine - bStartLine);\r
+ os.write(' ');\r
+ os.write('@');\r
+ os.write('@');\r
+ os.write("</td></tr>\n".getBytes());\r
+ left = aStartLine + 1;\r
+ right = bStartLine + 1;\r
+ }\r
+\r
+ @Override\r
+ protected void writeLine(final char prefix, final RawText text, final int cur) throws IOException {\r
+ os.write("<tr>".getBytes());\r
+ switch (prefix) {\r
+ case '+':\r
+ os.write(("<th></th><th>" + (right++) + "</th>").getBytes());\r
+ os.write("<td><div class=\"diff add2\">".getBytes());\r
+ break;\r
+ case '-':\r
+ os.write(("<th>" + (left++) + "</th><th></th>").getBytes());\r
+ os.write("<td><div class=\"diff remove2\">".getBytes());\r
+ break;\r
+ default:\r
+ os.write(("<th>" + (left++) + "</th><th>" + (right++) + "</th>").getBytes());\r
+ os.write("<td>".getBytes());\r
+ break;\r
+ }\r
+ os.write(prefix);\r
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
+ text.writeLine(bos, cur);\r
+ String line = bos.toString();\r
+ line = StringUtils.escapeForHtml(line, false);\r
+ os.write(line.getBytes());\r
+ switch (prefix) {\r
+ case '+':\r
+ case '-':\r
+ os.write("</div>".getBytes());\r
+ break;\r
+ default:\r
+ os.write("</td>".getBytes());\r
+ }\r
+ os.write("</tr>\n".getBytes());\r
+ }\r
+\r
+ /**\r
+ * Workaround function for complex private methods in DiffFormatter. This\r
+ * sets the html for the diff headers.\r
+ * \r
+ * @return\r
+ */\r
+ @Override\r
+ public String getHtml() {\r
+ String html = os.toString();\r
+ String[] lines = html.split("\n");\r
+ StringBuilder sb = new StringBuilder(); \r
+ boolean inFile = false;\r
+ String oldnull = "a/dev/null";\r
+ for (String line : lines) {\r
+ if (line.startsWith("index")) {\r
+ // skip index lines\r
+ } else if (line.startsWith("new file")) {\r
+ // skip new file lines\r
+ } else if (line.startsWith("diff")) {\r
+ if (line.indexOf(oldnull) > -1) {\r
+ // a is null, use b\r
+ line = line.substring(("diff --git " + oldnull).length()).trim();\r
+ line = line.substring(2); // trim b/\r
+ } else {\r
+ // use a\r
+ line = line.substring("diff --git a/".length()).trim();\r
+ line = line.substring(0, line.indexOf(" b/")).trim();\r
+ }\r
+ if (inFile) {\r
+ sb.append("</tbody></table></div>\n");\r
+ inFile = false;\r
+ }\r
+ sb.append("<div class='header'>").append(line).append("</div>");\r
+ sb.append("<div class=\"diff\">"); \r
+ sb.append("<table><tbody>");\r
+ inFile = true;\r
+ } else if (line.startsWith("---") || line.startsWith("+++")) {\r
+ // skip --- +++ lines\r
+ } else {\r
+ sb.append(line).append('\n');\r
+ }\r
+ }\r
+ sb.append("</table></div>");\r
+ return sb.toString();\r
+ }\r
+}\r
--- /dev/null
+package com.gitblit.utils;\r
+\r
+import static org.eclipse.jgit.lib.Constants.encodeASCII;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+\r
+import org.eclipse.jgit.diff.DiffFormatter;\r
+import org.eclipse.jgit.diff.RawText;\r
+\r
+public class GitWebDiffFormatter extends DiffFormatter {\r
+\r
+ private final OutputStream os;\r
+\r
+ public GitWebDiffFormatter(OutputStream os) {\r
+ super(os);\r
+ this.os = os;\r
+ }\r
+\r
+ /**\r
+ * Output a hunk header\r
+ * \r
+ * @param aStartLine\r
+ * within first source\r
+ * @param aEndLine\r
+ * within first source\r
+ * @param bStartLine\r
+ * within second source\r
+ * @param bEndLine\r
+ * within second source\r
+ * @throws IOException\r
+ */\r
+ @Override\r
+ protected void writeHunkHeader(int aStartLine, int aEndLine, int bStartLine, int bEndLine) throws IOException {\r
+ os.write("<div class=\"diff hunk_header\"><span class=\"diff hunk_info\">".getBytes());\r
+ os.write('@');\r
+ os.write('@');\r
+ writeRange('-', aStartLine + 1, aEndLine - aStartLine);\r
+ writeRange('+', bStartLine + 1, bEndLine - bStartLine);\r
+ os.write(' ');\r
+ os.write('@');\r
+ os.write('@');\r
+ os.write("</span></div>".getBytes());\r
+ }\r
+\r
+ protected void writeRange(final char prefix, final int begin, final int cnt) throws IOException {\r
+ os.write(' ');\r
+ os.write(prefix);\r
+ switch (cnt) {\r
+ case 0:\r
+ // If the range is empty, its beginning number must\r
+ // be the\r
+ // line just before the range, or 0 if the range is\r
+ // at the\r
+ // start of the file stream. Here, begin is always 1\r
+ // based,\r
+ // so an empty file would produce "0,0".\r
+ //\r
+ os.write(encodeASCII(begin - 1));\r
+ os.write(',');\r
+ os.write('0');\r
+ break;\r
+\r
+ case 1:\r
+ // If the range is exactly one line, produce only\r
+ // the number.\r
+ //\r
+ os.write(encodeASCII(begin));\r
+ break;\r
+\r
+ default:\r
+ os.write(encodeASCII(begin));\r
+ os.write(',');\r
+ os.write(encodeASCII(cnt));\r
+ break;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ protected void writeLine(final char prefix, final RawText text, final int cur) throws IOException {\r
+ switch (prefix) {\r
+ case '+':\r
+ os.write("<span class=\"diff add\">".getBytes());\r
+ break;\r
+ case '-':\r
+ os.write("<span class=\"diff remove\">".getBytes());\r
+ break;\r
+ }\r
+ os.write(prefix);\r
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
+ text.writeLine(bos, cur);\r
+ String line = bos.toString();\r
+ line = StringUtils.escapeForHtml(line, false);\r
+ os.write(line.getBytes());\r
+ switch (prefix) {\r
+ case '+':\r
+ case '-':\r
+ os.write("</span>\n".getBytes());\r
+ break;\r
+ default:\r
+ os.write('\n');\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Workaround function for complex private methods in DiffFormatter. This\r
+ * sets the html for the diff headers.\r
+ * \r
+ * @return\r
+ */\r
+ public String getHtml() {\r
+ String html = os.toString();\r
+ String[] lines = html.split("\n");\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append("<div class=\"diff\">");\r
+ for (String line : lines) {\r
+ if (line.startsWith("diff")) {\r
+ sb.append("<div class=\"diff header\">").append(line).append("</div>");\r
+ } else if (line.startsWith("---")) {\r
+ sb.append("<span class=\"diff remove\">").append(line).append("</span><br/>");\r
+ } else if (line.startsWith("+++")) {\r
+ sb.append("<span class=\"diff add\">").append(line).append("</span><br/>");\r
+ } else {\r
+ sb.append(line).append('\n');\r
+ }\r
+ }\r
+ sb.append("</div>\n");\r
+ return sb.toString();\r
+ }\r
+}\r
+++ /dev/null
-package com.gitblit.utils;\r
-\r
-import static org.eclipse.jgit.lib.Constants.encodeASCII;\r
-\r
-import java.io.ByteArrayOutputStream;\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-\r
-import org.eclipse.jgit.diff.DiffFormatter;\r
-import org.eclipse.jgit.diff.RawText;\r
-\r
-public class HtmlDiffFormatter extends DiffFormatter {\r
-\r
- private final OutputStream os;\r
-\r
- public HtmlDiffFormatter(OutputStream os) {\r
- super(os);\r
- this.os = os;\r
- }\r
-\r
- /**\r
- * Output a hunk header\r
- * \r
- * @param aStartLine\r
- * within first source\r
- * @param aEndLine\r
- * within first source\r
- * @param bStartLine\r
- * within second source\r
- * @param bEndLine\r
- * within second source\r
- * @throws IOException\r
- */\r
- @Override\r
- protected void writeHunkHeader(int aStartLine, int aEndLine, int bStartLine, int bEndLine) throws IOException {\r
- os.write("<div class=\"diff hunk_header\"><span class=\"diff hunk_info\">".getBytes());\r
- os.write('@');\r
- os.write('@');\r
- writeRange('-', aStartLine + 1, aEndLine - aStartLine);\r
- writeRange('+', bStartLine + 1, bEndLine - bStartLine);\r
- os.write(' ');\r
- os.write('@');\r
- os.write('@');\r
- os.write("</span></div>".getBytes());\r
- }\r
-\r
- private void writeRange(final char prefix, final int begin, final int cnt) throws IOException {\r
- os.write(' ');\r
- os.write(prefix);\r
- switch (cnt) {\r
- case 0:\r
- // If the range is empty, its beginning number must\r
- // be the\r
- // line just before the range, or 0 if the range is\r
- // at the\r
- // start of the file stream. Here, begin is always 1\r
- // based,\r
- // so an empty file would produce "0,0".\r
- //\r
- os.write(encodeASCII(begin - 1));\r
- os.write(',');\r
- os.write('0');\r
- break;\r
-\r
- case 1:\r
- // If the range is exactly one line, produce only\r
- // the number.\r
- //\r
- os.write(encodeASCII(begin));\r
- break;\r
-\r
- default:\r
- os.write(encodeASCII(begin));\r
- os.write(',');\r
- os.write(encodeASCII(cnt));\r
- break;\r
- }\r
- }\r
-\r
- @Override\r
- protected void writeLine(final char prefix, final RawText text, final int cur) throws IOException {\r
- switch (prefix) {\r
- case '+':\r
- os.write("<span class=\"diff add\">".getBytes());\r
- break;\r
- case '-':\r
- os.write("<span class=\"diff remove\">".getBytes());\r
- break;\r
- }\r
- os.write(prefix);\r
- ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
- text.writeLine(bos, cur);\r
- String line = bos.toString();\r
- line = StringUtils.escapeForHtml(line, false);\r
- os.write(line.getBytes());\r
- switch (prefix) {\r
- case '+':\r
- case '-':\r
- os.write("</span>\n".getBytes());\r
- break;\r
- default:\r
- os.write('\n');\r
- }\r
- }\r
-\r
- /**\r
- * Workaround function for complex private methods in DiffFormatter. This\r
- * sets the html for the diff headers.\r
- * \r
- * @return\r
- */\r
- public String getHtml() {\r
- String html = os.toString();\r
- String[] lines = html.split("\n");\r
- StringBuilder sb = new StringBuilder();\r
- sb.append("<div class=\"diff\">");\r
- for (String line : lines) {\r
- if (line.startsWith("diff")) {\r
- sb.append("<div class=\"diff header\">").append(line).append("</div>");\r
- } else if (line.startsWith("---")) {\r
- sb.append("<span class=\"diff remove\">").append(line).append("</span><br/>");\r
- } else if (line.startsWith("+++")) {\r
- sb.append("<span class=\"diff add\">").append(line).append("</span><br/>");\r
- } else {\r
- sb.append(line).append('\n');\r
- }\r
- }\r
- sb.append("</div>\n");\r
- return sb.toString();\r
- }\r
-}\r
return list;\r
}\r
\r
- public static String getCommitDiff(Repository r, RevCommit commit, boolean outputHtml) {\r
- return getCommitDiff(r, null, commit, null, outputHtml);\r
+ public static enum DiffOutputType {\r
+ PLAIN, GITWEB, GITBLIT;\r
+\r
+ public static DiffOutputType forName(String name) {\r
+ for (DiffOutputType type : values()) {\r
+ if (type.name().equalsIgnoreCase(name)) {\r
+ return type;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public static String getCommitDiff(Repository r, RevCommit commit, DiffOutputType outputType) {\r
+ return getCommitDiff(r, null, commit, null, outputType);\r
}\r
\r
- public static String getCommitDiff(Repository r, RevCommit commit, String path, boolean outputHtml) {\r
- return getCommitDiff(r, null, commit, path, outputHtml);\r
+ public static String getCommitDiff(Repository r, RevCommit commit, String path, DiffOutputType outputType) {\r
+ return getCommitDiff(r, null, commit, path, outputType);\r
}\r
\r
- public static String getCommitDiff(Repository r, RevCommit baseCommit, RevCommit commit, boolean outputHtml) {\r
- return getCommitDiff(r, baseCommit, commit, null, outputHtml);\r
+ public static String getCommitDiff(Repository r, RevCommit baseCommit, RevCommit commit, DiffOutputType outputType) {\r
+ return getCommitDiff(r, baseCommit, commit, null, outputType);\r
}\r
\r
- public static String getCommitDiff(Repository r, RevCommit baseCommit, RevCommit commit, String path, boolean outputHtml) {\r
+ public static String getCommitDiff(Repository r, RevCommit baseCommit, RevCommit commit, String path, DiffOutputType outputType) {\r
try {\r
RevTree baseTree;\r
if (baseCommit == null) {\r
final ByteArrayOutputStream os = new ByteArrayOutputStream();\r
RawTextComparator cmp = RawTextComparator.DEFAULT;\r
DiffFormatter df;\r
- if (outputHtml) {\r
- df = new HtmlDiffFormatter(os);\r
- } else {\r
+ switch (outputType) {\r
+ case GITWEB:\r
+ df = new GitWebDiffFormatter(os);\r
+ break;\r
+ case GITBLIT:\r
+ df = new GitBlitDiffFormatter(os);\r
+ break;\r
+ case PLAIN:\r
+ default:\r
df = new DiffFormatter(os);\r
+ break;\r
}\r
df.setRepository(r);\r
df.setDiffComparator(cmp);\r
df.format(diffs);\r
}\r
String diff;\r
- if (outputHtml) {\r
+ if (df instanceof GitWebDiffFormatter) {\r
// workaround for complex private methods in DiffFormatter\r
- diff = ((HtmlDiffFormatter) df).getHtml();\r
+ diff = ((GitWebDiffFormatter) df).getHtml();\r
} else {\r
diff = os.toString();\r
}\r
df = new SimpleDateFormat("yyyy-MM");\r
}\r
walk.markStart(lastCommit);\r
- \r
+\r
Iterable<RevCommit> revlog = walk;\r
for (RevCommit rev : revlog) {\r
Date d = getCommitDate(rev);\r
String p = df.format(d);\r
if (!metricMap.containsKey(p))\r
metricMap.put(p, new Metric(p));\r
- Metric m = metricMap.get(p); \r
+ Metric m = metricMap.get(p);\r
m.count++;\r
total.count++;\r
if (tagMap.containsKey(rev.getId())) {\r
m.tag++;\r
total.tag++;\r
}\r
- } \r
+ }\r
} catch (Throwable t) {\r
LOGGER.error("Failed to mine log history for metrics", t);\r
}\r
import org.eclipse.jgit.lib.Repository;\r
import org.eclipse.jgit.revwalk.RevCommit;\r
\r
+import com.gitblit.GitBlit;\r
+import com.gitblit.Keys;\r
import com.gitblit.utils.JGitUtils;\r
import com.gitblit.utils.StringUtils;\r
+import com.gitblit.utils.JGitUtils.DiffOutputType;\r
import com.gitblit.wicket.LinkPanel;\r
import com.gitblit.wicket.RepositoryPage;\r
import com.gitblit.wicket.WicketUtils;\r
Repository r = getRepository();\r
RevCommit commit = JGitUtils.getCommit(r, objectId);\r
\r
+ DiffOutputType diffType = DiffOutputType.forName(GitBlit.self().settings().getString(Keys.web.diffStyle, DiffOutputType.GITBLIT.name()));\r
+\r
String diff;\r
if (StringUtils.isEmpty(baseObjectId)) {\r
// use first parent\r
- diff = JGitUtils.getCommitDiff(r, commit, blobPath, true);\r
+ diff = JGitUtils.getCommitDiff(r, commit, blobPath, diffType);\r
add(new BookmarkablePageLink<Void>("patchLink", PatchPage.class, WicketUtils.newPathParameter(repositoryName, objectId, blobPath)));\r
} else {\r
// base commit specified\r
RevCommit baseCommit = JGitUtils.getCommit(r, baseObjectId);\r
- diff = JGitUtils.getCommitDiff(r, baseCommit, commit, blobPath, true);\r
+ diff = JGitUtils.getCommitDiff(r, baseCommit, commit, blobPath, diffType);\r
add(new BookmarkablePageLink<Void>("patchLink", PatchPage.class, WicketUtils.newBlobDiffParameter(repositoryName, baseObjectId, objectId, blobPath)));\r
}\r
\r
import org.eclipse.jgit.lib.Repository;\r
import org.eclipse.jgit.revwalk.RevCommit;\r
\r
+import com.gitblit.GitBlit;\r
+import com.gitblit.Keys;\r
import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.JGitUtils.DiffOutputType;\r
import com.gitblit.wicket.LinkPanel;\r
import com.gitblit.wicket.RepositoryPage;\r
import com.gitblit.wicket.WicketUtils;\r
\r
Repository r = getRepository();\r
RevCommit commit = JGitUtils.getCommit(r, objectId);\r
- String diff = JGitUtils.getCommitDiff(r, commit, true);\r
+ DiffOutputType diffType = DiffOutputType.forName(GitBlit.self().settings().getString(Keys.web.diffStyle, DiffOutputType.GITBLIT.name()));\r
+ String diff = JGitUtils.getCommitDiff(r, commit, diffType);\r
\r
List<String> parents = new ArrayList<String>();\r
if (commit.getParentCount() > 0) {\r
\r
div.diff {\r
font-family: monospace;\r
+ overflow: auto;\r
}\r
\r
div.diff.header {\r
font-family: inherit;\r
}\r
\r
+div.diff.add2 {\r
+ background-color: #DDFFDD;\r
+ font-family: inherit;\r
+}\r
+\r
+div.diff.remove2 {\r
+ background-color: #FFDDDD;\r
+ font-family: inherit;\r
+}\r
+\r
+div.diff table {\r
+ border-right: 1px solid #bbb;\r
+ border-bottom: 1px solid #bbb;\r
+ width: 100%;\r
+}\r
+\r
+div.diff table th, div.diff table td {\r
+ margin: 0px;\r
+ padding: 0px;\r
+ font-family: monospace; \r
+}\r
+\r
+div.diff table th {\r
+ background-color: #faf8dc;\r
+ border-left: 1px solid #bbb; \r
+ text-align: center;\r
+ color: #999;\r
+ padding-left: 5px;\r
+ padding-right: 5px;\r
+}\r
+\r
+div.diff table th.header {\r
+ background-color: #D2C3AF;\r
+ border-right: 0px;\r
+ border-bottom: 1px solid #808080;\r
+ font-family: inherit;\r
+ font-size:0.9em;\r
+ color: black;\r
+ padding: 2px;\r
+ text-align: left;\r
+}\r
+\r
+div.diff table td.hunk_header {\r
+ background-color: #dAe2e5 !important; \r
+ border-bottom: 1px solid #bac2c5;\r
+ color: #555;\r
+}\r
+\r
+div.diff table td {\r
+ border-left: 1px solid #bbb;\r
+ background-color: #fbfbfb;\r
+}\r
+\r
span.addition, span.modification, span.deletion, span.rename {\r
border: 1px solid #888;\r
float: left;\r