]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9584 Add root project key to response of api/components/search
authorJulien HENRY <julien.henry@sonarsource.com>
Wed, 26 Jul 2017 15:48:32 +0000 (17:48 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Wed, 26 Jul 2017 15:48:32 +0000 (17:48 +0200)
server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDto.java
server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchAction.java
server/sonar-server/src/main/resources/org/sonar/server/component/ws/search-components-example.json
server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchActionTest.java
sonar-ws/src/main/protobuf/ws-components.proto

index 215a248c0c4f66ba118837a7bf8c111496ac2aee..797dfb1f57a52791ebff07f8803d26278a519761 100644 (file)
@@ -60,6 +60,11 @@ public class ComponentDto implements Component {
    */
   private String kee;
 
+  /**
+   * Key of the root component this component belongs to. Consistent with projectUUid.
+   */
+  private String projectKey;
+
   /**
    * Not empty . Max size is 50 (note that effective UUID values are 40 characters with
    * the current algorithm in use). Obviously it is unique.
@@ -221,6 +226,18 @@ public class ComponentDto implements Component {
     return this;
   }
 
+  /**
+   * Return the root project key. On a root project, return itself
+   */
+  public String projectKey() {
+    return projectKey;
+  }
+
+  public ComponentDto setProjectKey(String projectKey) {
+    this.projectKey = projectKey;
+    return this;
+  }
+
   public boolean isRoot() {
     return UUID_PATH_OF_ROOT.equals(uuidPath);
   }
index fecf8cf87158ed1f1d85f5f3e8fb42d6f39f6108..b9939aabb1c2edba2eb5f1aa5ac805c5a57c2285 100644 (file)
 
   <select id="selectByQuery" resultType="Component">
     select
-      <include refid="componentColumns"/>
+      <include refid="componentColumns"/>,
+      root.kee as projectKey
+    from projects p
+    inner join projects root on p.project_uuid=root.uuid and p.organization_uuid=root.organization_uuid
     <include refid="sqlSelectByQuery"/>
     ORDER BY LOWER(p.name), p.name, p.id
   </select>
 
   <select id="countByQuery" resultType="int">
     select count(p.id)
+    from projects p
     <include refid="sqlSelectByQuery"/>
   </select>
 
   <sql id="sqlSelectByQuery">
-    from projects p
     where
       p.enabled=${_true}
       AND p.copy_component_uuid is null
index c9c83436a8e38b1833f5062df0f7a23e05c9f7b2..997131fb86b812e96befde3ed4e1168497490518 100644 (file)
@@ -47,6 +47,7 @@ import static java.util.Collections.emptyList;
 import static java.util.Collections.emptySet;
 import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
 import static org.assertj.guava.api.Assertions.assertThat;
 import static org.sonar.db.component.ComponentTesting.newDirectory;
 import static org.sonar.db.component.ComponentTesting.newFileDto;
@@ -547,7 +548,8 @@ public class ComponentDaoTest {
   @Test
   public void select_provisioned() {
     OrganizationDto organization = db.organizations().insert();
-    ComponentDto provisionedProject = db.components().insertComponent(ComponentTesting.newPrivateProjectDto(organization).setKey("provisioned.project").setName("Provisioned Project"));
+    ComponentDto provisionedProject = db.components()
+      .insertComponent(ComponentTesting.newPrivateProjectDto(organization).setKey("provisioned.project").setName("Provisioned Project"));
     ComponentDto provisionedView = db.components().insertView(organization);
     String projectUuid = db.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(organization)).getComponentUuid();
     String disabledProjectUuid = db.components().insertProjectAndSnapshot(ComponentTesting.newPrivateProjectDto(organization).setEnabled(false)).getComponentUuid();
@@ -966,6 +968,23 @@ public class ComponentDaoTest {
     assertThat(underTest.selectByQuery(dbSession, allProjectsQuery, 0, 10)).extracting(ComponentDto::getKey).containsOnly("public-key", "private-key");
   }
 
+  @Test
+  public void selectByQuery_returns_projectKey() {
+    ComponentDto project = ComponentTesting.newPublicProjectDto(db.getDefaultOrganization()).setKey("project-key");
+    db.components().insertComponent(project);
+    ComponentDto module = ComponentTesting.newModuleDto(project).setKey("module-key");
+    db.components().insertComponent(module);
+    ComponentDto file = ComponentTesting.newFileDto(module).setKey("file-key");
+    db.components().insertComponent(file);
+
+    ComponentQuery allQuery = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.FILE).build();
+
+    assertThat(underTest.selectByQuery(dbSession, allQuery, 0, 10)).extracting(ComponentDto::getKey, ComponentDto::projectKey)
+      .containsOnly(tuple("project-key", "project-key"),
+        tuple("module-key", "project-key"),
+        tuple("file-key", "project-key"));
+  }
+
   @Test
   public void selectByQuery_on_empty_list_of_component_id() {
     ComponentQuery dbQuery = ComponentQuery.builder().setQualifiers(Qualifiers.PROJECT).setComponentIds(emptySet()).build();
index 658de71faa9867ea44410530b2d291a37ad32851..b26ae50b54cbb0a2b1db3837b53d8015f6941ba1 100644 (file)
@@ -46,8 +46,8 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static org.sonar.core.util.Protobuf.setNullable;
 import static org.sonar.server.util.LanguageParamUtils.getExampleValue;
 import static org.sonar.server.util.LanguageParamUtils.getLanguageKeys;
-import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext;
 import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter;
+import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.ACTION_SEARCH;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_LANGUAGE;
@@ -179,6 +179,7 @@ public class SearchAction implements ComponentsWsAction {
       .setOrganization(organization.getKey())
       .setId(dto.uuid())
       .setKey(dto.key())
+      .setProjectKey(dto.projectKey())
       .setName(dto.name())
       .setQualifier(dto.qualifier());
     setNullable(dto.language(), builder::setLanguage);
index dafce93382832c6fb9fa17daf68c886d06e36377..8f86a13f6ed811d5676fbd0e275bdfa29fc3cf57 100644 (file)
@@ -10,7 +10,8 @@
       "id": "directory-uuid",
       "key": "directory-key",
       "qualifier": "DIR",
-      "name": "Directory Name"
+      "name": "Directory Name",
+      "projectKey": "project-key"
     },
     {
       "organization": "my-org-1",
       "key": "file-key",
       "qualifier": "FIL",
       "name": "File Name",
-      "language": "java"
+      "language": "java",
+      "projectKey": "project-key"
     },
     {
       "organization": "my-org-1",
       "id": "module-uuid",
       "key": "module-key",
       "qualifier": "BRC",
-      "name": "Module Name"
+      "name": "Module Name",
+      "projectKey": "project-key"
     },
     {
       "organization": "my-org-1",
       "id": "project-uuid",
       "key": "project-key",
       "qualifier": "TRK",
-      "name": "Project Name"
+      "name": "Project Name",
+      "projectKey": "project-key"
     }
   ]
 }
index 0a22c4c68da69bd8df8adb9d7e34d1218562e27b..ac1651bc67d42a5533fb415c77c9c6b4e0f017ff 100644 (file)
@@ -45,11 +45,14 @@ import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.WsActionTester;
 import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.WsComponents.Component;
 import org.sonarqube.ws.WsComponents.SearchWsResponse;
 import org.sonarqube.ws.client.component.SearchWsRequest;
 
+import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.sonar.api.resources.Qualifiers.DIRECTORY;
@@ -66,7 +69,6 @@ import static org.sonar.db.component.ComponentTesting.newModuleDto;
 import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
 import static org.sonar.db.component.ComponentTesting.newView;
 import static org.sonar.test.JsonAssert.assertJson;
-import static org.sonarqube.ws.WsComponents.Component;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_LANGUAGE;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
@@ -185,6 +187,25 @@ public class SearchActionTest {
     assertThat(response.getComponentsList()).extracting(Component::getKey).containsOnly(file1.getKey(), file2.getKey());
   }
 
+  @Test
+  public void return_project_key() throws IOException {
+    ComponentDto project = ComponentTesting.newPublicProjectDto(db.getDefaultOrganization());
+    ComponentDto module = ComponentTesting.newModuleDto(project);
+    ComponentDto file1 = newFileDto(module).setKey("file1");
+    ComponentDto file2 = newFileDto(module).setKey("file2");
+    ComponentDto file3 = newFileDto(project).setKey("file3");
+    db.components().insertComponents(project, module, file1, file2, file3);
+
+    SearchWsResponse response = call(new SearchWsRequest().setQualifiers(asList(PROJECT, MODULE, FILE)));
+
+    assertThat(response.getComponentsList()).extracting(Component::getKey, Component::getProjectKey)
+      .containsOnly(tuple(project.getKey(), project.getKey()),
+        tuple(module.getKey(), project.getKey()),
+        tuple(file1.getKey(), project.getKey()),
+        tuple(file2.getKey(), project.getKey()),
+        tuple(file3.getKey(), project.getKey()));
+  }
+
   @Test
   public void do_not_verify_permissions_if_user_is_root() throws IOException {
     OrganizationDto org = db.organizations().insert();
index 58b02d9687c265f9efbb7eb61e62c79444a033e4..4a7fe369ced224568af4405746a3b1d5565c49a0 100644 (file)
@@ -118,6 +118,8 @@ message Component {
   optional Tags tags = 14;
   optional string visibility = 15;
   optional string leakPeriodDate = 16;
+  // Root project key
+  optional string projectKey = 17;
 
   message Tags {
     repeated string tags = 1;