Skip to content

Commit 6481976

Browse files
author
Vladimir Kotal
committed
allow to configure bug/review properties per project
fixes #3773
1 parent e24a7d7 commit 6481976

File tree

6 files changed

+193
-31
lines changed

6 files changed

+193
-31
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/Configuration.java

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
import org.opengrok.indexer.history.RepositoryInfo;
6161
import org.opengrok.indexer.logger.LoggerFactory;
6262

63+
import static org.opengrok.indexer.configuration.PatternUtil.compilePattern;
64+
6365

6466
/**
6567
* Placeholder class for all configuration variables. Due to the multi-threaded
@@ -76,20 +78,6 @@ public final class Configuration {
7678
private static final Logger LOGGER = LoggerFactory.getLogger(Configuration.class);
7779
public static final String PLUGIN_DIRECTORY_DEFAULT = "plugins";
7880

79-
/**
80-
* A check if a pattern contains at least one pair of parentheses meaning
81-
* that there is at least one capture group. This group must not be empty.
82-
*/
83-
private static final String PATTERN_SINGLE_GROUP = ".*\\([^\\)]+\\).*";
84-
/**
85-
* Error string for invalid patterns without a single group. This is passed
86-
* as a first argument to the constructor of PatternSyntaxException and in
87-
* the output it is followed by the invalid pattern.
88-
*
89-
* @see PatternSyntaxException
90-
* @see #PATTERN_SINGLE_GROUP
91-
*/
92-
private static final String PATTERN_MUST_CONTAIN_GROUP = "The pattern must contain at least one non-empty group -";
9381
/**
9482
* Error string for negative numbers (could be int, double, long, ...).
9583
* First argument is the name of the property, second argument is the actual
@@ -1057,10 +1045,7 @@ public String getBugPage() {
10571045
* contain a single character
10581046
*/
10591047
public void setBugPattern(String bugPattern) throws PatternSyntaxException {
1060-
if (!bugPattern.matches(PATTERN_SINGLE_GROUP)) {
1061-
throw new PatternSyntaxException(PATTERN_MUST_CONTAIN_GROUP, bugPattern, 0);
1062-
}
1063-
this.bugPattern = Pattern.compile(bugPattern).toString();
1048+
this.bugPattern = compilePattern(bugPattern);
10641049
}
10651050

