Make mime types and file extentions configurable per project
Some mime types and file extensions can be handled by multiple
formatters, e.g. there can be two different formatters for Markdown.
By allowing projects to configure mime types and file extensions for
formatters each project can decide which formatter should be used.
E.g. if globally the following Markdown formatter is configured
[formatter "MARKDOWN"]
mime-type = text/x-markdown
a project may overwrite this by having the following configuration in
a 'xdocs.config' file in its refs/meta/config branch:
[formatter "FANCY_MARKDOWN"]
mime-type = text/x-markdown
[formatter "MARKDOWN"]
Formatter configurations are inherited from parent projects.
Being able to configure file extensions on project level is also
useful if projects use different file extensions for one format. E.g.
some projects my use *.adoc files for asciidoc documentation and other
projects may use *.txt for asciidoc documentation.
Change-Id: I5b095ab4c697d8367f3ddd421312fd59ca6a4051
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
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 1bb0e2b..57eb74b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocGlobalConfig.java
@@ -21,8 +21,7 @@
import org.eclipse.jgit.lib.Config;
public class XDocGlobalConfig {
- private static final String SECTION_FORMATTER = "formatter";
-
+ public static final String SECTION_FORMATTER = "formatter";
public static final String KEY_ALLOW_HTML = "allowHtml";
public static final String KEY_EXT = "ext";
public static final String KEY_MIME_TYPE = "mimeType";
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java
index 786a646..70eb763 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocServlet.java
@@ -126,7 +126,7 @@
return;
}
MimeType mimeType = fileTypeRegistry.getMimeType(key.file, null);
- FormatterProvider formatter = formatters.get(key.file);
+ FormatterProvider formatter = formatters.get(state, key.file);
if (formatter == null
&& !("image".equals(mimeType.getMediaType())
&& fileTypeRegistry.isSafeInline(mimeType))) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java
index e0b7a60..b11afe8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/XDocWebLink.java
@@ -90,7 +90,7 @@
public String getPatchUrl(String projectName, String revision,
String fileName) {
- FormatterProvider formatter = formatters.get(fileName);
+ FormatterProvider formatter = formatters.get(projectName, fileName);
if (formatter == null) {
return null;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatters.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatters.java
index 64e9fc1..8d046ce 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatters.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/formatter/Formatters.java
@@ -16,17 +16,23 @@
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_EXT;
import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.KEY_MIME_TYPE;
+import static com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig.SECTION_FORMATTER;
import org.apache.commons.io.FilenameUtils;
+import org.eclipse.jgit.lib.Config;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.registration.DynamicMap;
+import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.FileTypeRegistry;
import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.xdocs.ConfigSection;
import com.googlesource.gerrit.plugins.xdocs.XDocGlobalConfig;
import eu.medsea.mimeutil.MimeType;
@@ -39,35 +45,45 @@
private final PluginConfigFactory pluginCfgFactory;
private final FileTypeRegistry fileTypeRegistry;
private final DynamicMap<Formatter> formatters;
+ private final ProjectCache projectCache;
@Inject
Formatters(
@PluginName String pluginName,
PluginConfigFactory pluginCfgFactory,
FileTypeRegistry fileTypeRegistry,
- DynamicMap<Formatter> formatters) {
+ DynamicMap<Formatter> formatters,
+ ProjectCache projectCache) {
this.pluginName = pluginName;
this.pluginCfgFactory = pluginCfgFactory;
this.fileTypeRegistry = fileTypeRegistry;
this.formatters = formatters;
+ this.projectCache = projectCache;
}
- public FormatterProvider get(String fileName) {
- XDocGlobalConfig pluginCfg =
- new XDocGlobalConfig(pluginCfgFactory.getGlobalPluginConfig(pluginName));
+ public FormatterProvider get(String projectName, String fileName) {
+ ProjectState project = projectCache.get(new Project.NameKey(projectName));
+ if (project == null) {
+ return null;
+ }
+ return get(project, fileName);
+ }
+
+ public FormatterProvider get(ProjectState project, String fileName) {
MimeType mimeType = fileTypeRegistry.getMimeType(fileName, null);
String extension = FilenameUtils.getExtension(fileName);
for (String pluginName : formatters.plugins()) {
for (Entry<String, Provider<Formatter>> e :
formatters.byPlugin(pluginName).entrySet()) {
+ ConfigSection formatterCfg = getFormatterConfig(e.getKey(), project);
for (String configuredMimeType :
- pluginCfg.getFormatterConfig(e.getKey()).getStringList(KEY_MIME_TYPE)) {
+ formatterCfg.getStringList(KEY_MIME_TYPE)) {
if (mimeType.equals(new MimeType(configuredMimeType))) {
return new FormatterProvider(e.getKey(), e.getValue());
}
}
for (String ext :
- pluginCfg.getFormatterConfig(e.getKey()).getStringList(KEY_EXT)) {
+ formatterCfg.getStringList(KEY_EXT)) {
if (extension.equals(ext)) {
return new FormatterProvider(e.getKey(), e.getValue());
}
@@ -77,6 +93,20 @@
return null;
}
+ private ConfigSection getFormatterConfig(String formatterName,
+ ProjectState project) {
+ for (ProjectState p : project.tree()) {
+ Config cfg = pluginCfgFactory.getProjectPluginConfig(p, pluginName);
+ if (cfg.getSubsections(SECTION_FORMATTER).contains(formatterName)) {
+ return new XDocGlobalConfig(cfg).getFormatterConfig(formatterName);
+ }
+ }
+
+ return new XDocGlobalConfig(
+ pluginCfgFactory.getGlobalPluginConfig(pluginName))
+ .getFormatterConfig(formatterName);
+ }
+
public FormatterProvider getByName(String formatterName) {
for (String pluginName : formatters.plugins()) {
for (Entry<String, Provider<Formatter>> e :
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index ff50605..86f3891 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -23,6 +23,28 @@
Default: `README.md`
+The global formatter configuration can be overridden per project.
+Configuring any parameter for a formatter overrides the complete
+global formatter configuration.
+
+<a id="ext">
+formatter.<formatter>.ext
+: Extension of files that should be rendered by this formatter.
+
+ Multiple extensions may be specified for a formatter.
+
+ Overrides the [globally configured file extensions](#formatterExt)
+ for this formatter.
+
+<a id="mimeType">
+formatter.<formatter>.mimeType
+: The mime type of files that should be rendered by this formatter.
+
+ Multiple mime types may be specified for a formatter.
+
+ Overrides the [globally configured mime types](#formatterMimeType)
+ for this formatter.
+
<a id="globalConfig">
Global Configuration
--------------------
@@ -48,18 +70,22 @@
* `MARKDOWN`
* `PLAIN_TEXT`
-<a id="ext">
+<a id="formatterExt">
formatter.<formatter>.ext
: Extension of files that will be rendered by this formatter.
Multiple extensions may be specified for a formatter.
+ Can be overridden on [project-level](#ext).
+
<a id="formatterMimeType">
formatter.<formatter>.mimeType
: The mime type of files that will be rendered by this formatter.
Multiple mime types may be specified for a formatter.
+ Can be overridden on [project-level](#mimeType).
+
<a id="formatterAllowHtml">
formatter.<formatter>.allowHtml
: Whether inline HTML blocks and inline HTML tags are allowed for
@@ -75,6 +101,8 @@
**WARNING:** Allowing HTML for user-provided input is a security
risk, e.g. code for XSS attacks may be contained in the HTML.
+ *CANNOT* be overridden on project-level.
+
Supported for the following formatters: `MARKDOWN`
Default: `false`