]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5254 New WS /api/sources/scm
authorSimon Brandhof <simon.brandhof@gmail.com>
Tue, 29 Apr 2014 16:16:21 +0000 (18:16 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Tue, 29 Apr 2014 16:16:21 +0000 (18:16 +0200)
19 files changed:
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java
sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
sonar-server/src/main/java/org/sonar/server/source/SourceService.java
sonar-server/src/main/java/org/sonar/server/source/ws/ScmAction.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/source/ws/ScmWriter.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/source/ws/ShowAction.java
sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java
sonar-server/src/main/java/org/sonar/server/ws/ListingWs.java
sonar-server/src/test/java/org/sonar/server/source/ws/ScmWriterTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java
sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java
sonar-server/src/test/java/org/sonar/server/ws/ListingWsTest.java
sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_grouped_scm_commits.json [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm.json [deleted file]
sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_commits.json [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_with_from_and_to_params.json [deleted file]
sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_without_repeating_same_lines.json [deleted file]
sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_without_repeating_same_lines_and_with_from_param_after_repetition.json [deleted file]
sonar-server/src/test/resources/org/sonar/server/ws/ListingWsTest/list.json

index 31fd348d2a5b4c0f7a1f3f9b2e46508803f9154f..3f75ee3777f46f461dea7541c482665a09eed58f 100644 (file)
@@ -441,7 +441,7 @@ public interface WebService extends ServerExtension {
       this.exampleValue = newParam.exampleValue;
       this.defaultValue = newParam.defaultValue;
       this.required = newParam.required;
-      this.possibleValues = (newParam.possibleValues == null ? new String[0] : newParam.possibleValues);
+      this.possibleValues = newParam.possibleValues;
     }
 
     public String key() {
@@ -472,6 +472,7 @@ public interface WebService extends ServerExtension {
     /**
      * @since 4.4
      */
+    @CheckForNull
     public String[] possibleValues() {
       return possibleValues;
     }
index 0c437cf82ce36371247caf34694a078189f01e42..b2fcfe87dcde37297f93701605447e0540afbe39 100644 (file)
@@ -116,6 +116,8 @@ import org.sonar.server.source.CodeColorizers;
 import org.sonar.server.source.DeprecatedSourceDecorator;
 import org.sonar.server.source.HtmlSourceDecorator;
 import org.sonar.server.source.SourceService;
+import org.sonar.server.source.ws.ScmAction;
+import org.sonar.server.source.ws.ScmWriter;
 import org.sonar.server.source.ws.ShowAction;
 import org.sonar.server.source.ws.SourcesWs;
 import org.sonar.server.startup.*;
@@ -384,6 +386,8 @@ class ServerComponents {
     pico.addSingleton(SourceService.class);
     pico.addSingleton(SourcesWs.class);
     pico.addSingleton(ShowAction.class);
+    pico.addSingleton(ScmWriter.class);
+    pico.addSingleton(ScmAction.class);
 
     // text
     pico.addSingleton(MacroInterpreter.class);
index 07ac61c839ab9c60a891e820677489c564045815..e081b1cce793bc56db6abd20c79d81f324e2d955 100644 (file)
@@ -58,11 +58,7 @@ public class SourceService implements ServerComponent {
   }
 
   public List<String> getLinesAsHtml(String fileKey, @Nullable Integer from, @Nullable Integer to) {
-    ResourceDto project = resourceDao.getRootProjectByComponentKey(fileKey);
-    if (project == null) {
-      throw new NotFoundException("File does not exist");
-    }
-    UserSession.get().checkProjectPermission(UserRole.CODEVIEWER, project.getKey());
+    checkPermission(fileKey);
 
     List<String> decoratedSource = sourceDecorator.getDecoratedSourceAsHtml(fileKey, from, to);
     if (!decoratedSource.isEmpty()) {
@@ -71,11 +67,25 @@ public class SourceService implements ServerComponent {
     return deprecatedSourceDecorator.getSourceAsHtml(fileKey, from, to);
   }
 
+  public void checkPermission(String fileKey) {
+    ResourceDto project = resourceDao.getRootProjectByComponentKey(fileKey);
+    if (project == null) {
+      throw new NotFoundException("File does not exist");
+    }
+    UserSession.get().checkProjectPermission(UserRole.CODEVIEWER, project.getKey());
+  }
+
+  /**
+   * Warning - does not check permission
+   */
   @CheckForNull
   public String getScmAuthorData(String fileKey) {
     return findDataFromComponent(fileKey, CoreMetrics.SCM_AUTHORS_BY_LINE_KEY);
   }
 
+  /**
+   * Warning - does not check permission
+   */
   @CheckForNull
   public String getScmDateData(String fileKey) {
     return findDataFromComponent(fileKey, CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY);
diff --git a/sonar-server/src/main/java/org/sonar/server/source/ws/ScmAction.java b/sonar-server/src/main/java/org/sonar/server/source/ws/ScmAction.java
new file mode 100644 (file)
index 0000000..eb227b5
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.source.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.RequestHandler;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.source.SourceService;
+
+public class ScmAction implements RequestHandler {
+
+  private final SourceService service;
+  private final ScmWriter scmWriter;
+
+  public ScmAction(SourceService service, ScmWriter scmWriter) {
+    this.service = service;
+    this.scmWriter = scmWriter;
+  }
+
+  void define(WebService.NewController controller) {
+    WebService.NewAction action = controller.createAction("scm")
+      .setDescription("Get SCM information of source files")
+      .setSince("4.4")
+      .setHandler(this);
+
+    action
+      .createParam("key")
+      .setRequired(true)
+      .setDescription("File key")
+      .setExampleValue("my_project:/src/foo/Bar.php");
+
+    action
+      .createParam("from")
+      .setDescription("First line to return. Starts at 1.")
+      .setExampleValue("10")
+      .setDefaultValue("1");
+
+    action
+      .createParam("to")
+      .setDescription("Last line to return (inclusive)")
+      .setExampleValue("20");
+
+    action
+      .createParam("groupCommits")
+      .setDescription("Group lines by SCM commit")
+      .setPossibleValues("false", "true")
+      .setDefaultValue("true");
+  }
+
+  @Override
+  public void handle(Request request, Response response) {
+    String fileKey = request.mandatoryParam("key");
+    service.checkPermission(fileKey);
+
+    int from = Math.max(request.paramAsInt("from", 1), 1);
+    int to = request.paramAsInt("to", Integer.MAX_VALUE);
+
+    String authors = service.getScmAuthorData(fileKey);
+    String dates = service.getScmDateData(fileKey);
+
+    JsonWriter json = response.newJsonWriter().beginObject();
+    scmWriter.write(authors, dates, from, to, request.paramAsBoolean("groupCommits", true), json);
+    json.endObject().close();
+  }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/source/ws/ScmWriter.java b/sonar-server/src/main/java/org/sonar/server/source/ws/ScmWriter.java
new file mode 100644 (file)
index 0000000..d00b837
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.source.ws;
+
+import com.google.common.base.Splitter;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.text.JsonWriter;
+
+import javax.annotation.Nullable;
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+public class ScmWriter implements ServerComponent {
+
+  void write(@Nullable String authorsData, @Nullable String datesDate, int from, int to, boolean group, JsonWriter json) {
+    json.name("scm").beginObject();
+    if (authorsData != null) {
+      List<String> authors = splitLine(authorsData);
+      List<String> dates = splitLine(datesDate);
+
+      String previousAuthor = null;
+      String previousDate = null;
+      boolean started = false;
+      for (int i = 0; i < authors.size(); i++) {
+        String[] authorWithLine = splitColumn(authors.get(i));
+        Integer line = Integer.parseInt(authorWithLine[0]);
+        String author = authorWithLine[1];
+
+        String[] dateWithLine = splitColumn(dates.get(i));
+        String date = dateWithLine[1];
+        String formattedDate = DateUtils.formatDate(DateUtils.parseDateTime(date));
+        if (line >= from && line <= to) {
+          if (!started || !group || !isSameCommit(date, previousDate, author, previousAuthor)) {
+            json.name(Integer.toString(line)).beginArray();
+            json.value(author);
+            json.value(formattedDate);
+            json.endArray();
+            started = true;
+          }
+        }
+        previousAuthor = author;
+        previousDate = date;
+      }
+    }
+    json.endObject();
+  }
+
+  private List<String> splitLine(@Nullable String line) {
+    if (line == null) {
+      return Collections.emptyList();
+    }
+    return newArrayList(Splitter.on(";").omitEmptyStrings().split(line));
+  }
+
+  private String[] splitColumn(String column) {
+    return column.split("=");
+  }
+
+  private boolean isSameCommit(String date, String previousDate, String author, String previousAuthor) {
+    return author.equals(previousAuthor) && date.equals(previousDate);
+  }
+}
index 9c919ed5afaabfdc9398950162516dfa4db013b4..0acdcbe82e3851a249f50eb535cf24ccc48a0f0e 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-
 package org.sonar.server.source.ws;
 
-import com.google.common.base.Splitter;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.source.SourceService;
 
-import javax.annotation.Nullable;
-import java.util.Collections;
 import java.util.List;
 
-import static com.google.common.collect.Lists.newArrayList;
-
 public class ShowAction implements RequestHandler {
 
   private final SourceService sourceService;
+  private final ScmWriter scmWriter;
 
-  public ShowAction(SourceService sourceService) {
+  public ShowAction(SourceService sourceService, ScmWriter scmWriter) {
     this.sourceService = sourceService;
+    this.scmWriter = scmWriter;
   }
 
   void define(WebService.NewController controller) {
@@ -73,29 +68,34 @@ public class ShowAction implements RequestHandler {
       .setDescription("Enable loading of SCM information per line")
       .setPossibleValues("true", "false")
       .setDefaultValue("false");
+
+    action
+      .createParam("groupCommits")
+      .setDescription("Group lines by SCM commit. Used only if 'scm' is 'true'")
+      .setPossibleValues("false", "true")
+      .setDefaultValue("true");
   }
 
   @Override
   public void handle(Request request, Response response) {
     String fileKey = request.mandatoryParam("key");
     int from = Math.max(request.paramAsInt("from", 1), 1);
+    int to = request.paramAsInt("to", Integer.MAX_VALUE);
 
-    Integer toParam = request.paramAsInt("to");
-
-    List<String> sourceHtml = sourceService.getLinesAsHtml(fileKey, from, toParam);
+    List<String> sourceHtml = sourceService.getLinesAsHtml(fileKey, from, to);
     if (sourceHtml.isEmpty()) {
       throw new NotFoundException("File '" + fileKey + "' has no sources");
     }
 
-    int to = toParam != null ? toParam : sourceHtml.size() + from;
     JsonWriter json = response.newJsonWriter().beginObject();
     writeSource(sourceHtml, from, json);
 
     if (request.paramAsBoolean("scm", false)) {
       String scmAuthorData = sourceService.getScmAuthorData(fileKey);
       String scmDataData = sourceService.getScmDateData(fileKey);
-      writeScm(scmAuthorData, scmDataData, from, to, json);
+      scmWriter.write(scmAuthorData, scmDataData, from, to, request.paramAsBoolean("groupCommits", true), json);
     }
+
     json.endObject().close();
   }
 
@@ -107,50 +107,4 @@ public class ShowAction implements RequestHandler {
     }
     json.endObject();
   }
-
-  private void writeScm(@Nullable String authorData, @Nullable String scmDateData, int from, int to, JsonWriter json) {
-    if (authorData != null) {
-      json.name("scm").beginObject();
-      List<String> authors = splitLine(authorData);
-      List<String> dates = splitLine(scmDateData);
-
-      String previousAuthor = null;
-      String previousDate = null;
-      boolean scmDataAdded = false;
-      for (int i = 0; i < authors.size(); i++) {
-        String[] authorWithLine = splitColumn(authors.get(i));
-        Integer line = Integer.parseInt(authorWithLine[0]);
-        String author = authorWithLine[1];
-
-        String[] dateWithLine = splitColumn(dates.get(i));
-        String date = dateWithLine[1];
-        String formattedDate = DateUtils.formatDate(DateUtils.parseDateTime(date));
-        if (line >= from && line <= to && (!isSameCommit(date, previousDate, author, previousAuthor) || !scmDataAdded)) {
-          json.name(Integer.toString(line)).beginArray();
-          json.value(author);
-          json.value(formattedDate);
-          json.endArray();
-          scmDataAdded = true;
-        }
-        previousAuthor = author;
-        previousDate = date;
-      }
-      json.endObject();
-    }
-  }
-
-  private boolean isSameCommit(String date, String previousDate, String author, String previousAuthor) {
-    return author.equals(previousAuthor) && date.equals(previousDate);
-  }
-
-  private List<String> splitLine(@Nullable String line) {
-    if (line == null) {
-      return Collections.emptyList();
-    }
-    return newArrayList(Splitter.on(";").omitEmptyStrings().split(line));
-  }
-
-  private String[] splitColumn(String column) {
-    return column.split("=");
-  }
 }
index c1bc2c2cea58b09e3aa28ecb85a00eb71b25d151..d04d656fe113cefd08b62f604a6f67aaa7c569db 100644 (file)
@@ -25,15 +25,18 @@ import org.sonar.api.server.ws.WebService;
 public class SourcesWs implements WebService {
 
   private final ShowAction showAction;
+  private final ScmAction scmAction;
 
-  public SourcesWs(ShowAction showAction) {
+  public SourcesWs(ShowAction showAction, ScmAction scmAction) {
     this.showAction = showAction;
+    this.scmAction = scmAction;
   }
 
   @Override
   public void define(Context context) {
     NewController controller = context.createController("api/sources");
     showAction.define(controller);
+    scmAction.define(controller);
     controller.done();
   }
 }
index 0c91af5e257e6ad6a592f0a56a1e3e6329a16f3c..010f3f19d84eba7a189d81146834769cd04ad5ce 100644 (file)
@@ -117,6 +117,16 @@ public class ListingWs implements WebService {
     writer.beginObject();
     writer.prop("key", param.key());
     writer.prop("description", param.description());
+    writer.prop("required", param.isRequired());
+    writer.prop("defaultValue", param.defaultValue());
+    writer.prop("exampleValue", param.exampleValue());
+    if (param.possibleValues() != null) {
+      writer.name("possibleValues").beginArray();
+      for (String s : param.possibleValues()) {
+        writer.value(s);
+      }
+      writer.endArray();
+    }
     writer.endObject();
   }
 }
diff --git a/sonar-server/src/test/java/org/sonar/server/source/ws/ScmWriterTest.java b/sonar-server/src/test/java/org/sonar/server/source/ws/ScmWriterTest.java
new file mode 100644 (file)
index 0000000..3818012
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.source.ws;
+
+import org.json.JSONException;
+import org.junit.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.sonar.api.utils.text.JsonWriter;
+
+import java.io.StringWriter;
+
+public class ScmWriterTest {
+
+  ScmWriter writer = new ScmWriter();
+
+  @Test
+  public void write_authors_and_dates() throws Exception {
+    // same commit on lines 1 and 2
+    test("1=julien;2=julien;3=simon;", "1=2013-03-13T16:22:31+0100;2=2013-03-13T16:22:31+0100;3=2014-01-01T16:22:31+0100;", 1, Integer.MAX_VALUE, false,
+      "{\"scm\": {\"1\": [\"julien\", \"2013-03-13\"], \"2\": [\"julien\", \"2013-03-13\"], \"3\": [\"simon\", \"2014-01-01\"]}}");
+  }
+
+  @Test
+  public void filter_by_range_of_lines() throws Exception {
+    String authors = "1=julien;2=simon;";
+    String dates = "1=2013-03-13T16:22:31+0100;2=2014-01-01T16:22:31+0100;";
+
+    test(authors, dates, 2, 200, false, "{\"scm\": {\"2\": [\"simon\", \"2014-01-01\"]}}");
+    test(authors, dates, 3, 5, false, "{\"scm\": {}}");
+    test(authors, dates, -2, 1, false, "{\"scm\": {\"1\": [\"julien\", \"2013-03-13\"]}}");
+  }
+
+  @Test
+  public void group_by_commits() throws Exception {
+    // lines 1 and 2 are the same commit, but not 3 (different date)
+    String authors = "1=julien;2=julien;3=julien;4=simon;";
+    String dates = "1=2013-03-13T16:22:31+0100;2=2013-03-13T16:22:31+0100;3=2013-03-14T16:22:31+0100;4=2014-01-01T16:22:31+0100";
+
+    test(authors, dates, 1, Integer.MAX_VALUE, true,
+      "{\"scm\": {\"1\": [\"julien\", \"2013-03-13\"], \"3\": [\"julien\", \"2013-03-14\"], \"4\": [\"simon\", \"2014-01-01\"]}}");
+
+    test(authors, dates, 2, 4, true,
+      "{\"scm\": {\"2\": [\"julien\", \"2013-03-13\"], \"3\": [\"julien\", \"2013-03-14\"], \"4\": [\"simon\", \"2014-01-01\"]}}");
+
+    test(authors, dates, 1, 2, true, "{\"scm\": {\"1\": [\"julien\", \"2013-03-13\"]}}");
+    test(authors, dates, 10, 20, true, "{\"scm\": {}}");
+  }
+
+
+  private void test(String authors, String dates, int from, int to, boolean group, String expected) throws JSONException {
+    StringWriter output = new StringWriter();
+    JsonWriter jsonWriter = JsonWriter.of(output);
+    jsonWriter.beginObject();
+    writer.write(authors, dates, from, to, group, jsonWriter);
+    jsonWriter.endObject();
+    JSONAssert.assertEquals(output.toString(), expected, true);
+  }
+}
index d723c113d071e2ec44d8b9dd180809fc3adadbfc..7e45810dbc3158c4fbb97d74add1c58bfd1dabe5 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-
 package org.sonar.server.source.ws;
 
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.server.ws.WsTester;
+import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.source.SourceService;
+import org.sonar.server.ws.WsTester;
 
+import javax.annotation.Nullable;
 import java.util.Collections;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static org.fest.assertions.Assertions.assertThat;
 import static org.fest.assertions.Fail.fail;
-import static org.mockito.Matchers.*;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-@RunWith(MockitoJUnitRunner.class)
 public class ShowActionTest {
 
-  @Mock
-  SourceService sourceService;
+  SourceService sourceService = mock(SourceService.class);
+  ScmWriter scmWriter = new FakeScmWriter();
 
   WsTester tester;
 
   @Before
   public void setUp() throws Exception {
-    tester = new WsTester(new SourcesWs(new ShowAction(sourceService)));
+    tester = new WsTester(new SourcesWs(new ShowAction(sourceService, scmWriter), new ScmAction(sourceService, scmWriter)));
   }
 
   @Test
@@ -107,7 +107,7 @@ public class ShowActionTest {
   }
 
   @Test
-  public void show_source_with_scm() throws Exception {
+  public void show_source_with_grouped_scm_commits() throws Exception {
     String fileKey = "src/Foo.java";
     when(sourceService.getLinesAsHtml(eq(fileKey), anyInt(), anyInt())).thenReturn(newArrayList(
       "public class <span class=\"sym-31 sym\">HelloWorld</span> {}"
@@ -117,67 +117,27 @@ public class ShowActionTest {
     when(sourceService.getScmDateData(fileKey)).thenReturn("1=2013-03-13T16:22:31+0100;");
 
     WsTester.TestRequest request = tester.newRequest("show").setParam("key", fileKey).setParam("scm", "true");
-    request.execute().assertJson(getClass(), "show_source_with_scm.json");
-  }
-
-  @Test
-  public void show_source_with_scm_with_from_and_to_params() throws Exception {
-    String fileKey = "src/Foo.java";
-    when(sourceService.getLinesAsHtml(fileKey, 3, 5)).thenReturn(newArrayList(
-      " */",
-      "",
-      "public class <span class=\"sym-31 sym\">HelloWorld</span> {"
-    ));
-    when(sourceService.getScmAuthorData(fileKey))
-      .thenReturn("1=julien;2=simon;3=julien;4=simon;5=jean;6=julien");
-    when(sourceService.getScmDateData(fileKey))
-      .thenReturn("1=2013-03-13T16:22:31+0100;2=2013-03-14T16:22:31+0100;3=2013-03-13T16:22:31+0100;4=2013-03-14T16:22:31+0100;5=2013-03-15T16:22:31+0100;6=2013-03-13T16:22:31+0100;");
-
-    WsTester.TestRequest request = tester.newRequest("show")
-      .setParam("key", fileKey)
-      .setParam("from", "3")
-      .setParam("to", "5")
-      .setParam("scm", "true");
-    request.execute().assertJson(getClass(), "show_source_with_scm_with_from_and_to_params.json");
+    request.execute().assertJson(getClass(), "show_source_with_grouped_scm_commits.json");
   }
 
   @Test
-  public void show_source_with_scm_without_repeating_same_lines() throws Exception {
+  public void show_source_with_scm_commits() throws Exception {
     String fileKey = "src/Foo.java";
     when(sourceService.getLinesAsHtml(eq(fileKey), anyInt(), anyInt())).thenReturn(newArrayList(
-      " */",
-      "",
-      "public class <span class=\"sym-31 sym\">HelloWorld</span> {"
+      "public class <span class=\"sym-31 sym\">HelloWorld</span> {}"
     ));
-    when(sourceService.getScmAuthorData(fileKey))
-      .thenReturn("1=julien;2=julien;3=simon");
-    when(sourceService.getScmDateData(fileKey))
-      .thenReturn("1=2013-03-13T16:22:31+0100;2=2013-03-13T16:22:31+0100;3=2013-03-14T16:22:31+0100;");
-    WsTester.TestRequest request = tester.newRequest("show")
-      .setParam("key", fileKey)
-      .setParam("scm", "true");
-    request.execute().assertJson(getClass(), "show_source_with_scm_without_repeating_same_lines.json");
-  }
 
-  @Test
-  public void show_source_with_scm_when_from_is_after_same_commit() throws Exception {
-    String fileKey = "src/Foo.java";
-    when(sourceService.getLinesAsHtml(fileKey, 3, 5)).thenReturn(newArrayList(
-      " */",
-      "",
-      "public class <span class=\"sym-31 sym\">HelloWorld</span> {"
-    ));
+    when(sourceService.getScmAuthorData(fileKey)).thenReturn("1=julien;");
+    when(sourceService.getScmDateData(fileKey)).thenReturn("1=2013-03-13T16:22:31+0100;");
 
-    // Since line 2, it's the same commit
-    when(sourceService.getScmAuthorData(fileKey))
-      .thenReturn("1=julien;2=simon;3=simon;4=simon;5=simon;6=simon");
-    when(sourceService.getScmDateData(fileKey))
-      .thenReturn("1=2013-03-13T16:22:31+0100;2=2013-03-14T16:22:31+0100;3=2013-03-14T16:22:31+0100;4=2013-03-14T16:22:31+0100;5=2013-03-14T16:22:31+0100;6=2013-03-14T16:22:31+0100;");
-    WsTester.TestRequest request = tester.newRequest("show")
-      .setParam("key", fileKey)
-      .setParam("from", "3")
-      .setParam("to", "5")
-      .setParam("scm", "true");
-    request.execute().assertJson(getClass(), "show_source_with_scm_without_repeating_same_lines_and_with_from_param_after_repetition.json");
+    WsTester.TestRequest request = tester.newRequest("show").setParam("key", fileKey).setParam("scm", "true").setParam("groupCommits", "false");
+    request.execute().assertJson(getClass(), "show_source_with_scm_commits.json");
+  }
+
+  class FakeScmWriter extends ScmWriter {
+    @Override
+    void write(@Nullable String authorsData, @Nullable String datesDate, int from, int to, boolean group, JsonWriter json) {
+      json.prop("scm", "done,group=" + group);
+    }
   }
 }
index f7a37a78a46e6c386aa2212cc081cd1b0d35efda..6ddbd9f484545f965c0b89b289f16622eb2f0827 100644 (file)
@@ -30,8 +30,9 @@ import static org.mockito.Mockito.mock;
 
 public class SourcesWsTest {
 
-  ShowAction showAction = new ShowAction(mock(SourceService.class));
-  WsTester tester = new WsTester(new SourcesWs(showAction));
+  ShowAction showAction = new ShowAction(mock(SourceService.class), new ScmWriter());
+  ScmAction scmAction = new ScmAction(mock(SourceService.class), new ScmWriter());
+  WsTester tester = new WsTester(new SourcesWs(showAction, scmAction));
 
   @Test
   public void define_ws() throws Exception {
index 9f6bf16cc7b6de5075b730f5c131e74daaadf4f5..a6525564341bc1b22ef8a34f890c044f841e47a5 100644 (file)
@@ -83,7 +83,13 @@ public class ListingWsTest {
           public void handle(Request request, Response response) {
           }
         });
-      create.createParam("key").setDescription("Key of new metric");
+      create
+        .createParam("severity")
+        .setDescription("Severity")
+        .setRequired(true)
+        .setPossibleValues("BLOCKER", "INFO")
+        .setExampleValue("INFO")
+        .setDefaultValue("BLOCKER");
       create.createParam("name");
       newController.done();
     }
diff --git a/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_grouped_scm_commits.json b/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_grouped_scm_commits.json
new file mode 100644 (file)
index 0000000..ae51626
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "source": {
+    "1": "public class <span class=\"sym-31 sym\">HelloWorld</span> {}"
+  },
+  "scm": "done,group=true"
+}
+
+
+
+
+
+
+
+
diff --git a/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm.json b/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm.json
deleted file mode 100644 (file)
index 6e75309..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "source": {
-    "1": "public class <span class=\"sym-31 sym\">HelloWorld</span> {}"
-  },
-  "scm": {
-    "1": ["julien", "2013-03-13"]
-  }
-}
-
-
-
-
-
-
-
-
diff --git a/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_commits.json b/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_commits.json
new file mode 100644 (file)
index 0000000..99ff3d2
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "source": {
+    "1": "public class <span class=\"sym-31 sym\">HelloWorld</span> {}"
+  },
+  "scm": "done,group=false"
+}
+
+
+
+
+
+
+
+
diff --git a/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_with_from_and_to_params.json b/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_with_from_and_to_params.json
deleted file mode 100644 (file)
index a454052..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "source": {
-    "3": " */",
-    "4": "",
-    "5": "public class <span class=\"sym-31 sym\">HelloWorld</span> {"
-  },
-  "scm": {
-    "3": ["julien", "2013-03-13"],
-    "4": ["simon", "2013-03-14"],
-    "5": ["jean", "2013-03-15"]
-  }
-}
-
-
-
-
-
-
-
-
diff --git a/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_without_repeating_same_lines.json b/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_without_repeating_same_lines.json
deleted file mode 100644 (file)
index ae74340..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "source": {
-    "1": " */",
-    "2": "",
-    "3": "public class <span class=\"sym-31 sym\">HelloWorld</span> {"
-  },
-  "scm": {
-    "1": ["julien", "2013-03-13"],
-    "3": ["simon", "2013-03-14"]
-  }
-}
-
-
-
-
-
-
-
-
diff --git a/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_without_repeating_same_lines_and_with_from_param_after_repetition.json b/sonar-server/src/test/resources/org/sonar/server/source/ws/ShowActionTest/show_source_with_scm_without_repeating_same_lines_and_with_from_param_after_repetition.json
deleted file mode 100644 (file)
index 1f852be..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "source": {
-    "3": " */",
-    "4": "",
-    "5": "public class <span class=\"sym-31 sym\">HelloWorld</span> {"
-  },
-  "scm": {
-    "3": ["simon", "2013-03-14"]
-  }
-}
-
-
-
-
-
-
-
-
index ed4058562c101773cfe4a090ec37eb64f3d5357d..fe48e902ea35058de33afd7a338753e799ea53d2 100644 (file)
           "post": true,
           "params": [
             {
-              "key": "key",
-              "description": "Key of new metric"
+              "key": "name",
+              "required": false
             },
             {
-              "key": "name"
+              "key": "severity",
+              "description": "Severity",
+              "required": true,
+              "defaultValue": "BLOCKER",
+              "exampleValue": "INFO",
+              "possibleValues": ["BLOCKER", "INFO"]
+
             }
           ]
         },