blob: 8030d787071dc4f0f3fdc80165a2e57846795c3b [file] [log] [blame]
package com.googlesource.gerrit.plugins.hooks.util;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.hooks.its.ItsName;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class IssueExtractor {
private static final Logger log = LoggerFactory.getLogger(
IssueExtractor.class);
private final Config gerritConfig;
private final String itsName;
private final CommitMessageFetcher commitMessageFetcher;
@Inject
IssueExtractor(@GerritServerConfig Config gerritConfig,
@ItsName String itsName, CommitMessageFetcher commitMessageFetcher) {
this.gerritConfig = gerritConfig;
this.itsName = itsName;
this.commitMessageFetcher = commitMessageFetcher;
}
/**
* Gets issue ids from a string.
*
* @param haystack String to extract issue ids from
* @return array of {@link Strings}. Each String being a found issue id.
*/
public String[] getIssueIds(String haystack) {
Pattern pattern = getPattern();
if (pattern == null) return new String[] {};
log.debug("Matching '" + haystack + "' against " + pattern.pattern());
Set<String> issues = Sets.newHashSet();
Matcher matcher = pattern.matcher(haystack);
while (matcher.find()) {
int groupIdx = Math.min(matcher.groupCount(), 1);
issues.add(matcher.group(groupIdx));
}
return issues.toArray(new String[issues.size()]);
}
/**
* Gets the regular expression used to identify issue ids.
* @return the regular expression, or {@code null}, if there is no pattern
* to match issue ids.
*/
public Pattern getPattern() {
Pattern ret = null;
String match = gerritConfig.getString("commentLink", itsName, "match");
if (match != null) {
ret = Pattern.compile(match);
}
return ret;
}
/**
* Adds an issue to the map returned by {@link #getIssueIds(String, String)}.
*
* @param issue The issue to add.
* @param map The map that the issue should get added to.
* @param occurrence The occurrence the issue get added at in {@code map}.
*/
private void addIssueOccurrence(String issue, Map<String,Set<String>> map, String occurrence) {
Set<String> occurrences = map.get(issue);
if (occurrences == null) {
occurrences = Sets.newLinkedHashSet();
map.put(issue, occurrences);
}
occurrences.add(occurrence);
}
/**
* Gets issues for a commit.
*
* @param projectName The project to fetch {@code commitId} from.
* @param commitId The commit id to fetch issues for.
* @return A mapping, whose keys are issue ids and whose values is a set of
* places where the issue occurs. Each issue occurs at least in
* "somewhere".
*/
public Map<String,Set<String>> getIssueIds(String projectName,
String commitId) {
Map<String,Set<String>> ret = Maps.newHashMap();
String commitMessage = commitMessageFetcher.fetchGuarded(projectName,
commitId);
for (String issue : getIssueIds(commitMessage)) {
addIssueOccurrence(issue, ret, "somewhere");
}
return ret;
}
}