Merge "Add navigation links to side-by-side and unified diff screens"
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/Module.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/Module.java
index 65be419..d822faf 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/Module.java
@@ -31,6 +31,7 @@
import com.googlesource.gerrit.plugins.xdocs.formatter.Formatter;
import com.googlesource.gerrit.plugins.xdocs.formatter.MarkdownFormatter;
import com.googlesource.gerrit.plugins.xdocs.formatter.PlainTextFormatter;
+import com.googlesource.gerrit.plugins.xdocs.formatter.ZipFormatter;
import java.util.List;
@@ -57,6 +58,9 @@
bind(Formatter.class)
.annotatedWith(Exports.named(PlainTextFormatter.NAME))
.to(PlainTextFormatter.class);
+ bind(Formatter.class)
+ .annotatedWith(Exports.named(ZipFormatter.NAME))
+ .to(ZipFormatter.class);
DynamicSet.bind(binder(), ProjectWebLink.class)
.to(XDocWebLink.class);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java
index e84e1e4..1f86e69 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java
@@ -17,9 +17,12 @@
import com.googlesource.gerrit.plugins.xdocs.formatter.AsciidoctorFormatter;
import com.googlesource.gerrit.plugins.xdocs.formatter.MarkdownFormatter;
import com.googlesource.gerrit.plugins.xdocs.formatter.PlainTextFormatter;
+import com.googlesource.gerrit.plugins.xdocs.formatter.ZipFormatter;
import org.eclipse.jgit.lib.Config;
+import java.util.Arrays;
+
public class XDocGlobalConfig {
public static final String SECTION_FORMATTER = "formatter";
public static final String KEY_ALLOW_HTML = "allowHtml";
@@ -49,5 +52,7 @@
"text/x-markdown");
cfg.setString(SECTION_FORMATTER, PlainTextFormatter.NAME, KEY_MIME_TYPE,
"text/plain");
+ cfg.setStringList(SECTION_FORMATTER, ZipFormatter.NAME, KEY_EXT,
+ Arrays.asList("jar", "war", "zip"));
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/AsciidoctorFormatter.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/AsciidoctorFormatter.java
index 42c0456..2f9ae4d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/AsciidoctorFormatter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/AsciidoctorFormatter.java
@@ -15,12 +15,9 @@
package com.googlesource.gerrit.plugins.xdocs.formatter;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_ALLOW_HTML;
-import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_CSS_THEME;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_INCLUDE_TOC;
-import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_INHERIT_CSS;
import static java.nio.charset.StandardCharsets.UTF_8;
-import com.google.common.base.MoreObjects;
import com.google.common.io.ByteStreams;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.annotations.PluginData;
@@ -35,17 +32,14 @@
import org.asciidoctor.Options;
import org.asciidoctor.OptionsBuilder;
import org.asciidoctor.SafeMode;
-import org.eclipse.jgit.util.TemporaryBuffer;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
-import java.net.URL;
import java.util.Properties;
@Singleton
@@ -57,7 +51,6 @@
private static final String ERUBY = "erb";
private final File baseDir;
- private final String defaultCss;
private final Properties attributes;
private final FormatterUtil util;
private final Formatters formatters;
@@ -66,7 +59,6 @@
public AsciidoctorFormatter(@PluginData File baseDir,
FormatterUtil formatterUtil, Formatters formatters) throws IOException {
this.baseDir = baseDir;
- this.defaultCss = readCss();
this.attributes = readAttributes();
this.util = formatterUtil;
this.formatters = formatters;
@@ -92,18 +84,7 @@
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteStreams.copy(input, out);
String html = out.toString(UTF_8.name());
- String cssTheme = projectCfg.getString(KEY_CSS_THEME);
- String inheritedCss =
- util.getInheritedCss(projectName, NAME, "asciidoctor", cssTheme);
- String projectCss = util.getCss(projectName, "asciidoctor", cssTheme);
- if (projectCfg.getBoolean(KEY_INHERIT_CSS, true)) {
- return util.insertCss(html,
- MoreObjects.firstNonNull(inheritedCss, defaultCss), projectCss);
- } else {
- return util.insertCss(html,
- MoreObjects.firstNonNull(projectCss,
- MoreObjects.firstNonNull(inheritedCss, defaultCss)));
- }
+ return util.applyCss(html, NAME, projectName);
}
} finally {
if (!tmpFile.delete()) {
@@ -154,19 +135,6 @@
return ab.get();
}
- private static String readCss() throws IOException {
- String name = "asciidoctor.css";
- URL url = AsciidoctorFormatter.class.getResource(name);
- if (url == null) {
- throw new FileNotFoundException("Resource " + name);
- }
- try (InputStream in = url.openStream();
- TemporaryBuffer.Heap tmp = new TemporaryBuffer.Heap(128 * 1024)) {
- tmp.copy(in);
- return new String(tmp.toByteArray(), UTF_8);
- }
- }
-
private static Properties readAttributes() throws IOException {
Properties attributes = new Properties();
try (InputStream in = AsciidoctorFormatter.class
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/FormatterUtil.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/FormatterUtil.java
index 2c49704..5d62a7e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/FormatterUtil.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/FormatterUtil.java
@@ -14,11 +14,13 @@
package com.googlesource.gerrit.plugins.xdocs.formatter;
+import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_CSS_THEME;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_INHERIT_CSS;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;
import com.google.common.base.Joiner;
+import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.gerrit.extensions.annotations.PluginData;
import com.google.gerrit.extensions.annotations.PluginName;
@@ -40,20 +42,31 @@
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.util.TemporaryBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
@Singleton
public class FormatterUtil {
+ private static final Logger log = LoggerFactory.getLogger(FormatterUtil.class);
+
private final String pluginName;
private final File baseDir;
private final GitRepositoryManager repoManager;
private final ProjectCache projectCache;
private final Formatters formatters;
+ private final Map<String, String> defaultCss;
@Inject
FormatterUtil(@PluginName String pluginName,
@@ -66,6 +79,7 @@
this.repoManager = repoManager;
this.projectCache = projectCache;
this.formatters = formatters;
+ this.defaultCss = new HashMap<>();
}
/**
@@ -191,6 +205,47 @@
return null;
}
+ public String applyCss(String html, String formatterName, String projectName)
+ throws IOException {
+ ConfigSection projectCfg =
+ formatters.getFormatterConfig(formatterName, projectName);
+ String cssName = formatterName.toLowerCase(Locale.US);
+ String cssTheme = projectCfg.getString(KEY_CSS_THEME);
+ String defaultCss = getDefaultCss(formatterName);
+ String inheritedCss =
+ getInheritedCss(projectName, formatterName, cssName, cssTheme);
+ String projectCss = getCss(projectName, cssName, cssTheme);
+ if (projectCfg.getBoolean(KEY_INHERIT_CSS, true)) {
+ return insertCss(html,
+ MoreObjects.firstNonNull(inheritedCss, defaultCss), projectCss);
+ } else {
+ return insertCss(html,
+ MoreObjects.firstNonNull(projectCss,
+ MoreObjects.firstNonNull(inheritedCss, defaultCss)));
+ }
+ }
+
+ private String getDefaultCss(String formatterName) throws IOException {
+ String css = defaultCss.get(formatterName) ;
+ if (css == null) {
+ URL url = FormatterUtil.class.getResource(
+ formatterName.toLowerCase(Locale.US) + ".css");
+ if (url != null) {
+ try (InputStream in = url.openStream();
+ TemporaryBuffer.Heap tmp = new TemporaryBuffer.Heap(128 * 1024)) {
+ tmp.copy(in);
+ css = new String(tmp.toByteArray(), UTF_8);
+ }
+ } else {
+ log.info(String.format("No default CSS for formatter '%s' found.",
+ formatterName));
+ css = "";
+ }
+ defaultCss.put(formatterName, css);
+ }
+ return css;
+ }
+
/**
* Inserts the given CSS into the given HTML.
*
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/HtmlBuilder.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/HtmlBuilder.java
new file mode 100644
index 0000000..c971df5
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/HtmlBuilder.java
@@ -0,0 +1,121 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.googlesource.gerrit.plugins.xdocs.formatter;
+
+import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;
+
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.inject.Inject;
+
+import org.eclipse.jgit.lib.PersonIdent;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+public class HtmlBuilder {
+ private final DateFormat rfc2822DateFormatter;
+ private final StringBuilder html = new StringBuilder();
+
+ @Inject
+ HtmlBuilder(@GerritPersonIdent PersonIdent gerritIdent) {
+ rfc2822DateFormatter =
+ new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
+ rfc2822DateFormatter.setCalendar(Calendar.getInstance(
+ gerritIdent.getTimeZone(), Locale.US));
+ }
+
+ public HtmlBuilder startDocument() {
+ return open("html");
+ }
+
+ public HtmlBuilder endDocument() {
+ return close("html");
+ }
+
+ public HtmlBuilder openBody() {
+ return open("body");
+ }
+
+ public HtmlBuilder closeBody() {
+ return close("body");
+ }
+
+ public HtmlBuilder openHead() {
+ return open("head");
+ }
+
+ public HtmlBuilder closeHead() {
+ return close("head");
+ }
+
+ public HtmlBuilder openTable() {
+ return open("table");
+ }
+
+ public HtmlBuilder closeTable() {
+ return close("table");
+ }
+
+ public HtmlBuilder openRow() {
+ return open("tr");
+ }
+
+ public HtmlBuilder closeRow() {
+ return close("tr");
+ }
+
+ public HtmlBuilder appendCellHeader(String s) {
+ return open("th").append(s).close("th");
+ }
+
+ public HtmlBuilder appendCell(String s) {
+ return open("td").append(s).close("td");
+ }
+
+ public HtmlBuilder appendCell() {
+ return appendCell("");
+ }
+
+ public HtmlBuilder appendDateCell(long date) {
+ return open("td").appendDate(date).close("td");
+ }
+
+ public HtmlBuilder open(String tag) {
+ html.append("<").append(tag).append(">");
+ return this;
+ }
+
+ public HtmlBuilder close(String tag) {
+ html.append("</").append(tag).append(">");
+ return this;
+ }
+
+ public HtmlBuilder append(String s) {
+ html.append(escapeHtml(s));
+ return this;
+ }
+
+ public HtmlBuilder appendDate(long date) {
+ html.append(rfc2822DateFormatter.format(new Date(date)));
+ return this;
+ }
+
+ public String toString() {
+ return html.toString();
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/ZipFormatter.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/ZipFormatter.java
new file mode 100644
index 0000000..fcb9bd8
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/ZipFormatter.java
@@ -0,0 +1,77 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// 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.googlesource.gerrit.plugins.xdocs.formatter;
+
+import com.google.inject.Inject;
+
+import com.googlesource.gerrit.plugins.xdocs.ConfigSection;
+
+import org.apache.commons.io.FileUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public class ZipFormatter implements StreamFormatter {
+ public static final String NAME = "ZIP";
+
+ private final FormatterUtil util;
+ private final HtmlBuilder html;
+
+ @Inject
+ ZipFormatter(
+ Formatters formatters,
+ FormatterUtil formatterUtil,
+ HtmlBuilder html) {
+ this.util = formatterUtil;
+ this.html = html;
+ }
+
+ @Override
+ public String format(String projectName, String revision, ConfigSection globalCfg,
+ InputStream raw) throws IOException {
+ html.startDocument()
+ .openHead()
+ .closeHead()
+ .openBody()
+ .openTable()
+ .appendCellHeader("name")
+ .appendCellHeader("size")
+ .appendCellHeader("last modified");
+ try (ZipInputStream zip = new ZipInputStream(raw)) {
+ for (ZipEntry entry; (entry = zip.getNextEntry()) != null;) {
+ html.openRow()
+ .appendCell(entry.getName());
+ if (!entry.isDirectory()) {
+ if (entry.getSize() != -1) {
+ html.appendCell(FileUtils.byteCountToDisplaySize(entry.getSize()));
+ } else {
+ html.appendCell("n/a");
+ }
+ } else {
+ html.appendCell();
+ }
+ html.appendDateCell(entry.getTime())
+ .closeRow();
+ }
+ }
+ html.closeTable()
+ .closeBody()
+ .endDocument();
+
+ return util.applyCss(html.toString(), NAME, projectName);
+ }
+}
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index f7b2632..7477b6e 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -82,6 +82,13 @@
<td><a href="../../../Documentation/licenses.html#Apache2_0">Apache2.0</a></td>
<td><a href="http://commons.apache.org">http://commons.apache.org</a></td>
</tr>
+ <tr>
+ <td><tt>ZipFormatter</tt></td>
+ <td><tt>ZIP</tt></td>
+ <td>Formatter for zip files.</td>
+ <td></td>
+ <td></td>
+ </tr>
</table>
<a id="htmlDiff">
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 26d773e..2b12b55 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -96,7 +96,7 @@
Overrides the [global configuration of `inheritCss`](#formatterInheritCss)
for this formatter.
- Supported for the following formatters: `ASCIIDOCTOR`, `MARKDOWN`
+ Supported for the following formatters: `ASCIIDOCTOR`, `MARKDOWN`, `ZIP`
Default: `true` (CSS is inherited)
@@ -111,7 +111,7 @@
Overrides the [global configuration of `cssTheme`](#formatterCssTheme)
for this formatter.
- Supported for the following formatters: `ASCIIDOCTOR`, `MARKDOWN`
+ Supported for the following formatters: `ASCIIDOCTOR`, `MARKDOWN`, `ZIP`
By default not set.
@@ -137,6 +137,7 @@
* `ASCIIDOCTOR`: `@PLUGIN@/asciidoctor.css`
* `MARKDOWN`: `@PLUGIN@/markdown.css`
+* `ZIP`: `@PLUGIN@/zip.css`
If link:inheritCss[inheritCss] is set to true custom CSS files are
inherited from parent projects.
@@ -158,6 +159,10 @@
mimeType = text/x-markdown
[formatter "PLAIN_TEXT"]
mimeType = text/plain
+ [formatter "ZIP"]
+ ext = jar
+ ext = war
+ ext = zip
```
Supported formatters:
@@ -165,6 +170,7 @@
* `ASCIIDOCTOR`
* `MARKDOWN`
* `PLAIN_TEXT`
+* `ZIP`
<a id="formatterExt">
formatter.<formatter>.ext
@@ -243,7 +249,7 @@
Can be overridden on [project-level](#inheritCss).
- Supported for the following formatters: `ASCIIDOCTOR`, `MARKDOWN`
+ Supported for the following formatters: `ASCIIDOCTOR`, `MARKDOWN`, `ZIP`
Default: `true` (CSS is inherited)
@@ -256,7 +262,7 @@
Can be overridden on [project-level](#cssTheme).
- Supported for the following formatters: `ASCIIDOCTOR`, `MARKDOWN`
+ Supported for the following formatters: `ASCIIDOCTOR`, `MARKDOWN`, `ZIP`
By default not set.
@@ -295,3 +301,4 @@
* `ASCIIDOCTOR`: `asciidoctor.css`
* `MARKDOWN`: `markdown.css`
+* `ZIP`: `zip.css`