Support inheritable project specific plugin parameters in the UI
The UI now also displays the inherited value.
Change-Id: I2ec034f919f31afc5687f9da6cbbe05f878d98c1
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 48ef56a..9bfbd4d 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -1298,9 +1298,21 @@
The type of the configuration parameter, can be `STRING`, `INT`,
`LONG`, `BOOLEAN` or `LIST`.
|`value` |optional|
-The value of the configuration parameter as string.
+The value of the configuration parameter as string. If the parameter
+is inheritable this is the effective value which is deduced from
+`configured_value` and `inherited_value`.
|`permitted_values`|optional|
The list of permitted values, only set if the `type` is `LIST`.
+|`inheritable` |`false` if not set|
+Whether the configuration parameter can be inherited.
+|`configured_value`|optional|
+The value of the configuration parameter that is configured on this
+project, only set if `inheritable` is true.
+|`inherited_value` |optional|
+The inherited value of the configuration parameter, only set if
+`inheritable` is true.
+|`permitted_values` |optional|
+The list of permitted values, only set if the `type` is `LIST`.
|===============================
[[dashboard-info]]
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
index 7f2c5e4..98b9534 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
@@ -191,6 +191,7 @@
String patchSetRevision();
String patchSetUserIdentity();
String patchSizeCell();
+ String pluginProjectConfigInheritedValue();
String pluginsTable();
String posscore();
String projectActions();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java
index 19ae1f3..05ffa9a 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java
@@ -29,4 +29,6 @@
String effectiveMaxObjectSizeLimit(String effectiveMaxObjectSizeLimit);
String globalMaxObjectSizeLimit(String globalMaxObjectSizeLimit);
String pluginProjectOptionsTitle(String pluginName);
+ String pluginProjectInheritedValue(String value);
+ String pluginProjectInheritedListValue(String value);
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties
index 4c69cf8..6338920 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties
@@ -8,3 +8,6 @@
effectiveMaxObjectSizeLimit = effective: {0}
globalMaxObjectSizeLimit = The global max object size limit is set to {0}. The limit cannot be increased on project level.
pluginProjectOptionsTitle = {0} Plugin Options
+pluginProjectOptionsTitle = {0} Plugin
+pluginProjectInheritedValue = inherited: {0}
+pluginProjectInheritedListValue = INHERIT ({0})
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
index 31f89fb..d836cb5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
@@ -387,8 +387,21 @@
private TextBox renderTextBox(LabeledWidgetsGrid g,
ConfigParameterInfo param, boolean numbersOnly) {
NpTextBox textBox = numbersOnly ? new NpIntTextBox() : new NpTextBox();
- textBox.setValue(param.value());
- g.add(getDisplayName(param), textBox);
+ if (param.inheritable()) {
+ textBox.setValue(param.configuredValue());
+ Label inheritedLabel =
+ new Label(Util.M.pluginProjectInheritedValue(param
+ .inheritedValue()));
+ inheritedLabel.setStyleName(Gerrit.RESOURCES.css()
+ .pluginProjectConfigInheritedValue());
+ HorizontalPanel p = new HorizontalPanel();
+ p.add(textBox);
+ p.add(inheritedLabel);
+ g.add(getDisplayName(param), p);
+ } else {
+ textBox.setValue(param.value());
+ g.add(getDisplayName(param), textBox);
+ }
saveEnabler.listenTo(textBox);
return textBox;
}
@@ -405,13 +418,29 @@
private ListBox renderListBox(LabeledWidgetsGrid g,
ConfigParameterInfo param) {
ListBox listBox = new ListBox();
- for (int i = 0; i < param.permittedValues().length(); i++) {
- String sv = param.permittedValues().get(i);
- listBox.addItem(sv);
- if (sv.equals(param.value())) {
- listBox.setSelectedIndex(i);
+ if (param.inheritable()) {
+ listBox.addItem(
+ Util.M.pluginProjectInheritedListValue(param.inheritedValue()));
+ if (param.configuredValue() == null) {
+ listBox.setSelectedIndex(0);
+ }
+ for (int i = 0; i < param.permittedValues().length(); i++) {
+ String pv = param.permittedValues().get(i);
+ listBox.addItem(pv);
+ if (pv.equals(param.configuredValue())) {
+ listBox.setSelectedIndex(i + 1);
+ }
+ }
+ } else {
+ for (int i = 0; i < param.permittedValues().length(); i++) {
+ String pv = param.permittedValues().get(i);
+ listBox.addItem(pv);
+ if (pv.equals(param.value())) {
+ listBox.setSelectedIndex(i);
+ }
}
}
+
g.add(getDisplayName(param), listBox);
saveEnabler.listenTo(listBox);
return listBox;
@@ -480,7 +509,10 @@
values.put(e2.getKey(), Boolean.toString(((CheckBox) widget).getValue()));
} else if (widget instanceof ListBox) {
ListBox listBox = (ListBox) widget;
- String value = listBox.getValue(listBox.getSelectedIndex());
+ // the inherited value is at index 0,
+ // if it is selected no value should be set on this project
+ String value = listBox.getSelectedIndex() > 0
+ ? listBox.getValue(listBox.getSelectedIndex()) : null;
values.put(e2.getKey(), value);
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
index c0e13e4..77daccf 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -1623,3 +1623,8 @@
padding-top: 5px;
padding-left: 5px;
}
+
+.pluginProjectConfigInheritedValue {
+ padding-top: 5px;
+ padding-left: 5px;
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
index f1bc33b..381c189 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
@@ -151,6 +151,9 @@
public final native String displayName() /*-{ return this.display_name; }-*/;
public final native String type() /*-{ return this.type; }-*/;
public final native String value() /*-{ return this.value; }-*/;
+ public final native boolean inheritable() /*-{ return this.inheritable ? true : false; }-*/;
+ public final native String configuredValue() /*-{ return this.configured_value; }-*/;
+ public final native String inheritedValue() /*-{ return this.inherited_value; }-*/;
public final native JsArrayString permittedValues() /*-{ return this.permitted_values; }-*/;
protected ConfigParameterInfo() {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectConfigEntry.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectConfigEntry.java
index d093833..8076eaa 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectConfigEntry.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectConfigEntry.java
@@ -28,33 +28,61 @@
}
private final String displayName;
+ private final boolean inheritable;
private final String defaultValue;
private final Type type;
private final List<String> permittedValues;
public ProjectConfigEntry(String displayName, String defaultValue) {
- this(displayName, defaultValue, Type.STRING, null);
+ this(displayName, defaultValue, false);
+ }
+
+ public ProjectConfigEntry(String displayName, String defaultValue,
+ boolean inheritable) {
+ this(displayName, defaultValue, Type.STRING, null, inheritable);
}
public ProjectConfigEntry(String displayName, int defaultValue) {
- this(displayName, Integer.toString(defaultValue), Type.INT, null);
+ this(displayName, defaultValue, false);
+ }
+
+ public ProjectConfigEntry(String displayName, int defaultValue,
+ boolean inheritable) {
+ this(displayName, Integer.toString(defaultValue), Type.INT, null,
+ inheritable);
}
public ProjectConfigEntry(String displayName, long defaultValue) {
- this(displayName, Long.toString(defaultValue), Type.LONG, null);
+ this(displayName, defaultValue, false);
}
+ public ProjectConfigEntry(String displayName, long defaultValue,
+ boolean inheritable) {
+ this(displayName, Long.toString(defaultValue), Type.LONG, null, inheritable);
+ }
+
+ // For inheritable boolean use 'LIST' type with InheritableBoolean
public ProjectConfigEntry(String displayName, boolean defaultValue) {
- this(displayName, Boolean.toString(defaultValue), Type.BOOLEAN, null);
+ this(displayName, Boolean.toString(defaultValue), Type.BOOLEAN, null, false);
}
public ProjectConfigEntry(String displayName, String defaultValue,
List<String> permittedValues) {
- this(displayName, defaultValue, Type.LIST, permittedValues);
+ this(displayName, defaultValue, permittedValues, false);
+ }
+
+ public ProjectConfigEntry(String displayName, String defaultValue,
+ List<String> permittedValues, boolean inheritable) {
+ this(displayName, defaultValue, Type.LIST, permittedValues, inheritable);
}
public <T extends Enum<?>> ProjectConfigEntry(String displayName,
T defaultValue, Class<T> permittedValues) {
+ this(displayName, defaultValue, permittedValues, false);
+ }
+
+ public <T extends Enum<?>> ProjectConfigEntry(String displayName,
+ T defaultValue, Class<T> permittedValues, boolean inheritable) {
this(displayName, defaultValue.name(), Type.LIST, Lists.transform(
Arrays.asList(permittedValues.getEnumConstants()),
new Function<Enum<?>, String>() {
@@ -62,21 +90,26 @@
public String apply(Enum<?> e) {
return e.name();
}
- }));
+ }), inheritable);
}
private ProjectConfigEntry(String displayName, String defaultValue,
- Type type, List<String> permittedValues) {
+ Type type, List<String> permittedValues, boolean inheritable) {
this.displayName = displayName;
this.defaultValue = defaultValue;
this.type = type;
this.permittedValues = permittedValues;
+ this.inheritable = inheritable;
}
public String getDisplayName() {
return displayName;
}
+ public boolean isInheritable() {
+ return inheritable;
+ }
+
public String getDefaultValue() {
return defaultValue;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ConfigInfo.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ConfigInfo.java
index 891301b..18e713c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ConfigInfo.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ConfigInfo.java
@@ -25,6 +25,7 @@
import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
import com.google.gerrit.reviewdb.client.Project.SubmitType;
import com.google.gerrit.server.actions.ActionInfo;
+import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
@@ -57,6 +58,7 @@
TransferConfig config,
DynamicMap<ProjectConfigEntry> pluginConfigEntries,
PluginConfigFactory cfgFactory,
+ AllProjectsNameProvider allProjects,
DynamicMap<RestView<ProjectResource>> views) {
ProjectState projectState = control.getProjectState();
Project p = control.getProject();
@@ -113,7 +115,8 @@
}
pluginConfig =
- getPluginConfig(control.getProjectState(), pluginConfigEntries, cfgFactory);
+ getPluginConfig(control.getProjectState(), pluginConfigEntries,
+ cfgFactory, allProjects);
actions = Maps.newTreeMap();
for (UiAction.Description d : UiActions.from(
@@ -126,17 +129,29 @@
private Map<String, Map<String, ConfigParameterInfo>> getPluginConfig(
ProjectState project, DynamicMap<ProjectConfigEntry> pluginConfigEntries,
- PluginConfigFactory cfgFactory) {
+ PluginConfigFactory cfgFactory, AllProjectsNameProvider allProjects) {
TreeMap<String, Map<String, ConfigParameterInfo>> pluginConfig = new TreeMap<>();
for (Entry<ProjectConfigEntry> e : pluginConfigEntries) {
PluginConfig cfg =
cfgFactory.getFromProjectConfig(project, e.getPluginName());
ProjectConfigEntry configEntry = e.getProvider().get();
+ String configuredValue = cfg.getString(e.getExportName());
ConfigParameterInfo p = new ConfigParameterInfo();
p.displayName = configEntry.getDisplayName();
p.type = configEntry.getType();
- p.value = cfg.getString(e.getExportName(), configEntry.getDefaultValue());
p.permittedValues = configEntry.getPermittedValues();
+ if (configEntry.isInheritable()
+ && !allProjects.get().equals(project.getProject().getNameKey())) {
+ PluginConfig cfgWithInheritance =
+ cfgFactory.getFromProjectConfigWithInheritance(project,
+ e.getPluginName());
+ p.inheritable = true;
+ p.value = cfgWithInheritance.getString(e.getExportName(), configEntry.getDefaultValue());
+ p.configuredValue = configuredValue;
+ p.inheritedValue = getInheritedValue(project, cfgFactory, e);
+ } else {
+ p.value = configuredValue != null ? configuredValue : configEntry.getDefaultValue();
+ }
Map<String, ConfigParameterInfo> pc = pluginConfig.get(e.getPluginName());
if (pc == null) {
pc = new TreeMap<>();
@@ -147,6 +162,22 @@
return !pluginConfig.isEmpty() ? pluginConfig : null;
}
+ private String getInheritedValue(ProjectState project,
+ PluginConfigFactory cfgFactory, Entry<ProjectConfigEntry> e) {
+ ProjectConfigEntry configEntry = e.getProvider().get();
+ ProjectState parent = Iterables.getFirst(project.parents(), null);
+ String inheritedValue = configEntry.getDefaultValue();
+ if (parent != null) {
+ PluginConfig parentCfgWithInheritance =
+ cfgFactory.getFromProjectConfigWithInheritance(parent,
+ e.getPluginName());
+ inheritedValue =
+ parentCfgWithInheritance.getString(e.getExportName(),
+ configEntry.getDefaultValue());
+ }
+ return inheritedValue;
+ }
+
public static class InheritedBooleanInfo {
public Boolean value;
public InheritableBoolean configuredValue;
@@ -163,6 +194,9 @@
public String displayName;
public ProjectConfigEntry.Type type;
public String value;
+ public Boolean inheritable;
+ public String configuredValue;
+ public String inheritedValue;
public List<String> permittedValues;
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetConfig.java
index 1ee1d00..88ac83f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetConfig.java
@@ -18,6 +18,7 @@
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.git.TransferConfig;
@@ -29,16 +30,19 @@
private final TransferConfig config;
private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
private final PluginConfigFactory cfgFactory;
+ private final AllProjectsNameProvider allProjects;
private final DynamicMap<RestView<ProjectResource>> views;
@Inject
public GetConfig(TransferConfig config,
DynamicMap<ProjectConfigEntry> pluginConfigEntries,
PluginConfigFactory cfgFactory,
+ AllProjectsNameProvider allProjects,
DynamicMap<RestView<ProjectResource>> views,
Provider<CurrentUser> currentUser) {
this.config = config;
this.pluginConfigEntries = pluginConfigEntries;
+ this.allProjects = allProjects;
this.cfgFactory = cfgFactory;
this.views = views;
}
@@ -46,6 +50,6 @@
@Override
public ConfigInfo apply(ProjectResource resource) {
return new ConfigInfo(resource.getControl(), config,
- pluginConfigEntries, cfgFactory, views);
+ pluginConfigEntries, cfgFactory, allProjects, views);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
index 0cfdbd2..e50c751 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
@@ -26,6 +26,7 @@
import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
import com.google.gerrit.reviewdb.client.Project.SubmitType;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
@@ -67,6 +68,7 @@
private final TransferConfig config;
private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
private final PluginConfigFactory cfgFactory;
+ private final AllProjectsNameProvider allProjects;
private final DynamicMap<RestView<ProjectResource>> views;
private final Provider<CurrentUser> currentUser;
@@ -78,6 +80,7 @@
TransferConfig config,
DynamicMap<ProjectConfigEntry> pluginConfigEntries,
PluginConfigFactory cfgFactory,
+ AllProjectsNameProvider allProjects,
DynamicMap<RestView<ProjectResource>> views,
Provider<CurrentUser> currentUser) {
this.metaDataUpdateFactory = metaDataUpdateFactory;
@@ -87,6 +90,7 @@
this.config = config;
this.pluginConfigEntries = pluginConfigEntries;
this.cfgFactory = cfgFactory;
+ this.allProjects = allProjects;
this.views = views;
this.currentUser = currentUser;
}
@@ -162,9 +166,8 @@
}
ProjectState state = projectStateFactory.create(projectConfig);
- return new ConfigInfo(
- state.controlFor(currentUser.get()),
- config, pluginConfigEntries, cfgFactory, views);
+ return new ConfigInfo(state.controlFor(currentUser.get()), config,
+ pluginConfigEntries, cfgFactory, allProjects, views);
} catch (ConfigInvalidException err) {
throw new ResourceConflictException("Cannot read project " + projectName, err);
} catch (IOException err) {