10661051
public String getBugPattern() {
@@ -1088,10 +1073,7 @@ public String getReviewPattern() {
10881073
* contain a single character
10891074
*/
10901075
public void setReviewPattern(String reviewPattern) throws PatternSyntaxException {
1091-
if (!reviewPattern.matches(PATTERN_SINGLE_GROUP)) {
1092-
throw new PatternSyntaxException(PATTERN_MUST_CONTAIN_GROUP, reviewPattern, 0);
1093-
}
1094-
this.reviewPattern = Pattern.compile(reviewPattern).toString();
1076+
this.reviewPattern = compilePattern(reviewPattern);
10951077
}
10961078

10971079
public String getWebappLAF() {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
22+
*/
23+
package org.opengrok.indexer.configuration;
24+
25+
import java.util.regex.Pattern;
26+
import java.util.regex.PatternSyntaxException;
27+
28+
public class PatternUtil {
29+
private PatternUtil() {
30+
// private to enforce static
31+
}
32+
33+
/**
34+
* A check if a pattern contains at least one pair of parentheses meaning
35+
* that there is at least one capture group. This group must not be empty.
36+
*/
37+
static final String PATTERN_SINGLE_GROUP = ".*\\([^\\)]+\\).*";
38+
/**
39+
* Error string for invalid patterns without a single group. This is passed
40+
* as a first argument to the constructor of PatternSyntaxException and in
41+
* the output it is followed by the invalid pattern.
42+
*
43+
* @see PatternSyntaxException
44+
* @see #PATTERN_SINGLE_GROUP
45+
*/
46+
static final String PATTERN_MUST_CONTAIN_GROUP = "The pattern must contain at least one non-empty group -";
47+
48+
/**
49+
* Check and compile the bug pattern.
50+
*
51+
* @param pattern the new pattern
52+
* @throws PatternSyntaxException when the pattern is not a valid regexp or
53+
* does not contain at least one capture group and the group does not
54+
* contain a single character
55+
*/
56+
public static String compilePattern(String pattern) throws PatternSyntaxException {
57+
if (!pattern.matches(PATTERN_SINGLE_GROUP)) {
58+
throw new PatternSyntaxException(PATTERN_MUST_CONTAIN_GROUP, pattern, 0);
59+
}
60+
return Pattern.compile(pattern).toString();
61+
}
62+
}

opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/Project.java

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@
3232
import java.util.TreeSet;
3333
import java.util.logging.Level;
3434
import java.util.logging.Logger;
35+
import java.util.regex.PatternSyntaxException;
36+
3537
import org.opengrok.indexer.logger.LoggerFactory;
3638
import org.opengrok.indexer.util.ClassUtil;
3739
import org.opengrok.indexer.util.ForbiddenSymlinkException;
3840
import org.opengrok.indexer.web.Util;
3941

42+
import static org.opengrok.indexer.configuration.PatternUtil.compilePattern;
43+
4044
/**
4145
* Placeholder for the information that builds up a project.
4246
*/
@@ -100,6 +104,14 @@ public class Project implements Comparable<Project>, Nameable, Serializable {
100104
*/
101105
private transient Set<Group> groups = new TreeSet<>();
102106

107+
/**
108+
* These properties override global settings, if set.
109+
*/
110+
private String bugPage;
111+
private String bugPattern;
112+
private String reviewPage;
113+
private String reviewPattern;
114+
103115
// This empty constructor is needed for serialization.
104116
public Project() {
105117
}
@@ -302,6 +314,70 @@ public void addGroup(Group group) {
302314
}
303315
}
304316

317+
public void setBugPage(String bugPage) {
318+
this.bugPage = bugPage;
319+
}
320+
321+
public String getBugPage() {
322+
if (bugPage != null) {
323+
return bugPage;
324+
} else {
325+
return RuntimeEnvironment.getInstance().getBugPage();
326+
}
327+
}
328+
329+
/**
330+
* Set the bug pattern to a new value.
331+
*
332+
* @param bugPattern the new pattern
333+
* @throws PatternSyntaxException when the pattern is not a valid regexp or
334+
* does not contain at least one capture group and the group does not
335+
* contain a single character
336+
*/
337+
public void setBugPattern(String bugPattern) throws PatternSyntaxException {
338+
this.bugPattern = compilePattern(bugPattern);
339+
}
340+
341+
public String getBugPattern() {
342+
if (bugPattern != null) {
343+
return bugPattern;
344+
} else {
345+
return RuntimeEnvironment.getInstance().getBugPattern();
346+
}
347+
}
348+
349+
public String getReviewPage() {
350+
if (reviewPage != null) {
351+
return reviewPage;
352+
} else {
353+
return RuntimeEnvironment.getInstance().getReviewPage();
354+
}
355+
}
356+
357+
public void setReviewPage(String reviewPage) {
358+
this.reviewPage = reviewPage;
359+
}
360+
361+
public String getReviewPattern() {
362+
if (reviewPattern != null) {
363+
return reviewPattern;
364+
} else {
365+
return RuntimeEnvironment.getInstance().getReviewPattern();
366+
}
367+
}
368+
369+
/**
370+
* Set the review pattern to a new value.
371+
*
372+
* @param reviewPattern the new pattern
373+
* @throws PatternSyntaxException when the pattern is not a valid regexp or
374+
* does not contain at least one capture group and the group does not
375+
* contain a single character
376+
*/
377+
public void setReviewPattern(String reviewPattern) throws PatternSyntaxException {
378+
this.reviewPattern = compilePattern(reviewPattern);
379+
}
380+
305381
/**
306382
* Fill the project with the current configuration where the applicable
307383
* project property has a default value.
@@ -310,7 +386,7 @@ public final void completeWithDefaults() {
310386
Configuration defaultCfg = new Configuration();
311387
final RuntimeEnvironment env = RuntimeEnvironment.getInstance();
312388

313-
/**
389+
/*
314390
* Choosing strategy for properties (tabSize used as example here):
315391
* <pre>
316392
* this cfg defaultCfg chosen value
@@ -346,6 +422,20 @@ public final void completeWithDefaults() {
346422
if (mergeCommitsEnabled == null) {
347423
setMergeCommitsEnabled(env.isMergeCommitsEnabled());
348424
}
425+
426+
if (bugPage == null) {
427+
setBugPage(env.getBugPage());
428+
}
429+
if (bugPattern == null) {
430+
setBugPattern(env.getBugPattern());
431+
}
432+
433+
if (reviewPage == null) {
434+
setReviewPage(env.getReviewPage());
435+
}
436+
if (reviewPattern == null) {
437+
setReviewPattern(env.getReviewPattern());
438+
}
349439
}
350440

351441
/**

opengrok-indexer/src/test/java/org/opengrok/indexer/configuration/ProjectTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ public void testMergeProjects1() {
135135
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
136136
env.setTabSize(new Configuration().getTabSize() + 3731);
137137
env.setNavigateWindowEnabled(!new Configuration().isNavigateWindowEnabled());
138+
env.setBugPage("http://example.com/bugPage");
139+
env.setBugPattern("([1-9][0-9]{6,7})");
140+
env.setReviewPage("http://example.com/reviewPage");
141+
env.setReviewPattern("([A-Z]{2}ARC[ \\\\/]\\\\d{4}/\\\\d{3})");
138142

139143
Project p1 = new Project();
140144
assertNotNull(p1);
@@ -143,6 +147,10 @@ public void testMergeProjects1() {
143147

144148
assertEquals(env.getTabSize(), p1.getTabSize());
145149
assertEquals(env.isNavigateWindowEnabled(), p1.isNavigateWindowEnabled());
150+
assertEquals(env.getBugPage(), p1.getBugPage());
151+
assertEquals(env.getBugPattern(), p1.getBugPattern());
152+
assertEquals(env.getReviewPage(), p1.getReviewPage());
153+
assertEquals(env.getReviewPattern(), p1.getReviewPattern());
146154
}
147155

148156
/**
@@ -157,13 +165,25 @@ public void testMergeProjects2() {
157165
p1.setTabSize(new Project().getTabSize() + 9737);
158166
p1.setNavigateWindowEnabled(true);
159167
p1.setHandleRenamedFiles(true);
168+
final String customBugPage = "http://example.com/bugPage";
169+
p1.setBugPage(customBugPage);
170+
final String customBugPattern = "([1-9][0-1]{6,7})";
171+
p1.setBugPattern(customBugPattern);
172+
final String customReviewPage = "http://example.com/reviewPage";
173+
p1.setReviewPage(customReviewPage);
174+
final String customReviewPattern = "([A-Z]{2}XYZ[ \\\\/]\\\\d{4}/\\\\d{3})";
175+
p1.setReviewPattern(customReviewPattern);
160176

161177
p1.completeWithDefaults();
162178

163179
assertNotNull(p1);
164180
assertTrue(p1.isNavigateWindowEnabled(), "Navigate window should be turned on");
165181
assertTrue(p1.isHandleRenamedFiles(), "Renamed file handling should be true");
166182
assertEquals(new Project().getTabSize() + 9737, p1.getTabSize());
183+
assertEquals(p1.getBugPage(), customBugPage);
184+
assertEquals(p1.getBugPattern(), customBugPattern);
185+
assertEquals(p1.getReviewPage(), customReviewPage);
186+
assertEquals(p1.getReviewPattern(), customReviewPattern);
167187
}
168188

169189
/**

opengrok-web/src/main/java/org/opengrok/web/PageConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ public String[] getSearchOnlyIn() {
791791
*
792792
* @return {@code null} if not available, the project otherwise.
793793
*/
794+
@Nullable
794795
public Project getProject() {
795796
return Project.getProject(getResourceFile());
796797
}

opengrok-web/src/main/webapp/history.jsp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,23 @@ include file="minisearch.jspf"
171171
if ((hist = (History) request.getAttribute("history.jsp-hist")) != null) {
172172
RuntimeEnvironment env = cfg.getEnv();
173173
String uriEncodedName = cfg.getUriEncodedPath();
174+
Project project = cfg.getProject();
174175
175176
boolean striked = false;
176177
String userPage = env.getUserPage();
177178
String userPageSuffix = env.getUserPageSuffix();
178-
String bugPage = env.getBugPage();
179-
String bugRegex = env.getBugPattern();
180-
Pattern bugPattern = Pattern.compile(bugRegex);
181-
String reviewPage = env.getReviewPage();
182-
String reviewRegex = env.getReviewPattern();
183-
Pattern reviewPattern = Pattern.compile(reviewRegex);
179+
String bugPage = project != null ? project.getBugPage() : env.getBugPage();
180+
String bugRegex = project != null ? project.getBugPattern() : env.getBugPattern();
181+
Pattern bugPattern = null;
182+
if (bugRegex != null) {
183+
bugPattern = Pattern.compile(bugRegex);
184+
}
185+
String reviewPage = project != null ? project.getReviewPage() : env.getReviewPage();
186+
String reviewRegex = project != null ? project.getReviewPattern() : env.getReviewPattern();
187+
Pattern reviewPattern = null;
188+
if (reviewRegex != null) {
189+
reviewPattern = Pattern.compile(reviewRegex);
190+
}
184191
185192
Format df = new SimpleDateFormat("dd-MMM-yyyy");
186193
@@ -352,10 +359,10 @@ document.domReady.push(function() {domReadyHistory();});
352359
int summaryLength = Math.max(10, cfg.getRevisionMessageCollapseThreshold());
353360
String cout = Util.htmlize(entry.getMessage());
354361
355-
if (bugPage != null && bugPage.length() > 0) {
362+
if (bugPage != null && bugPage.length() > 0 && bugPattern != null) {
356363
cout = Util.linkifyPattern(cout, bugPattern, "$1", Util.completeUrl(bugPage + "$1", request));
357364
}
358-
if (reviewPage != null && reviewPage.length() > 0) {
365+
if (reviewPage != null && reviewPage.length() > 0 && reviewPattern != null) {
359366
cout = Util.linkifyPattern(cout, reviewPattern, "$1", Util.completeUrl(reviewPage + "$1", request));
360367
}
361368

0 commit comments

Comments
 (0)