Merge "Allow to extract issue ids directly by project name, and commit id"
diff --git a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java
index 970d5c4..8030d78 100644
--- a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java
+++ b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractor.java
@@ -1,9 +1,11 @@
 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;
@@ -21,12 +23,14 @@
 
   private final Config gerritConfig;
   private final String itsName;
+  private final CommitMessageFetcher commitMessageFetcher;
 
   @Inject
   IssueExtractor(@GerritServerConfig Config gerritConfig,
-      @ItsName String itsName) {
+      @ItsName String itsName, CommitMessageFetcher commitMessageFetcher) {
     this.gerritConfig = gerritConfig;
     this.itsName = itsName;
+    this.commitMessageFetcher = commitMessageFetcher;
   }
 
   /**
@@ -65,4 +69,40 @@
     }
     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;
+  }
 }
diff --git a/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractorTest.java b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractorTest.java
index f1290ea..33705a3 100644
--- a/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractorTest.java
+++ b/hooks-its/src/test/java/com/googlesource/gerrit/plugins/hooks/util/IssueExtractorTest.java
@@ -17,9 +17,13 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import org.eclipse.jgit.lib.Config;
 
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import com.google.gerrit.server.config.FactoryModule;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.inject.Guice;
@@ -30,6 +34,7 @@
 public class IssueExtractorTest extends LoggingMockingTestCase {
   private Injector injector;
   private Config serverConfig;
+  private CommitMessageFetcher commitMessageFetcher;
 
   public void testPatternNullMatch() {
     IssueExtractor issueExtractor = injector.getInstance(IssueExtractor.class);
@@ -171,6 +176,77 @@
     assertLogMessageContains("Matching");
   }
 
+  public void testIssueIdsCommitSingleIssue() {
+    expect(serverConfig.getString("commentLink", "ItsTestName", "match"))
+    .andReturn("bug#(\\d+)").atLeastOnce();
+
+    expect(commitMessageFetcher.fetchGuarded("testProject",
+        "1234567891123456789212345678931234567894")).andReturn(
+            "bug#42\n" +
+            "\n" +
+            "Change-Id: I1234567891123456789212345678931234567894");
+
+    replayMocks();
+
+    IssueExtractor issueExtractor = injector.getInstance(IssueExtractor.class);
+    Map<String,Set<String>> actual = issueExtractor.getIssueIds("testProject",
+        "1234567891123456789212345678931234567894");
+
+    Map<String,Set<String>> expected = Maps.newHashMap();
+    expected.put("42", Sets.newHashSet("somewhere"));
+    assertEquals("Extracted issues do not match", expected, actual);
+
+    assertLogMessageContains("Matching");
+  }
+
+  public void testIssueIdsCommitMultipleIssues() {
+    expect(serverConfig.getString("commentLink", "ItsTestName", "match"))
+    .andReturn("bug#(\\d+)").atLeastOnce();
+
+    expect(commitMessageFetcher.fetchGuarded("testProject",
+        "1234567891123456789212345678931234567894")).andReturn(
+            "bug#42, and bug#4711\n" +
+            "\n" +
+            "Change-Id: I1234567891123456789212345678931234567894");
+
+    replayMocks();
+
+    IssueExtractor issueExtractor = injector.getInstance(IssueExtractor.class);
+    Map<String,Set<String>> actual = issueExtractor.getIssueIds("testProject",
+        "1234567891123456789212345678931234567894");
+
+    Map<String,Set<String>> expected = Maps.newHashMap();
+    expected.put("42", Sets.newHashSet("somewhere"));
+    expected.put("4711", Sets.newHashSet("somewhere"));
+    assertEquals("Extracted issues do not match", expected, actual);
+
+    assertLogMessageContains("Matching");
+  }
+
+  public void testIssueIdsCommitMultipleIssuesMultipleTimes() {
+    expect(serverConfig.getString("commentLink", "ItsTestName", "match"))
+    .andReturn("bug#(\\d+)").atLeastOnce();
+
+    expect(commitMessageFetcher.fetchGuarded("testProject",
+        "1234567891123456789212345678931234567894")).andReturn(
+            "bug#42, bug#4711, bug#4711, bug#42, and bug#4711\n" +
+            "\n" +
+            "Change-Id: I1234567891123456789212345678931234567894");
+
+    replayMocks();
+
+    IssueExtractor issueExtractor = injector.getInstance(IssueExtractor.class);
+    Map<String,Set<String>> actual = issueExtractor.getIssueIds("testProject",
+        "1234567891123456789212345678931234567894");
+
+    Map<String,Set<String>> expected = Maps.newHashMap();
+    expected.put("42", Sets.newHashSet("somewhere"));
+    expected.put("4711", Sets.newHashSet("somewhere"));
+    assertEquals("Extracted issues do not match", expected, actual);
+
+    assertLogMessageContains("Matching");
+  }
+
   @Override
   public void setUp() throws Exception {
     super.setUp();
@@ -187,6 +263,9 @@
       serverConfig = createMock(Config.class);
       bind(Config.class).annotatedWith(GerritServerConfig.class)
           .toInstance(serverConfig);
+
+      commitMessageFetcher = createMock(CommitMessageFetcher.class);
+      bind(CommitMessageFetcher.class).toInstance(commitMessageFetcher);
     }
   }
 }
\ No newline at end of file