aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-webapi
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2023-03-27 15:44:00 -0500
committersonartech <sonartech@sonarsource.com>2023-04-04 20:03:16 +0000
commit3f602a70548d285d61d0295b704aa18a3b8314b8 (patch)
tree3a59c6ee1f0898c12af24bc12bf94b869b6feed6 /server/sonar-webserver-webapi
parent02f358bec4d5636d8c23bf34d4d086b0405f65cf (diff)
downloadsonarqube-3f602a70548d285d61d0295b704aa18a3b8314b8.tar.gz
sonarqube-3f602a70548d285d61d0295b704aa18a3b8314b8.zip
SONAR-18860 Refactor usage of main_branch_project_uuid to use branch is_main flag in webserver-webapi module
Diffstat (limited to 'server/sonar-webserver-webapi')
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentCleanerServiceIT.java17
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/SearchActionIT.java2
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/BulkDeleteActionIT.java4
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/setting/ws/ValuesActionIT.java10
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/ShowActionIT.java3
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java18
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentFinder.java39
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java4
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ShowAction.java44
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/TreeAction.java20
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java12
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java70
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java2
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java6
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java13
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java15
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/BulkDeleteAction.java6
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/ValuesAction.java45
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/source/ws/LinesAction.java6
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java32
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java8
21 files changed, 205 insertions, 171 deletions
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentCleanerServiceIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentCleanerServiceIT.java
index 51fca49833f..8a27c0aca4a 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentCleanerServiceIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentCleanerServiceIT.java
@@ -86,33 +86,26 @@ public class ComponentCleanerServiceIT {
}
@Test
- public void delete_list_of_components_from_db() {
+ public void delete_component_from_db() {
ComponentDto componentDto1 = db.components().insertPublicProject();
ComponentDto componentDto2 = db.components().insertPublicProject();
- ComponentDto componentDto3 = db.components().insertPublicProject();
mockResourceTypeAsValidProject();
- underTest.deleteComponents(dbSession, asList(componentDto1, componentDto2));
+ underTest.deleteComponent(dbSession, componentDto1);
dbSession.commit();
assertNotExists(componentDto1);
- assertNotExists(componentDto2);
- assertExists(componentDto3);
+ assertExists(componentDto2);
}
@Test
public void fail_with_IAE_if_project_non_deletable() {
ComponentDto componentDto1 = db.components().insertPublicProject();
- ComponentDto componentDto2 = db.components().insertPublicProject();
-
mockResourceTypeAsNonDeletable();
-
dbSession.commit();
- List<ComponentDto> componentDtos = asList(componentDto1, componentDto2);
-
- assertThatThrownBy(() -> underTest.deleteComponents(dbSession, componentDtos))
+ assertThatThrownBy(() -> underTest.deleteComponent(dbSession, componentDto1))
.withFailMessage("Only projects can be deleted")
.isInstanceOf(IllegalArgumentException.class);
}
@@ -187,7 +180,7 @@ public class ComponentCleanerServiceIT {
dbClient.componentDao().insertOnMainBranch(dbSession, file);
dbSession.commit();
- assertThatThrownBy(() -> underTest.delete(dbSession, file))
+ assertThatThrownBy(() -> underTest.deleteComponent(dbSession, file))
.isInstanceOf(IllegalArgumentException.class);
}
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/SearchActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/SearchActionIT.java
index 7201714ab10..96933397589 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/SearchActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/SearchActionIT.java
@@ -337,7 +337,7 @@ public class SearchActionIT {
assertThatThrownBy(request::execute)
.isInstanceOf(NotFoundException.class)
- .hasMessage("Component key '%s' not found", key);
+ .hasMessage("Project '%s' not found", key);
}
@Test
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/BulkDeleteActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/BulkDeleteActionIT.java
index 099d3fd16ae..be5985198c8 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/BulkDeleteActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/BulkDeleteActionIT.java
@@ -230,7 +230,7 @@ public class BulkDeleteActionIT {
.setParam("projects", StringUtils.join(keys, ","))
.execute();
- verify(componentCleanerService, times(1_000)).delete(any(DbSession.class), any(ComponentDto.class));
+ verify(componentCleanerService, times(1_000)).deleteComponent(any(DbSession.class), any(ComponentDto.class));
ArgumentCaptor<Set<Project>> projectsCaptor = ArgumentCaptor.forClass(Set.class);
verify(projectLifeCycleListeners).onProjectsDeleted(projectsCaptor.capture());
assertThat(projectsCaptor.getValue()).hasSize(1_000);
@@ -306,7 +306,7 @@ public class BulkDeleteActionIT {
private void verifyComponentDeleted(ComponentDto... projects) {
ArgumentCaptor<ComponentDto> argument = ArgumentCaptor.forClass(ComponentDto.class);
- verify(componentCleanerService, times(projects.length)).delete(any(DbSession.class), argument.capture());
+ verify(componentCleanerService, times(projects.length)).deleteComponent(any(DbSession.class), argument.capture());
for (ComponentDto project : projects) {
assertThat(argument.getAllValues()).extracting(ComponentDto::uuid).contains(project.uuid());
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/setting/ws/ValuesActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/setting/ws/ValuesActionIT.java
index d80a7117d52..1906ad4bde8 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/setting/ws/ValuesActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/setting/ws/ValuesActionIT.java
@@ -335,28 +335,28 @@ public class ValuesActionIT {
}
@Test
- public void return_inherited_values_on_module() {
+ public void return_inherited_values_on_component() {
logInAsProjectUser();
ComponentDto file = db.components().insertComponent(newFileDto(project));
definitions.addComponents(asList(
PropertyDefinition.builder("defaultProperty").defaultValue("default").onQualifiers(PROJECT).build(),
PropertyDefinition.builder("globalProperty").onQualifiers(PROJECT).build(),
PropertyDefinition.builder("projectProperty").onQualifiers(PROJECT).build(),
- PropertyDefinition.builder("moduleProperty").onQualifiers(PROJECT).build()));
+ PropertyDefinition.builder("componentProperty").onQualifiers(PROJECT).build()));
db.properties().insertProperties(null, null, null, null,
newGlobalPropertyDto().setKey("globalProperty").setValue("global"));
db.properties().insertProperties(null, project.getKey(), project.name(), project.qualifier(),
newComponentPropertyDto(project).setKey("projectProperty").setValue("project"));
db.properties().insertProperties(null, file.getKey(), file.name(), file.qualifier(),
- newComponentPropertyDto(file).setKey("moduleProperty").setValue("module"));
+ newComponentPropertyDto(file).setKey("componentProperty").setValue("component"));
- ValuesWsResponse result = executeRequestForComponentProperties(file, "defaultProperty", "globalProperty", "projectProperty", "moduleProperty");
+ ValuesWsResponse result = executeRequestForComponentProperties(file, "defaultProperty", "globalProperty", "projectProperty", "componentProperty");
assertThat(result.getSettingsList()).hasSize(4);
assertSetting(result.getSettings(0), "defaultProperty", "default", true);
assertSetting(result.getSettings(1), "globalProperty", "global", true);
assertSetting(result.getSettings(2), "projectProperty", "project", true);
- assertSetting(result.getSettings(3), "moduleProperty", "module", false);
+ assertSetting(result.getSettings(3), "componentProperty", "component", false);
}
@Test
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/ShowActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/ShowActionIT.java
index ee50e82fe5e..efbbffdfaf6 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/ShowActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/source/ws/ShowActionIT.java
@@ -27,6 +27,7 @@ import org.sonar.api.resources.Qualifiers;
import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.component.BranchDao;
import org.sonar.db.component.ComponentDao;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
@@ -54,6 +55,7 @@ public class ShowActionIT {
private DbClient dbClient = mock(DbClient.class);
private DbSession session = mock(DbSession.class);
private ComponentDao componentDao = mock(ComponentDao.class);
+ private BranchDao branchDao = mock(BranchDao.class);
private ComponentDto project = ComponentTesting.newPrivateProjectDto();
private ComponentDto file = ComponentTesting.newFileDto(project);
private ShowAction underTest = new ShowAction(sourceService, dbClient, userSessionRule,
@@ -63,6 +65,7 @@ public class ShowActionIT {
@Before
public void setUp() {
when(dbClient.componentDao()).thenReturn(componentDao);
+ when(dbClient.branchDao()).thenReturn(branchDao);
when(dbClient.openSession(false)).thenReturn(session);
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java
index 7557eaaa0df..435bd6dc4e8 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java
@@ -54,12 +54,6 @@ public class ComponentCleanerService {
}
}
- public void deleteComponents(DbSession dbSession, List<ComponentDto> components) {
- for (ComponentDto component : components) {
- delete(dbSession, component);
- }
- }
-
public void deleteBranch(DbSession dbSession, BranchDto branch) {
dbClient.purgeDao().deleteBranch(dbSession, branch.getUuid());
projectIndexers.commitAndIndexBranches(dbSession, singletonList(branch), PROJECT_DELETION);
@@ -78,12 +72,12 @@ public class ComponentCleanerService {
projectIndexers.commitAndIndexProjects(dbSession, singletonList(application), PROJECT_DELETION);
}
- public void delete(DbSession dbSession, ComponentDto project) {
- checkArgument(hasProjectScope(project) && isDeletable(project) && project.getMainBranchProjectUuid() == null, "Only projects can be deleted");
- dbClient.purgeDao().deleteProject(dbSession, project.uuid(), project.qualifier(), project.name(), project.getKey());
- dbClient.userDao().cleanHomepage(dbSession, project);
- dbClient.userTokenDao().deleteByProjectKey(dbSession, project.getKey());
- projectIndexers.commitAndIndexComponents(dbSession, singletonList(project), PROJECT_DELETION);
+ public void deleteComponent(DbSession dbSession, ComponentDto component) {
+ checkArgument(hasProjectScope(component) && isDeletable(component), "Only projects can be deleted");
+ dbClient.purgeDao().deleteProject(dbSession, component.uuid(), component.qualifier(), component.name(), component.getKey());
+ dbClient.userDao().cleanHomepage(dbSession, component);
+ dbClient.userTokenDao().deleteByProjectKey(dbSession, component.getKey());
+ projectIndexers.commitAndIndexComponents(dbSession, singletonList(component), PROJECT_DELETION);
}
private static boolean hasProjectScope(ComponentDto project) {
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentFinder.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentFinder.java
index 3ed37818c31..ef9394061c1 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentFinder.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentFinder.java
@@ -113,6 +113,30 @@ public class ComponentFinder {
return getBranchOrPullRequest(dbSession, project.getUuid(), project.getKey(), branchKey, pullRequestKey);
}
+ public ProjectAndBranch getAppOrProjectAndBranch(DbSession dbSession, String projectKey, @Nullable String branchKey, @Nullable String pullRequestKey) {
+ ProjectDto projectOrApp = getProjectOrApplicationByKey(dbSession, projectKey);
+ BranchDto branch = getBranchOrPullRequest(dbSession, projectOrApp, branchKey, pullRequestKey);
+ return new ProjectAndBranch(projectOrApp, branch);
+ }
+
+ public static class ProjectAndBranch {
+ private final ProjectDto project;
+ private final BranchDto branch;
+
+ public ProjectAndBranch(ProjectDto project, BranchDto branch) {
+ this.project = project;
+ this.branch = branch;
+ }
+
+ public ProjectDto getProject() {
+ return project;
+ }
+
+ public BranchDto getBranch() {
+ return branch;
+ }
+ }
+
public BranchDto getBranchOrPullRequest(DbSession dbSession, String projectUuid, String projectKey, @Nullable String branchKey, @Nullable String pullRequestKey) {
if (branchKey != null) {
return dbClient.branchDao().selectByBranchKey(dbSession, projectUuid, branchKey)
@@ -139,23 +163,22 @@ public class ComponentFinder {
}
private ComponentDto getByKey(DbSession dbSession, String key, String label) {
- return checkComponent(dbClient.componentDao().selectByKey(dbSession, key), "%s key '%s' not found", label, key);
+ return checkComponent(dbSession, dbClient.componentDao().selectByKey(dbSession, key), "%s key '%s' not found", label, key);
}
- /**
- * This method only returns components in main branches.
- */
public ComponentDto getByUuidFromMainBranch(DbSession dbSession, String uuid) {
return getByUuidFromMainBranch(dbSession, uuid, LABEL_COMPONENT);
}
private ComponentDto getByUuidFromMainBranch(DbSession dbSession, String uuid, String label) {
- return checkComponent(dbClient.componentDao().selectByUuid(dbSession, uuid), "%s id '%s' not found", label, uuid);
+ return checkComponent(dbSession, dbClient.componentDao().selectByUuid(dbSession, uuid), "%s id '%s' not found", label, uuid);
}
- private static ComponentDto checkComponent(Optional<ComponentDto> componentDto, String message, Object... messageArguments) {
- if (componentDto.isPresent() && componentDto.get().isEnabled() && componentDto.get().getMainBranchProjectUuid() == null) {
- return componentDto.get();
+ private ComponentDto checkComponent(DbSession session, Optional<ComponentDto> componentDto, String message, Object... messageArguments) {
+ if (componentDto.isPresent() && componentDto.get().isEnabled()) {
+ if (dbClient.branchDao().selectByUuid(session, componentDto.get().branchUuid()).map(BranchDto::isMain).orElse(true)) {
+ return componentDto.get();
+ }
}
throw new NotFoundException(format(message, messageArguments));
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java
index 45a3b0c4285..8054a7745d0 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ComponentDtoToWsComponent.java
@@ -66,7 +66,7 @@ class ComponentDtoToWsComponent {
}
public static Components.Component.Builder componentDtoToWsComponent(ComponentDto dto, @Nullable ProjectDto parentProjectDto,
- @Nullable SnapshotDto lastAnalysis, @Nullable String branch, @Nullable String pullRequest) {
+ @Nullable SnapshotDto lastAnalysis, boolean isMainBranch, @Nullable String branch, @Nullable String pullRequest) {
Components.Component.Builder wsComponent = Components.Component.newBuilder()
.setKey(ComponentDto.removeBranchAndPullRequestFromKey(dto.getKey()))
.setName(dto.name())
@@ -84,7 +84,7 @@ class ComponentDtoToWsComponent {
});
if (QUALIFIERS_WITH_VISIBILITY.contains(dto.qualifier())) {
wsComponent.setVisibility(Visibility.getLabel(dto.isPrivate()));
- if (Arrays.asList(Qualifiers.PROJECT, Qualifiers.APP).contains(dto.qualifier()) && dto.getMainBranchProjectUuid() != null && parentProjectDto != null) {
+ if (Arrays.asList(Qualifiers.PROJECT, Qualifiers.APP).contains(dto.qualifier()) && parentProjectDto != null && isMainBranch) {
wsComponent.getTagsBuilder().addAllTags(parentProjectDto.getTags());
}
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ShowAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ShowAction.java
index fa8b9de4696..277718f66ef 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ShowAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/ShowAction.java
@@ -43,7 +43,6 @@ import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Components;
import org.sonarqube.ws.Components.ShowWsResponse;
-import static java.util.Optional.ofNullable;
import static org.sonar.server.component.ws.ComponentDtoToWsComponent.componentDtoToWsComponent;
import static org.sonar.server.component.ws.ComponentDtoToWsComponent.projectOrAppToWsComponent;
import static org.sonar.server.component.ws.MeasuresWsParameters.PARAM_BRANCH;
@@ -143,30 +142,37 @@ public class ShowAction implements ComponentsWsAction {
private Components.Component.Builder toWsComponent(DbSession dbSession, ComponentDto component, @Nullable SnapshotDto lastAnalysis,
Request request) {
+
+ // project or application
if (isProjectOrApp(component)) {
ProjectDto project = dbClient.projectDao().selectProjectOrAppByKey(dbSession, component.getKey())
.orElseThrow(() -> new IllegalStateException("Project is in invalid state."));
boolean needIssueSync = needIssueSync(dbSession, component, project);
- return projectOrAppToWsComponent(project, lastAnalysis)
+ return projectOrAppToWsComponent(project, lastAnalysis).setNeedIssueSync(needIssueSync);
+ }
+
+ // parent project can an application. For components in portfolios, it will be null
+ ProjectDto parentProject = dbClient.projectDao().selectByBranchUuid(dbSession, component.branchUuid()).orElse(null);
+ boolean needIssueSync = needIssueSync(dbSession, component, parentProject);
+
+ // if this is a project calculated in a portfolio or app, we need to include the original branch name (if any)
+ if (component.getCopyComponentUuid() != null) {
+ String branch = dbClient.branchDao().selectByUuid(dbSession, component.getCopyComponentUuid())
+ .filter(b -> !b.isMain())
+ .map(BranchDto::getKey)
+ .orElse(null);
+ return componentDtoToWsComponent(component, parentProject, lastAnalysis, true, branch, null)
+ .setNeedIssueSync(needIssueSync);
+ }
+
+ // branch won't exist for portfolios
+ Optional<BranchDto> branchDto = dbClient.branchDao().selectByUuid(dbSession, component.branchUuid());
+ if (branchDto.isPresent() && !branchDto.get().isMain()) {
+ return componentDtoToWsComponent(component, parentProject, lastAnalysis, false, request.branch, request.pullRequest)
.setNeedIssueSync(needIssueSync);
} else {
- Optional<ProjectDto> parentProject = dbClient.projectDao().selectByUuid(dbSession,
- ofNullable(component.getMainBranchProjectUuid()).orElse(component.branchUuid()));
- boolean needIssueSync = needIssueSync(dbSession, component, parentProject.orElse(null));
- if (component.getCopyComponentUuid() != null) {
- String branch = dbClient.branchDao().selectByUuid(dbSession, component.getCopyComponentUuid())
- .filter(b -> !b.isMain())
- .map(BranchDto::getKey)
- .orElse(null);
- return componentDtoToWsComponent(component, parentProject.orElse(null), lastAnalysis, branch, null)
- .setNeedIssueSync(needIssueSync);
- } else if (component.getMainBranchProjectUuid() != null) {
- return componentDtoToWsComponent(component, parentProject.orElse(null), lastAnalysis, request.branch, request.pullRequest)
- .setNeedIssueSync(needIssueSync);
- } else {
- return componentDtoToWsComponent(component, parentProject.orElse(null), lastAnalysis, null, null)
- .setNeedIssueSync(needIssueSync);
- }
+ return componentDtoToWsComponent(component, parentProject, lastAnalysis, true, null, null)
+ .setNeedIssueSync(needIssueSync);
}
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/TreeAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/TreeAction.java
index 1cbba6819d9..1f786a346cb 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/TreeAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/TreeAction.java
@@ -233,33 +233,33 @@ public class TreeAction implements ComponentsWsAction {
.filter(b -> !b.isMain())
.collect(Collectors.toMap(BranchDto::getUuid, BranchDto::getBranchKey));
- response.setBaseComponent(toWsComponent(dbSession, baseComponent, referenceComponentsByUuid, branchKeyByReferenceUuid, request));
+ boolean isMainBranch = dbClient.branchDao().selectByUuid(dbSession, baseComponent.branchUuid()).map(BranchDto::isMain).orElse(true);
+ response.setBaseComponent(toWsComponent(dbSession, baseComponent, isMainBranch, referenceComponentsByUuid, branchKeyByReferenceUuid, request));
for (ComponentDto dto : components) {
- response.addComponents(toWsComponent(dbSession, dto, referenceComponentsByUuid, branchKeyByReferenceUuid, request));
+ response.addComponents(toWsComponent(dbSession, dto, isMainBranch, referenceComponentsByUuid, branchKeyByReferenceUuid, request));
}
return response.build();
}
- private Components.Component.Builder toWsComponent(DbSession dbSession, ComponentDto component,
+ private Components.Component.Builder toWsComponent(DbSession dbSession, ComponentDto component, boolean isMainBranch,
Map<String, ComponentDto> referenceComponentsByUuid, Map<String, String> branchKeyByReferenceUuid, Request request) {
ComponentDto referenceComponent = referenceComponentsByUuid.get(component.getCopyComponentUuid());
Components.Component.Builder wsComponent;
- if (component.getMainBranchProjectUuid() == null && component.isRootProject() && PROJECT_OR_APP_QUALIFIERS.contains(component.qualifier())) {
+ if (isMainBranch && component.isRootProject() && PROJECT_OR_APP_QUALIFIERS.contains(component.qualifier())) {
ProjectDto projectDto = componentFinder.getProjectOrApplicationByKey(dbSession, component.getKey());
wsComponent = projectOrAppToWsComponent(projectDto, null);
} else {
- Optional<ProjectDto> parentProject = dbClient.projectDao().selectByUuid(dbSession,
- ofNullable(component.getMainBranchProjectUuid()).orElse(component.branchUuid()));
+ ProjectDto parentProject = dbClient.projectDao().selectByBranchUuid(dbSession, component.branchUuid()).orElse(null);
if (referenceComponent != null) {
- wsComponent = componentDtoToWsComponent(component, parentProject.orElse(null), null, branchKeyByReferenceUuid.get(referenceComponent.uuid()), null);
- } else if (component.getMainBranchProjectUuid() != null) {
- wsComponent = componentDtoToWsComponent(component, parentProject.orElse(null), null, request.branch, request.pullRequest);
+ wsComponent = componentDtoToWsComponent(component, parentProject, null, false, branchKeyByReferenceUuid.get(referenceComponent.uuid()), null);
+ } else if (!isMainBranch) {
+ wsComponent = componentDtoToWsComponent(component, parentProject, null, false, request.branch, request.pullRequest);
} else {
- wsComponent = componentDtoToWsComponent(component, parentProject.orElse(null), null, null, null);
+ wsComponent = componentDtoToWsComponent(component, parentProject, null, true, null, null);
}
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java
index 5ec0692777a..31b961e38e0 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/AssignAction.java
@@ -30,8 +30,8 @@ import org.sonar.core.issue.IssueChangeContext;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
import org.sonar.db.issue.IssueDto;
+import org.sonar.db.project.ProjectDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.ws.IssueUpdater;
@@ -135,11 +135,11 @@ public class AssignAction implements HotspotsWsAction {
return checkFound(dbClient.userDao().selectActiveUserByLogin(dbSession, assignee), "Unknown user: %s", assignee);
}
- private void checkAssigneeProjectPermission(DbSession dbSession, UserDto assignee, String issueProjectUuid) {
- ComponentDto componentDto = checkFoundWithOptional(dbClient.componentDao().selectByUuid(dbSession, issueProjectUuid),
- "Could not find project for issue");
- String mainProjectUuid = componentDto.getMainBranchProjectUuid() == null ? componentDto.uuid() : componentDto.getMainBranchProjectUuid();
- if (componentDto.isPrivate() && !hasProjectPermission(dbSession, assignee.getUuid(), mainProjectUuid)) {
+ private void checkAssigneeProjectPermission(DbSession dbSession, UserDto assignee, String issueBranchUuid) {
+ ProjectDto project = checkFoundWithOptional(dbClient.projectDao().selectByBranchUuid(dbSession, issueBranchUuid),
+ "Could not find branch for issue");
+
+ if (project.isPrivate() && !hasProjectPermission(dbSession, assignee.getUuid(), project.getUuid())) {
throw new IllegalArgumentException(String.format("Provided user with login '%s' does not have 'Browse' permission to project", assignee.getLogin()));
}
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java
index 590d9bd5ce0..e7edae1e7f7 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java
@@ -38,7 +38,6 @@ import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.jetbrains.annotations.NotNull;
import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Scopes;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleType;
import org.sonar.api.server.ws.Change;
@@ -57,6 +56,7 @@ import org.sonar.db.project.ProjectDto;
import org.sonar.db.protobuf.DbIssues;
import org.sonar.db.rule.RuleDto;
import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.component.ComponentFinder.ProjectAndBranch;
import org.sonar.server.es.SearchOptions;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.TextRangeResponseFormatter;
@@ -70,7 +70,6 @@ import org.sonarqube.ws.Common;
import org.sonarqube.ws.Hotspots;
import org.sonarqube.ws.Hotspots.SearchWsResponse;
-import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
@@ -179,7 +178,7 @@ public class SearchAction implements HotspotsWsAction {
validateParameters(wsRequest);
try (DbSession dbSession = dbClient.openSession(false)) {
checkIfNeedIssueSync(dbSession, wsRequest);
- Optional<ComponentDto> project = getAndValidateProjectOrApplication(dbSession, wsRequest);
+ Optional<ProjectAndBranch> project = getAndValidateProjectOrApplication(dbSession, wsRequest);
SearchResponseData searchResponseData = searchHotspots(wsRequest, dbSession, project.orElse(null));
loadComponents(dbSession, searchResponseData);
loadRules(dbSession, searchResponseData);
@@ -327,24 +326,22 @@ public class SearchAction implements HotspotsWsAction {
action.setResponseExample(getClass().getResource("search-example.json"));
}
- private Optional<ComponentDto> getAndValidateProjectOrApplication(DbSession dbSession, WsRequest wsRequest) {
+ private Optional<ProjectAndBranch> getAndValidateProjectOrApplication(DbSession dbSession, WsRequest wsRequest) {
return wsRequest.getProjectKey().map(projectKey -> {
- ComponentDto project = getProject(dbSession, projectKey, wsRequest.getBranch().orElse(null), wsRequest.getPullRequest().orElse(null));
- if (!Scopes.PROJECT.equals(project.scope()) || !SUPPORTED_QUALIFIERS.contains(project.qualifier()) || !project.isEnabled()) {
+ ProjectAndBranch appOrProjectAndBranch = componentFinder.getAppOrProjectAndBranch(dbSession, projectKey, wsRequest.getBranch().orElse(null),
+ wsRequest.getPullRequest().orElse(null));
+
+ if (!SUPPORTED_QUALIFIERS.contains(appOrProjectAndBranch.getProject().getQualifier())) {
throw new NotFoundException(format("Project '%s' not found", projectKey));
}
- userSession.checkComponentPermission(USER, project);
- userSession.checkChildProjectsPermission(USER, project);
- return project;
+ userSession.checkProjectPermission(USER, appOrProjectAndBranch.getProject());
+ userSession.checkChildProjectsPermission(USER, appOrProjectAndBranch.getProject());
+ return appOrProjectAndBranch;
});
}
- private ComponentDto getProject(DbSession dbSession, String projectKey, @Nullable String branch, @Nullable String pullRequest) {
- return componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, projectKey, branch, pullRequest);
- }
-
- private SearchResponseData searchHotspots(WsRequest wsRequest, DbSession dbSession, @Nullable ComponentDto project) {
- SearchResponse result = doIndexSearch(wsRequest, dbSession, project);
+ private SearchResponseData searchHotspots(WsRequest wsRequest, DbSession dbSession, @Nullable ProjectAndBranch projectorApp) {
+ SearchResponse result = doIndexSearch(wsRequest, dbSession, projectorApp);
List<String> issueKeys = Arrays.stream(result.getHits().getHits())
.map(SearchHit::getId)
.collect(toList(result.getHits().getHits().length));
@@ -371,28 +368,29 @@ public class SearchAction implements HotspotsWsAction {
.toList();
}
- private SearchResponse doIndexSearch(WsRequest wsRequest, DbSession dbSession, @Nullable ComponentDto project) {
+ private SearchResponse doIndexSearch(WsRequest wsRequest, DbSession dbSession, @Nullable ProjectAndBranch projectOrAppAndBranch) {
var builder = IssueQuery.builder()
.types(singleton(RuleType.SECURITY_HOTSPOT.name()))
.sort(IssueQuery.SORT_HOTSPOTS)
.asc(true)
.statuses(wsRequest.getStatus().map(Collections::singletonList).orElse(STATUSES));
- if (project != null) {
- String projectUuid = firstNonNull(project.getMainBranchProjectUuid(), project.uuid());
- if (Qualifiers.APP.equals(project.qualifier())) {
- builder.viewUuids(singletonList(projectUuid));
+ if (projectOrAppAndBranch != null) {
+ ProjectDto projectOrApp = projectOrAppAndBranch.getProject();
+
+ if (Qualifiers.APP.equals(projectOrApp.getQualifier())) {
+ builder.viewUuids(singletonList(projectOrApp.getUuid()));
if (wsRequest.isInNewCodePeriod() && wsRequest.getPullRequest().isEmpty()) {
- addInNewCodePeriodFilterByProjects(builder, dbSession, project);
+ addInNewCodePeriodFilterByProjects(builder, dbSession, projectOrAppAndBranch.getBranch());
}
} else {
- builder.projectUuids(singletonList(projectUuid));
+ builder.projectUuids(singletonList(projectOrApp.getUuid()));
if (wsRequest.isInNewCodePeriod() && wsRequest.getPullRequest().isEmpty()) {
- addInNewCodePeriodFilter(dbSession, project, builder);
+ addInNewCodePeriodFilter(dbSession, projectOrApp, builder);
}
}
- addMainBranchFilter(project, builder);
+ addMainBranchFilter(projectOrAppAndBranch.getBranch(), builder);
}
if (!wsRequest.getHotspotKeys().isEmpty()) {
@@ -458,17 +456,17 @@ public class SearchAction implements HotspotsWsAction {
}
}
- private static void addMainBranchFilter(@NotNull ComponentDto project, IssueQuery.Builder builder) {
- if (project.getMainBranchProjectUuid() == null) {
+ private static void addMainBranchFilter(@NotNull BranchDto branch, IssueQuery.Builder builder) {
+ if (branch.isMain()) {
builder.mainBranch(true);
} else {
- builder.branchUuid(project.uuid());
+ builder.branchUuid(branch.getUuid());
builder.mainBranch(false);
}
}
- private void addInNewCodePeriodFilter(DbSession dbSession, @NotNull ComponentDto project, IssueQuery.Builder builder) {
- Optional<SnapshotDto> snapshot = dbClient.snapshotDao().selectLastAnalysisByComponentUuid(dbSession, project.uuid());
+ private void addInNewCodePeriodFilter(DbSession dbSession, @NotNull ProjectDto project, IssueQuery.Builder builder) {
+ Optional<SnapshotDto> snapshot = dbClient.snapshotDao().selectLastAnalysisByComponentUuid(dbSession, project.getUuid());
boolean isLastAnalysisUsingReferenceBranch = snapshot.map(SnapshotDto::getPeriodMode)
.orElse("").equals(REFERENCE_BRANCH.name());
@@ -484,21 +482,23 @@ public class SearchAction implements HotspotsWsAction {
}
}
- private void addInNewCodePeriodFilterByProjects(IssueQuery.Builder builder, DbSession dbSession, ComponentDto application) {
- Set<String> projectUuids;
- if (application.getMainBranchProjectUuid() == null) {
- projectUuids = dbClient.applicationProjectsDao().selectProjects(dbSession, application.uuid()).stream()
+ private void addInNewCodePeriodFilterByProjects(IssueQuery.Builder builder, DbSession dbSession, BranchDto appBranch) {
+ Set<String> branchUuids;
+
+ if (appBranch.isMain()) {
+ // TODO assuming project uuid matches main branch uuid
+ branchUuids = dbClient.applicationProjectsDao().selectProjects(dbSession, appBranch.getProjectUuid()).stream()
.map(ProjectDto::getUuid)
.collect(Collectors.toSet());
} else {
- projectUuids = dbClient.applicationProjectsDao().selectProjectBranchesFromAppBranchUuid(dbSession, application.uuid()).stream()
+ branchUuids = dbClient.applicationProjectsDao().selectProjectBranchesFromAppBranchUuid(dbSession, appBranch.getUuid()).stream()
.map(BranchDto::getUuid)
.collect(Collectors.toSet());
}
long now = system2.now();
- List<SnapshotDto> snapshots = dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids);
+ List<SnapshotDto> snapshots = dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, branchUuids);
Set<String> newCodeReferenceByProjects = snapshots
.stream()
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java
index d284e60e318..96c6a7a3968 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/LiveMeasureComputerImpl.java
@@ -97,8 +97,8 @@ public class LiveMeasureComputerImpl implements LiveMeasureComputer {
}
BranchDto branch = loadBranch(dbSession, branchComponent);
- Configuration config = projectConfigurationLoader.loadProjectConfiguration(dbSession, branch);
ProjectDto project = loadProject(dbSession, branch.getProjectUuid());
+ Configuration config = projectConfigurationLoader.loadBranchConfiguration(dbSession, branch);
QualityGate qualityGate = qGateComputer.loadQualityGate(dbSession, project, branch);
MeasureMatrix matrix = loadMeasureMatrix(dbSession, components.getAllUuids(), qualityGate);
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
index c4129a81e7f..8f325fd6553 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
@@ -165,7 +165,7 @@ public class ComponentAction implements MeasuresWsAction {
Optional<Measures.Period> period = snapshotToWsPeriods(analysis);
Optional<RefComponent> reference = getReference(dbSession, component);
- return buildResponse(request, component, reference, measuresByMetric, metrics, period);
+ return buildResponse(dbSession, request, component, reference, measuresByMetric, metrics, period);
}
}
@@ -246,10 +246,9 @@ public class ComponentAction implements MeasuresWsAction {
return refBranch.map(rb -> new RefComponent(rb, refComponent.get()));
}
- private static ComponentWsResponse buildResponse(ComponentRequest request, ComponentDto component, Optional<RefComponent> reference,
+ private ComponentWsResponse buildResponse(DbSession dbSession, ComponentRequest request, ComponentDto component, Optional<RefComponent> reference,
Map<MetricDto, LiveMeasureDto> measuresByMetric, Collection<MetricDto> metrics, Optional<Measures.Period> period) {
ComponentWsResponse.Builder response = ComponentWsResponse.newBuilder();
- boolean isMainBranch = component.getMainBranchProjectUuid() == null;
if (reference.isPresent()) {
BranchDto refBranch = reference.get().getRefBranch();
@@ -257,6 +256,7 @@ public class ComponentAction implements MeasuresWsAction {
response.setComponent(componentDtoToWsComponent(component, measuresByMetric, singletonMap(refComponent.uuid(), refComponent),
refBranch.isMain() ? null : refBranch.getBranchKey(), null));
} else {
+ boolean isMainBranch = dbClient.branchDao().selectByUuid(dbSession, component.branchUuid()).map(BranchDto::isMain).orElse(true);
response.setComponent(componentDtoToWsComponent(component, measuresByMetric, emptyMap(), isMainBranch ? null : request.getBranch(), request.getPullRequest()));
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
index da343f45723..35dfde3e2f1 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
@@ -270,7 +270,7 @@ public class ComponentTreeAction implements MeasuresWsAction {
private ComponentTreeWsResponse doHandle(ComponentTreeRequest request) {
ComponentTreeData data = load(request);
if (data.getComponents() == null) {
- return emptyResponse(data.getBaseComponent(), request);
+ return emptyResponse(data.getBaseComponent(), data.getBranch(), request);
}
return buildResponse(
@@ -290,7 +290,7 @@ public class ComponentTreeAction implements MeasuresWsAction {
.setTotal(paging.total())
.build();
- boolean isMainBranch = data.getBaseComponent().getMainBranchProjectUuid() == null;
+ boolean isMainBranch = data.getBranch() == null || data.getBranch().isMain();
response.setBaseComponent(
toWsComponent(
data.getBaseComponent(),
@@ -333,14 +333,14 @@ public class ComponentTreeAction implements MeasuresWsAction {
return additionalFields != null && additionalFields.contains(ADDITIONAL_METRICS);
}
- private static ComponentTreeWsResponse emptyResponse(@Nullable ComponentDto baseComponent, ComponentTreeRequest request) {
+ private static ComponentTreeWsResponse emptyResponse(@Nullable ComponentDto baseComponent, @Nullable BranchDto branch, ComponentTreeRequest request) {
ComponentTreeWsResponse.Builder response = ComponentTreeWsResponse.newBuilder();
response.getPagingBuilder()
.setPageIndex(request.getPage())
.setPageSize(request.getPageSize())
.setTotal(0);
if (baseComponent != null) {
- boolean isMainBranch = baseComponent.getMainBranchProjectUuid() == null;
+ boolean isMainBranch = branch == null || branch.isMain();
response.setBaseComponent(componentDtoToWsComponent(baseComponent, isMainBranch ? null : request.getBranch(), request.getPullRequest()));
}
return response.build();
@@ -415,9 +415,13 @@ public class ComponentTreeAction implements MeasuresWsAction {
try (DbSession dbSession = dbClient.openSession(false)) {
ComponentDto baseComponent = loadComponent(dbSession, wsRequest);
checkPermissions(baseComponent);
+ // portfolios don't have branches
+ BranchDto branchDto = dbClient.branchDao().selectByUuid(dbSession, baseComponent.branchUuid()).orElse(null);
+
Optional<SnapshotDto> baseSnapshot = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, baseComponent.branchUuid());
if (baseSnapshot.isEmpty()) {
return ComponentTreeData.builder()
+ .setBranch(branchDto)
.setBaseComponent(baseComponent)
.build();
}
@@ -455,6 +459,7 @@ public class ComponentTreeAction implements MeasuresWsAction {
return ComponentTreeData.builder()
.setBaseComponent(baseComponent)
+ .setBranch(branchDto)
.setComponentsFromDb(components)
.setComponentCount(componentCount)
.setBranchByReferenceUuid(branchByReferenceUuid)
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java
index 4c86e9f6668..7ddd4bafb9f 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeData.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+import org.sonar.db.component.BranchDto;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
@@ -35,6 +36,7 @@ import static java.util.Objects.requireNonNull;
class ComponentTreeData {
private final ComponentDto baseComponent;
+ private final BranchDto branch;
private final List<ComponentDto> components;
private final int componentCount;
private final Map<String, ComponentDto> referenceComponentsByUuid;
@@ -47,6 +49,7 @@ class ComponentTreeData {
this.baseComponent = builder.baseComponent;
this.components = builder.componentsFromDb;
this.componentCount = builder.componentCount;
+ this.branch = builder.branch;
this.referenceComponentsByUuid = builder.referenceComponentsByUuid;
this.branchByReferenceUuid = builder.branchByReferenceUuid;
this.metrics = builder.metrics;
@@ -63,6 +66,11 @@ class ComponentTreeData {
}
@CheckForNull
+ public BranchDto getBranch() {
+ return branch;
+ }
+
+ @CheckForNull
List<ComponentDto> getComponents() {
return components;
}
@@ -102,6 +110,8 @@ class ComponentTreeData {
private int componentCount;
private List<MetricDto> metrics;
private Measures.Period period;
+ private BranchDto branch;
+
private Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric;
private Builder() {
@@ -128,6 +138,11 @@ class ComponentTreeData {
return this;
}
+ public Builder setBranch(@Nullable BranchDto branch) {
+ this.branch = branch;
+ return this;
+ }
+
public Builder setMetrics(List<MetricDto> metrics) {
this.metrics = metrics;
return this;
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/BulkDeleteAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/BulkDeleteAction.java
index e431283145c..a38add5920c 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/BulkDeleteAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/BulkDeleteAction.java
@@ -94,7 +94,7 @@ public class BulkDeleteAction implements ProjectsWsAction {
.setChangelog(
new Change("7.8", parameterRequiredMessage),
new Change("9.1", "The parameter '" + PARAM_ANALYZED_BEFORE + "' "
- + "takes into account the analysis of all branches and pull requests, not only the main branch."));
+ + "takes into account the analysis of all branches and pull requests, not only the main branch."));
action
.createParam(PARAM_PROJECTS)
@@ -115,7 +115,7 @@ public class BulkDeleteAction implements ProjectsWsAction {
action.createParam(PARAM_VISIBILITY)
.setDescription("Filter the projects that should be visible to everyone (%s), or only specific user/groups (%s).<br/>" +
- "If no visibility is specified, the default project visibility will be used.",
+ "If no visibility is specified, the default project visibility will be used.",
Visibility.PUBLIC.getLabel(), Visibility.PRIVATE.getLabel())
.setRequired(false)
.setInternal(true)
@@ -148,7 +148,7 @@ public class BulkDeleteAction implements ProjectsWsAction {
Set<ComponentDto> componentDtos = new HashSet<>(dbClient.componentDao().selectByQuery(dbSession, query, 0, Integer.MAX_VALUE));
try {
- componentDtos.forEach(p -> componentCleanerService.delete(dbSession, p));
+ componentDtos.forEach(p -> componentCleanerService.deleteComponent(dbSession, p));
} finally {
projectLifeCycleListeners.onProjectsDeleted(componentDtos.stream().map(Project::from).collect(MoreCollectors.toSet(componentDtos.size())));
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/ValuesAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/ValuesAction.java
index ab2002a6941..deb01610b6e 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/ValuesAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/setting/ws/ValuesAction.java
@@ -25,6 +25,7 @@ import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;
import com.google.common.collect.TreeMultimap;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -124,11 +125,9 @@ public class ValuesAction implements SettingsWsAction {
try (DbSession dbSession = dbClient.openSession(true)) {
ValuesRequest valuesRequest = ValuesRequest.from(request);
Optional<ComponentDto> component = loadComponent(dbSession, valuesRequest);
- BranchDto branchDto = component.map(c -> componentFinder.getBranchByUuid(dbSession, c.branchUuid())).orElse(null);
-
Set<String> keys = loadKeys(valuesRequest);
Map<String, String> keysToDisplayMap = getKeysToDisplayMap(keys);
- List<Setting> settings = loadSettings(dbSession, component, keysToDisplayMap.keySet(), branchDto);
+ List<Setting> settings = loadSettings(dbSession, component, keysToDisplayMap.keySet());
return new ValuesResponseBuilder(settings, component, keysToDisplayMap).build();
}
}
@@ -160,28 +159,33 @@ public class ValuesAction implements SettingsWsAction {
return Optional.of(component);
}
- private List<Setting> loadSettings(DbSession dbSession, Optional<ComponentDto> component, Set<String> keys, @Nullable BranchDto branchDto) {
+ private List<Setting> loadSettings(DbSession dbSession, Optional<ComponentDto> component, Set<String> keys) {
// List of settings must be kept in the following orders : default -> global -> component -> branch
List<Setting> settings = new ArrayList<>();
settings.addAll(loadDefaultValues(keys));
settings.addAll(loadGlobalSettings(dbSession, keys));
- String branch = getBranchKeySafely(branchDto);
- if (component.isPresent() && branch != null && component.get().getMainBranchProjectUuid() != null) {
- ComponentDto project = componentFinder.getByUuidFromMainBranch(dbSession, component.get().getMainBranchProjectUuid());
- settings.addAll(loadComponentSettings(dbSession, keys, project).values());
- }
- component.ifPresent(componentDto -> settings.addAll(loadComponentSettings(dbSession, keys, componentDto).values()));
+ component.ifPresent(c -> settings.addAll(loadComponentSettings(dbSession, c, keys)));
return settings.stream()
.filter(s -> settingsWsSupport.isVisible(s.getKey(), component))
.toList();
}
- @CheckForNull
- private static String getBranchKeySafely(@Nullable BranchDto branchDto) {
- if (branchDto != null) {
- return branchDto.isMain() ? null : branchDto.getBranchKey();
+ private Collection<Setting> loadComponentSettings(DbSession dbSession, ComponentDto componentDto, Set<String> keys) {
+ BranchDto branchDto = componentFinder.getBranchByUuid(dbSession, componentDto.branchUuid());
+
+ List<String> componentUuids = new LinkedList<>();
+ if (!branchDto.isMain()) {
+ ComponentDto mainBranchComponent = componentFinder.getByKey(dbSession, componentDto.getKey());
+ if (!mainBranchComponent.isRoot()) {
+ componentUuids.add(mainBranchComponent.branchUuid());
+ }
+ componentUuids.add(mainBranchComponent.uuid());
+ }
+ if (!componentDto.isRoot()) {
+ componentUuids.add(componentDto.branchUuid());
}
- return null;
+ componentUuids.add(componentDto.uuid());
+ return loadComponentsSettings(dbSession, keys, componentUuids);
}
private List<Setting> loadDefaultValues(Set<String> keys) {
@@ -209,14 +213,9 @@ public class ValuesAction implements SettingsWsAction {
}
/**
- * Return list of settings by component uuid
+ * Return list of settings by component uuids
*/
- private Multimap<String, Setting> loadComponentSettings(DbSession dbSession, Set<String> keys, ComponentDto component) {
- List<String> componentUuids = new LinkedList<>();
- if (!component.uuid().equals(component.branchUuid())) {
- componentUuids.add(component.branchUuid());
- }
- componentUuids.add(component.uuid());
+ private Collection<Setting> loadComponentsSettings(DbSession dbSession, Set<String> keys, List<String> componentUuids) {
List<PropertyDto> properties = dbClient.propertiesDao().selectPropertiesByKeysAndComponentUuids(dbSession, keys, componentUuids);
List<PropertyDto> propertySets = dbClient.propertiesDao().selectPropertiesByKeysAndComponentUuids(dbSession, getPropertySetKeys(properties), componentUuids);
@@ -227,7 +226,7 @@ public class ValuesAction implements SettingsWsAction {
settingsByUuid.put(componentUuid,
Setting.createFromDto(propertyDto, getPropertySets(propertyKey, propertySets, componentUuid), propertyDefinitions.get(propertyKey)));
}
- return settingsByUuid;
+ return settingsByUuid.values();
}
private Set<String> getPropertySetKeys(List<PropertyDto> properties) {
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/source/ws/LinesAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/source/ws/LinesAction.java
index be693c44f8e..d24aec74705 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/source/ws/LinesAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/source/ws/LinesAction.java
@@ -158,13 +158,13 @@ public class LinesAction implements SourcesWsAction {
private ComponentDto loadComponent(DbSession dbSession, Request wsRequest) {
String componentKey = wsRequest.param(PARAM_KEY);
- String componentId = wsRequest.param(PARAM_UUID);
+ String componentUuid = wsRequest.param(PARAM_UUID);
String branch = wsRequest.param(PARAM_BRANCH);
String pullRequest = wsRequest.param(PARAM_PULL_REQUEST);
- checkArgument(componentId == null || (branch == null && pullRequest == null), "Parameter '%s' cannot be used at the same time as '%s' or '%s'",
+ checkArgument(componentUuid == null || (branch == null && pullRequest == null), "Parameter '%s' cannot be used at the same time as '%s' or '%s'",
PARAM_UUID, PARAM_BRANCH, PARAM_PULL_REQUEST);
if (branch == null && pullRequest == null) {
- return componentFinder.getByUuidOrKey(dbSession, componentId, componentKey, UUID_AND_KEY);
+ return componentFinder.getByUuidOrKey(dbSession, componentUuid, componentKey, UUID_AND_KEY);
}
checkRequest(componentKey != null, "The '%s' parameter is missing", PARAM_KEY);
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
index 8c8de6fcf66..58e63b6f858 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
@@ -26,7 +26,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
-import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.config.Configuration;
import org.sonar.api.resources.Qualifiers;
@@ -43,6 +42,7 @@ import org.sonar.api.web.UserRole;
import org.sonar.api.web.page.Page;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.component.BranchDto;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.measure.LiveMeasureDto;
@@ -149,9 +149,10 @@ public class ComponentAction implements NavigationWsAction {
String pullRequest = request.param(PARAM_PULL_REQUEST);
ComponentDto component = componentFinder.getByKeyAndOptionalBranchOrPullRequest(session, componentKey, branch, pullRequest);
checkComponentNotAModuleAndNotADirectory(component);
- ComponentDto rootProjectOrBranch = getRootProjectOrBranch(component, session);
- ComponentDto rootProject = rootProjectOrBranch.getMainBranchProjectUuid() == null ? rootProjectOrBranch
- : componentFinder.getByUuidFromMainBranch(session, rootProjectOrBranch.getMainBranchProjectUuid());
+ ComponentDto rootComponent = getRootProjectOrBranch(component, session);
+ // will be empty for portfolios
+ Optional<BranchDto> branchDto = dbClient.branchDao().selectByUuid(session, rootComponent.branchUuid());
+ String projectOrPortfolioUuid = branchDto.map(BranchDto::getProjectUuid).orElse(rootComponent.branchUuid());
if (!userSession.hasComponentPermission(USER, component) &&
!userSession.hasComponentPermission(ADMIN, component) &&
!userSession.isSystemAdministrator()) {
@@ -161,11 +162,10 @@ public class ComponentAction implements NavigationWsAction {
try (JsonWriter json = response.newJsonWriter()) {
json.beginObject();
- boolean isFavourite = isFavourite(session, rootProject, component);
- String branchKey = getBranchKey(session, component);
- writeComponent(json, component, analysis.orElse(null), isFavourite, branchKey);
+ boolean isFavourite = isFavourite(session, projectOrPortfolioUuid, component);
+ writeComponent(json, component, analysis.orElse(null), isFavourite, branchDto.map(BranchDto::getBranchKey).orElse(null));
writeProfiles(json, session, component);
- writeQualityGate(json, session, rootProject);
+ writeQualityGate(json, session, projectOrPortfolioUuid);
if (userSession.hasComponentPermission(ADMIN, component) ||
userSession.hasPermission(ADMINISTER_QUALITY_PROFILES) ||
userSession.hasPermission(ADMINISTER_QUALITY_GATES)) {
@@ -177,14 +177,6 @@ public class ComponentAction implements NavigationWsAction {
}
}
- @CheckForNull
- private String getBranchKey(DbSession session, ComponentDto component) {
- // TODO portfolios may have no branch, so we shouldn't faul?
- return dbClient.branchDao().selectByUuid(session, component.branchUuid())
- .map(b -> b.isMain() ? null : b.getBranchKey())
- .orElse(null);
- }
-
private static void checkComponentNotAModuleAndNotADirectory(ComponentDto component) {
BadRequestException.checkRequest(!MODULE_OR_DIR_QUALIFIERS.contains(component.qualifier()), "Operation not supported for module or directory components");
}
@@ -239,11 +231,11 @@ public class ComponentAction implements NavigationWsAction {
}
}
- private boolean isFavourite(DbSession session, ComponentDto rootComponent, ComponentDto component) {
+ private boolean isFavourite(DbSession session, String projectOrPortfolioUuid, ComponentDto component) {
PropertyQuery propertyQuery = PropertyQuery.builder()
.setUserUuid(userSession.getUuid())
.setKey("favourite")
- .setComponentUuid(isSubview(component) ? component.uuid() : rootComponent.uuid())
+ .setComponentUuid(isSubview(component) ? component.uuid() : projectOrPortfolioUuid)
.build();
List<PropertyDto> componentFavourites = dbClient.propertiesDao().selectByQuery(propertyQuery, session);
return componentFavourites.size() == 1;
@@ -266,8 +258,8 @@ public class ComponentAction implements NavigationWsAction {
json.endArray();
}
- private void writeQualityGate(JsonWriter json, DbSession session, ComponentDto component) {
- var qualityGateData = qualityGateFinder.getEffectiveQualityGate(session, component.uuid());
+ private void writeQualityGate(JsonWriter json, DbSession session, String projectOrPortfolioUuid) {
+ var qualityGateData = qualityGateFinder.getEffectiveQualityGate(session, projectOrPortfolioUuid);
json.name("qualityGate").beginObject()
.prop("key", qualityGateData.getUuid())
.prop("name", qualityGateData.getName())
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java
index 36813971f4f..4984ab3dd8d 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/setting/TestProjectConfigurationLoader.java
@@ -22,7 +22,6 @@ package org.sonar.server.setting;
import org.sonar.api.config.Configuration;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
-import org.sonar.db.component.ComponentDto;
public class TestProjectConfigurationLoader implements ProjectConfigurationLoader {
@@ -33,7 +32,12 @@ public class TestProjectConfigurationLoader implements ProjectConfigurationLoade
}
@Override
- public Configuration loadProjectConfiguration(DbSession dbSession, BranchDto branch) {
+ public Configuration loadBranchConfiguration(DbSession dbSession, BranchDto branch) {
+ return config;
+ }
+
+ @Override
+ public Configuration loadProjectConfiguration(DbSession dbSession, String projectUuid) {
return config;
}
}