Sync with upstream @ https://github.com/mstrap/bugtraqpull/1438/head
@@ -36,6 +36,7 @@ import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.StringTokenizer; | |||
import org.eclipse.jgit.errors.ConfigInvalidException; | |||
import org.eclipse.jgit.lib.Config; | |||
@@ -69,6 +70,7 @@ public final class BugtraqConfig { | |||
private static final String LOG_FILTERREGEX = "logfilterregex"; | |||
private static final String LOG_LINKREGEX = "loglinkregex"; | |||
private static final String LOG_LINKTEXT = "loglinktext"; | |||
private static final String PROJECTS = "projects"; | |||
// Static ================================================================= | |||
@@ -91,6 +93,7 @@ public final class BugtraqConfig { | |||
} | |||
throw ex; | |||
} | |||
if (getString(null, URL, config, baseConfig) != null) { | |||
allNames.add(null); | |||
} | |||
@@ -101,7 +104,7 @@ public final class BugtraqConfig { | |||
} | |||
} | |||
final List<BugtraqEntry> entries = new ArrayList<BugtraqEntry>(); | |||
final List<BugtraqConfigEntry> entries = new ArrayList<>(); | |||
for (String name : allNames) { | |||
final String url = getString(name, URL, config, baseConfig); | |||
if (url == null) { | |||
@@ -149,8 +152,26 @@ public final class BugtraqConfig { | |||
} | |||
} | |||
final String projectsList = getString(name, PROJECTS, config, baseConfig); | |||
final List<String> projects; | |||
if (projectsList != null) { | |||
projects = new ArrayList<>(); | |||
final StringTokenizer tokenizer = new StringTokenizer(projectsList, ",", false); | |||
while (tokenizer.hasMoreTokens()) { | |||
projects.add(tokenizer.nextToken().trim()); | |||
} | |||
if (projects.isEmpty()) { | |||
throw new ConfigInvalidException("'" + name + ".projects' must specify at least one project or be not present at all."); | |||
} | |||
} | |||
else { | |||
projects = null; | |||
} | |||
final String linkText = getString(name, LOG_LINKTEXT, config, baseConfig); | |||
entries.add(new BugtraqEntry(url, idRegex, linkRegex, filterRegex, linkText)); | |||
entries.add(new BugtraqConfigEntry(url, idRegex, linkRegex, filterRegex, linkText, projects)); | |||
} | |||
if (entries.isEmpty()) { | |||
@@ -163,18 +184,18 @@ public final class BugtraqConfig { | |||
// Fields ================================================================= | |||
@NotNull | |||
private final List<BugtraqEntry> entries; | |||
private final List<BugtraqConfigEntry> entries; | |||
// Setup ================================================================== | |||
BugtraqConfig(@NotNull List<BugtraqEntry> entries) { | |||
BugtraqConfig(@NotNull List<BugtraqConfigEntry> entries) { | |||
this.entries = entries; | |||
} | |||
// Accessing ============================================================== | |||
@NotNull | |||
public List<BugtraqEntry> getEntries() { | |||
public List<BugtraqConfigEntry> getEntries() { | |||
return Collections.unmodifiableList(entries); | |||
} | |||
@@ -199,6 +220,7 @@ public final class BugtraqConfig { | |||
if (headId == null || ObjectId.zeroId().equals(headId)) { | |||
return null; | |||
} | |||
RevCommit commit = rw.parseCommit(headId); | |||
RevTree tree = commit.getTree(); | |||
tw.reset(tree); | |||
@@ -254,8 +276,8 @@ public final class BugtraqConfig { | |||
return trimMaybeNull(baseConfig.getString(BUGTRAQ, subsection, key)); | |||
} | |||
return value; | |||
} | |||
return value; | |||
} | |||
@Nullable | |||
private static String trimMaybeNull(@Nullable String string) { |
@@ -0,0 +1,80 @@ | |||
/* | |||
* Copyright (c) 2013 by syntevo GmbH. All Rights Reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions are met: | |||
* | |||
* o Redistributions of source code must retain the above copyright notice, | |||
* this list of conditions and the following disclaimer. | |||
* | |||
* o Redistributions in binary form must reproduce the above copyright notice, | |||
* this list of conditions and the following disclaimer in the documentation | |||
* and/or other materials provided with the distribution. | |||
* | |||
* o Neither the name of syntevo GmbH nor the names of | |||
* its contributors may be used to endorse or promote products derived | |||
* from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | |||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
package com.syntevo.bugtraq; | |||
import java.util.*; | |||
import org.jetbrains.annotations.*; | |||
public final class BugtraqConfigEntry { | |||
// Fields ================================================================= | |||
private final String url; | |||
private final List<String> projects; | |||
private final List<BugtraqEntry> entries; | |||
// Setup ================================================================== | |||
public BugtraqConfigEntry(@NotNull String url, @NotNull String logIdRegex, @Nullable String logLinkRegex, @Nullable String logFilterRegex, @Nullable String logLinkText, @Nullable List<String> projects) throws BugtraqException { | |||
this.url = url; | |||
this.projects = projects; | |||
this.entries = new ArrayList<>(); | |||
if (projects == null) { | |||
entries.add(new BugtraqEntry(url, logIdRegex, logLinkRegex, logFilterRegex, logLinkText)); | |||
} | |||
else { | |||
for (String project : projects) { | |||
final String projectUrl = this.url.replace("%PROJECT%", project); | |||
final String projectLogIdRegex = logIdRegex.replace("%PROJECT%", project); | |||
final String projectLogLinkRegex = logLinkRegex != null ? logLinkRegex.replace("%PROJECT%", project) : null; | |||
final String projectLogFilterRegex = logFilterRegex != null ? logFilterRegex.replace("%PROJECT%", project) : null; | |||
final String projectLogLinkText = logLinkText != null ? logLinkText.replace("%PROJECT%", project) : null; | |||
entries.add(new BugtraqEntry(projectUrl, projectLogIdRegex, projectLogLinkRegex, projectLogFilterRegex, projectLogLinkText)); | |||
} | |||
} | |||
} | |||
// Accessing ============================================================== | |||
@NotNull | |||
public String getUrl() { | |||
return url; | |||
} | |||
@Nullable | |||
public List<String> getProjects() { | |||
return projects != null ? Collections.unmodifiableList(projects) : null; | |||
} | |||
public List<BugtraqEntry> getEntries() { | |||
return entries; | |||
} | |||
} |
@@ -31,7 +31,7 @@ package com.syntevo.bugtraq; | |||
import org.jetbrains.annotations.*; | |||
final class BugtraqEntry { | |||
public final class BugtraqEntry { | |||
// Fields ================================================================= | |||
@@ -57,10 +57,12 @@ public final class BugtraqFormatter { | |||
} | |||
}); | |||
for (BugtraqEntry entry : config.getEntries()) { | |||
final List<BugtraqParserIssueId> ids = entry.getParser().parse(message); | |||
for (BugtraqParserIssueId id : ids) { | |||
allIds.add(new IssueId(entry, id)); | |||
for (BugtraqConfigEntry configEntry : config.getEntries()) { | |||
for (BugtraqEntry entry : configEntry.getEntries()) { | |||
final List<BugtraqParserIssueId> ids = entry.getParser().parse(message); | |||
for (BugtraqParserIssueId id : ids) { | |||
allIds.add(new IssueId(entry, id)); | |||
} | |||
} | |||
} | |||
@@ -32,6 +32,7 @@ package com.syntevo.bugtraq; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.StringTokenizer; | |||
import junit.framework.TestCase; | |||
@@ -43,28 +44,28 @@ public class BugtraqFormatterTest extends TestCase { | |||
// Accessing ============================================================== | |||
public void testSimpleWithExtendedLink() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/JRA-%BUGID%", null, "JRA-\\d+", "\\d+", null)); | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/JRA-%BUGID%", null, "JRA-\\d+", "\\d+", null, null)); | |||
doTest(formatter, "JRA-7399: Email subject formatting", l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(": Email subject formatting")); | |||
doTest(formatter, " JRA-7399, JRA-7398: Email subject formatting", t(" "), l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(", "), l("JRA-7398", "https://jira.atlassian.com/browse/JRA-7398"), t(": Email subject formatting")); | |||
doTest(formatter, "Fixed JRA-7399", t("Fixed "), l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399")); | |||
} | |||
public void testLinkText() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/JRA-%BUGID%", null, "JRA-\\d+", "\\d+", "JIRA-%BUGID%")); | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/JRA-%BUGID%", null, "JRA-\\d+", "\\d+", "JIRA-%BUGID%", null)); | |||
doTest(formatter, " JRA-7399, JRA is text, JRA-7398: Email subject formatting", t(" "), l("JIRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(", JRA is text, "), l("JIRA-7398", "https://jira.atlassian.com/browse/JRA-7398"), t(": Email subject formatting")); | |||
} | |||
public void testTwoNonIntersectingConfigurations() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/%BUGID%", null, null, "JRA-\\d+", null), | |||
createEntry("https://issues.apache.org/jira/browse/%BUGID%", null, null, "VELOCITY-\\d+", null)); | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/%BUGID%", null, null, "JRA-\\d+", null, null), | |||
createEntry("https://issues.apache.org/jira/browse/%BUGID%", null, null, "VELOCITY-\\d+", null, null)); | |||
doTest(formatter, "JRA-7399, VELOCITY-847: fix", l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(", "), l("VELOCITY-847", "https://issues.apache.org/jira/browse/VELOCITY-847"), t(": fix")); | |||
doTest(formatter, " JRA-7399: fix/VELOCITY-847", t(" "), l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(": fix/"), l("VELOCITY-847", "https://issues.apache.org/jira/browse/VELOCITY-847")); | |||
doTest(formatter, "JRA-7399VELOCITY-847", l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), l("VELOCITY-847", "https://issues.apache.org/jira/browse/VELOCITY-847")); | |||
} | |||
public void testTwoIntersectingConfigurations() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://host1/%BUGID%", null, null, "A[AB]", null), | |||
createEntry("https://host2/%BUGID%", null, null, "BA[A]?", null)); | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://host1/%BUGID%", null, null, "A[AB]", null, null), | |||
createEntry("https://host2/%BUGID%", null, null, "BA[A]?", null, null)); | |||
doTest(formatter, "AA: fix", l("AA", "https://host1/AA"), t(": fix")); | |||
doTest(formatter, "AB: fix", l("AB", "https://host1/AB"), t(": fix")); | |||
doTest(formatter, "BA: fix", l("BA", "https://host2/BA"), t(": fix")); | |||
@@ -79,14 +80,34 @@ public class BugtraqFormatterTest extends TestCase { | |||
doTest(formatter, "BAABBA: fix", l("BAA", "https://host2/BAA"), t("B"), l("BA", "https://host2/BA"), t(": fix")); | |||
} | |||
public void testMultipleProjects() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/%PROJECT%-%BUGID%", null, "%PROJECT%-\\d+", "\\d+", null, "JRA,JRB,JRC")); | |||
doTest(formatter, "JRA-7399: Email subject formatting", l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(": Email subject formatting")); | |||
doTest(formatter, " JRA-7399, JRB-7398: Email subject formatting", t(" "), l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(", "), l("JRB-7398", "https://jira.atlassian.com/browse/JRB-7398"), t(": Email subject formatting")); | |||
doTest(formatter, "Fixed JRC-7399", t("Fixed "), l("JRC-7399", "https://jira.atlassian.com/browse/JRC-7399")); | |||
} | |||
// Utils ================================================================== | |||
private BugtraqFormatter createFormatter(BugtraqEntry ... entries) { | |||
private BugtraqFormatter createFormatter(BugtraqConfigEntry ... entries) { | |||
return new BugtraqFormatter(new BugtraqConfig(Arrays.asList(entries))); | |||
} | |||
private BugtraqConfigEntry createEntry(String url, @Nullable String filterRegex, @Nullable String linkRegex, @NotNull String idRegex, @Nullable String linkText, @Nullable String projectsList) throws BugtraqException { | |||
final List<String> projects; | |||
if (projectsList != null) { | |||
projects = new ArrayList<>(); | |||
final StringTokenizer tokenizer = new StringTokenizer(projectsList, ",", false); | |||
while (tokenizer.hasMoreTokens()) { | |||
projects.add(tokenizer.nextToken()); | |||
} | |||
} | |||
else { | |||
projects = null; | |||
} | |||
private BugtraqEntry createEntry(String url, @Nullable String filterRegex, @Nullable String linkRegex, @NotNull String idRegex, @Nullable String linkText) throws BugtraqException { | |||
return new BugtraqEntry(url, idRegex, linkRegex, filterRegex, linkText); | |||
return new BugtraqConfigEntry(url, idRegex, linkRegex, filterRegex, linkText, projects); | |||
} | |||
private Text t(String text) { |