Allow defining commentlinks in project.config
These are inherited from parent projects, including the system-wide commentlinks defined in project.config in all projects. Child projects may override commentlinks defined in parents by name, which project administrators can discover via GET /projects/myparent/config. Change-Id: I96dd6701350761a0af6e3d9babdef4f74ad4e29f
This commit is contained in:
@@ -14,12 +14,14 @@
|
||||
|
||||
package com.google.gerrit.server.git;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.gerrit.common.data.Permission.isPermission;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -66,6 +68,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class ProjectConfig extends VersionedMetaData {
|
||||
public static final String COMMENTLINK = "commentlink";
|
||||
@@ -138,6 +141,7 @@ public class ProjectConfig extends VersionedMetaData {
|
||||
private Map<String, ContributorAgreement> contributorAgreements;
|
||||
private Map<String, NotifyConfig> notifySections;
|
||||
private Map<String, LabelType> labelSections;
|
||||
private List<CommentLinkInfo> commentLinkSections;
|
||||
private List<ValidationError> validationErrors;
|
||||
private ObjectId rulesId;
|
||||
|
||||
@@ -155,8 +159,8 @@ public class ProjectConfig extends VersionedMetaData {
|
||||
return r;
|
||||
}
|
||||
|
||||
public static CommentLinkInfo buildCommentLink(Config cfg, String name)
|
||||
throws IllegalArgumentException {
|
||||
public static CommentLinkInfo buildCommentLink(Config cfg, String name,
|
||||
boolean allowRaw) throws IllegalArgumentException {
|
||||
String match = cfg.getString(COMMENTLINK, name, KEY_MATCH);
|
||||
|
||||
// Unfortunately this validation isn't entirely complete. Clients
|
||||
@@ -168,6 +172,8 @@ public class ProjectConfig extends VersionedMetaData {
|
||||
|
||||
String link = cfg.getString(COMMENTLINK, name, KEY_LINK);
|
||||
String html = cfg.getString(COMMENTLINK, name, KEY_HTML);
|
||||
checkArgument(allowRaw || Strings.isNullOrEmpty(html),
|
||||
"Raw html replacement not allowed");
|
||||
return new CommentLinkInfo(name, match, link, html);
|
||||
}
|
||||
|
||||
@@ -256,6 +262,10 @@ public class ProjectConfig extends VersionedMetaData {
|
||||
return labelSections;
|
||||
}
|
||||
|
||||
public Collection<CommentLinkInfo> getCommentLinkSections() {
|
||||
return commentLinkSections;
|
||||
}
|
||||
|
||||
public GroupReference resolve(AccountGroup group) {
|
||||
return resolve(GroupReference.forGroup(group));
|
||||
}
|
||||
@@ -356,6 +366,7 @@ public class ProjectConfig extends VersionedMetaData {
|
||||
loadAccessSections(rc, groupsByName);
|
||||
loadNotifySections(rc, groupsByName);
|
||||
loadLabelSections(rc);
|
||||
loadCommentLinkSections(rc);
|
||||
}
|
||||
|
||||
private void loadAccountsSection(
|
||||
@@ -613,6 +624,25 @@ public class ProjectConfig extends VersionedMetaData {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadCommentLinkSections(Config rc) {
|
||||
Set<String> subsections = rc.getSubsections(COMMENTLINK);
|
||||
commentLinkSections = Lists.newArrayListWithCapacity(subsections.size());
|
||||
for (String name : subsections) {
|
||||
try {
|
||||
commentLinkSections.add(buildCommentLink(rc, name, false));
|
||||
} catch (PatternSyntaxException e) {
|
||||
error(new ValidationError(PROJECT_CONFIG, String.format(
|
||||
"Invalid pattern \"%s\" in commentlink.%s.match: %s",
|
||||
rc.getString(COMMENTLINK, name, KEY_MATCH), name, e.getMessage())));
|
||||
} catch (IllegalArgumentException e) {
|
||||
error(new ValidationError(PROJECT_CONFIG, String.format(
|
||||
"Error in pattern \"%s\" in commentlink.%s.match: %s",
|
||||
rc.getString(COMMENTLINK, name, KEY_MATCH), name, e.getMessage())));
|
||||
}
|
||||
}
|
||||
commentLinkSections = ImmutableList.copyOf(commentLinkSections);
|
||||
}
|
||||
|
||||
private Map<String, GroupReference> readGroupList() throws IOException {
|
||||
groupsByUUID = new HashMap<AccountGroup.UUID, GroupReference>();
|
||||
Map<String, GroupReference> groupsByName =
|
||||
|
@@ -40,7 +40,7 @@ public class CommentLinkProvider implements Provider<List<CommentLinkInfo>> {
|
||||
List<CommentLinkInfo> cls =
|
||||
Lists.newArrayListWithCapacity(subsections.size());
|
||||
for (String name : subsections) {
|
||||
cls.add(ProjectConfig.buildCommentLink(cfg, name));
|
||||
cls.add(ProjectConfig.buildCommentLink(cfg, name, true));
|
||||
}
|
||||
return ImmutableList.copyOf(cls);
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ package com.google.gerrit.server.project;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
@@ -295,6 +296,16 @@ public class ProjectState {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an iterable that walks in-order from All-Projects through the
|
||||
* project hierarchy to this project.
|
||||
*/
|
||||
public Iterable<ProjectState> treeInOrder() {
|
||||
List<ProjectState> projects = Lists.newArrayList(tree());
|
||||
Collections.reverse(projects);
|
||||
return projects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an iterable that walks through the parents of this project. Starts
|
||||
* from the immediate parent of this project and progresses up the
|
||||
@@ -346,9 +357,7 @@ public class ProjectState {
|
||||
|
||||
public LabelTypes getLabelTypes() {
|
||||
Map<String, LabelType> types = Maps.newLinkedHashMap();
|
||||
List<ProjectState> projects = Lists.newArrayList(tree());
|
||||
Collections.reverse(projects);
|
||||
for (ProjectState s : projects) {
|
||||
for (ProjectState s : treeInOrder()) {
|
||||
for (LabelType type : s.getConfig().getLabelSections().values()) {
|
||||
String lower = type.getName().toLowerCase();
|
||||
LabelType old = types.get(lower);
|
||||
@@ -367,7 +376,16 @@ public class ProjectState {
|
||||
}
|
||||
|
||||
public List<CommentLinkInfo> getCommentLinks() {
|
||||
return commentLinks;
|
||||
Map<String, CommentLinkInfo> cls = Maps.newLinkedHashMap();
|
||||
for (CommentLinkInfo cl : commentLinks) {
|
||||
cls.put(cl.name.toLowerCase(), cl);
|
||||
}
|
||||
for (ProjectState s : treeInOrder()) {
|
||||
for (CommentLinkInfo cl : s.getConfig().getCommentLinkSections()) {
|
||||
cls.put(cl.name.toLowerCase(), cl);
|
||||
}
|
||||
}
|
||||
return ImmutableList.copyOf(cls.values());
|
||||
}
|
||||
|
||||
private boolean getInheritableBoolean(Function<Project, InheritableBoolean> func) {
|
||||
|
Reference in New Issue
Block a user