import org.sonar.db.DbTester;
import org.sonar.db.audit.AuditPersister;
import org.sonar.db.audit.NoOpAuditPersister;
+import org.sonar.db.component.BranchDto;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
assertProject(projectByKee.get(), "projectName_p1", "projectKee_o1_p1", "uuid_o1_p1", "desc_p1", "tag1,tag2", false);
}
+ @Test
+ public void select_by_branch_uuid() {
+ ProjectDto dto = createProject("o1", "p1");
+ projectDao.insert(db.getSession(), dto);
+ BranchDto branchDto = db.components().insertProjectBranch(dto);
+ assertThat(projectDao.selectByBranchUuid(db.getSession(), branchDto.getUuid()).get().getUuid()).isEqualTo(dto.getUuid());
+ }
+
@Test
public void select_projects() {
ProjectDto dto1 = createProject("o1", "p1");
return executeLargeInputs(keys, partition -> mapper(session).selectApplicationsByKeys(partition));
}
+ public Optional<ProjectDto> selectByBranchUuid(DbSession dbSession, String branchUuid) {
+ return Optional.ofNullable(mapper(dbSession).selectByBranchUuid(branchUuid));
+ }
+
public List<ProjectDto> selectProjects(DbSession session) {
return mapper(session).selectProjects();
}
List<ProjectDto> selectApplicationsByKeys(@Param("kees") Collection<String> kees);
+ @CheckForNull
+ ProjectDto selectByBranchUuid(String branchUuid);
+
List<String> selectAllProjectUuids();
Set<String> selectProjectUuidsAssociatedToDefaultQualityProfileByLanguage(@Param("languageFilters") Set<String> languageFilters);
mapper(dbSession).clearHomepages("PROJECT", project.getUuid(), system2.now());
}
- public void cleanHomepage(DbSession dbSession, ComponentDto project) {
- mapper(dbSession).clearHomepages("PROJECT", project.uuid(), system2.now());
+ public void cleanHomepage(DbSession dbSession, ComponentDto component) {
+ mapper(dbSession).clearHomepages("PROJECT", component.uuid(), system2.now());
}
public void cleanHomepage(DbSession dbSession, UserDto user) {
SELECT
<include refid="componentColumns"/>
FROM components p
+ left outer join project_branches pb on pb.uuid = p.branch_uuid
where
p.kee=#{key,jdbcType=VARCHAR}
- and p.main_branch_project_uuid is null
- </select>
+ and (pb.is_main = null or pb.is_main = ${_true}) </select>
<select id="selectByKeyCaseInsensitive" parameterType="String" resultType="Component">
SELECT
</foreach>
</select>
+ <select id="selectByBranchUuid" parameterType="String" resultType="Project">
+ SELECT
+ <include refid="projectColumns"/>
+ FROM projects p inner join project_branches pb on pb.project_uuid = p.uuid
+ where pb.uuid=#{branchUuid,jdbcType=VARCHAR}
+ </select>
+
<select id="selectProjects" resultType="Project">
select
<include refid="projectColumns"/>
globalSettings.setProperty(MAIN_BRANCH_PROP_KEY, MAIN_BRANCH_PROP_VALUE);
BranchDto mainBranch = insertBranch(MAIN_BRANCH_UUID, MAIN_BRANCH_UUID, true);
- Configuration configuration = underTest.loadProjectConfiguration(db.getSession(), mainBranch);
+ Configuration configuration = underTest.loadBranchConfiguration(db.getSession(), mainBranch);
assertThat(configuration.get(MAIN_BRANCH_PROP_KEY)).contains(MAIN_BRANCH_PROP_VALUE);
}
db.properties().insertProperty(projectPropKey2, projectPropValue2, MAIN_BRANCH_UUID);
BranchDto mainBranch = insertBranch(MAIN_BRANCH_UUID, MAIN_BRANCH_UUID, true);
-
- Configuration configuration = underTest.loadProjectConfiguration(db.getSession(), mainBranch);
+ Configuration configuration = underTest.loadBranchConfiguration(db.getSession(), mainBranch);
assertThat(configuration.get(GLOBAL_PROP_KEY)).contains(GLOBAL_PROP_VALUE);
assertThat(configuration.get(projectPropKey1)).contains(projectPropValue1);
BranchDto mainBranch = insertBranch(MAIN_BRANCH_UUID, MAIN_BRANCH_UUID, true);
BranchDto branch = insertBranch(BRANCH_UUID, MAIN_BRANCH_UUID, false);
- Configuration configuration = underTest.loadProjectConfiguration(db.getSession(), branch);
+ Configuration configuration = underTest.loadBranchConfiguration(db.getSession(), branch);
assertThat(configuration.get(GLOBAL_PROP_KEY)).contains(GLOBAL_PROP_VALUE);
assertThat(configuration.get(MAIN_BRANCH_PROP_KEY)).contains(MAIN_BRANCH_PROP_VALUE);
import org.sonar.api.config.Configuration;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
-import org.sonar.db.component.ComponentDto;
public interface ProjectConfigurationLoader {
/**
* Returns the applicable component configuration with most specific configuration overriding more global ones
* (eg. global > project > branch).
* <p>
- * Any component is accepted but SQ only supports specific properties for projects and branches.
*/
- Configuration loadProjectConfiguration(DbSession dbSession, BranchDto branch);
+ Configuration loadBranchConfiguration(DbSession dbSession, BranchDto branch);
+
+ Configuration loadProjectConfiguration(DbSession dbSession, String projectUuid);
}
package org.sonar.server.setting;
import java.util.List;
+import javax.annotation.Nullable;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.internal.Settings;
import org.sonar.db.DbClient;
}
@Override
- public Configuration loadProjectConfiguration(DbSession dbSession, BranchDto branchDto) {
- if (branchDto.isMain()) {
- ChildSettings mainBranchSettings = loadMainBranchConfiguration(dbSession, branchDto.getUuid());
- return mainBranchSettings.asConfiguration();
- } else {
- BranchDto mainBranch = dbClient.branchDao().selectMainBranchByProjectUuid(dbSession, branchDto.getProjectUuid())
- .orElseThrow(() -> new IllegalStateException("Main branch not found for project: " + branchDto.getProjectUuid()));
-
- ChildSettings mainBranchSettings = loadMainBranchConfiguration(dbSession, mainBranch.getUuid());
- ChildSettings settings = new ChildSettings(mainBranchSettings);
- dbClient.propertiesDao()
- .selectComponentProperties(dbSession, branchDto.getUuid())
- .forEach(property -> settings.setProperty(property.getKey(), property.getValue()));
- return settings.asConfiguration();
+ public Configuration loadBranchConfiguration(DbSession dbSession, BranchDto branch) {
+ return loadProjectAndBranchConfiguration(dbSession, branch.getProjectUuid(), branch.getUuid());
+ }
+
+ @Override
+ public Configuration loadProjectConfiguration(DbSession dbSession, String projectUuid) {
+ return loadProjectAndBranchConfiguration(dbSession, projectUuid, null);
+ }
+
+ private Configuration loadProjectAndBranchConfiguration(DbSession dbSession, String projectUuid, @Nullable String branchUuid) {
+ ChildSettings projectSettings = internalLoadProjectConfiguration(dbSession, projectUuid);
+
+ if (branchUuid == null) {
+ return projectSettings.asConfiguration();
}
+
+ ChildSettings settings = new ChildSettings(projectSettings);
+ dbClient.propertiesDao()
+ .selectComponentProperties(dbSession, branchUuid)
+ .forEach(property -> settings.setProperty(property.getKey(), property.getValue()));
+ return settings.asConfiguration();
}
- private ChildSettings loadMainBranchConfiguration(DbSession dbSession, String uuid) {
+ private ChildSettings internalLoadProjectConfiguration(DbSession dbSession, String uuid) {
ChildSettings settings = new ChildSettings(globalSettings);
List<PropertyDto> propertyDtos = dbClient.propertiesDao().selectComponentProperties(dbSession, uuid);
propertyDtos.forEach(property -> settings.setProperty(property.getKey(), property.getValue()));
return settings;
}
+
}
}
@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);
}
dbClient.componentDao().insertOnMainBranch(dbSession, file);
dbSession.commit();
- assertThatThrownBy(() -> underTest.delete(dbSession, file))
+ assertThatThrownBy(() -> underTest.deleteComponent(dbSession, file))
.isInstanceOf(IllegalArgumentException.class);
}
assertThatThrownBy(request::execute)
.isInstanceOf(NotFoundException.class)
- .hasMessage("Component key '%s' not found", key);
+ .hasMessage("Project '%s' not found", key);
}
@Test
.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);
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());
}
@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
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;
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,
@Before
public void setUp() {
when(dbClient.componentDao()).thenReturn(componentDao);
+ when(dbClient.branchDao()).thenReturn(branchDao);
when(dbClient.openSession(false)).thenReturn(session);
}
}
}
- 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);
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) {
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)
}
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));
}
}
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())
});
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());
}
}
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;
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);
}
}
.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);
}
}
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;
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()));
}
}
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;
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;
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;
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);
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));
.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()) {
}
}
- 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());
}
}
- 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()
}
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);
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);
}
}
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();
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()));
}
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(
.setTotal(paging.total())
.build();
- boolean isMainBranch = data.getBaseComponent().getMainBranchProjectUuid() == null;
+ boolean isMainBranch = data.getBranch() == null || data.getBranch().isMain();
response.setBaseComponent(
toWsComponent(
data.getBaseComponent(),
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();
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();
}
return ComponentTreeData.builder()
.setBaseComponent(baseComponent)
+ .setBranch(branchDto)
.setComponentsFromDb(components)
.setComponentCount(componentCount)
.setBranchByReferenceUuid(branchByReferenceUuid)
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;
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;
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;
return baseComponent;
}
+ @CheckForNull
+ public BranchDto getBranch() {
+ return branch;
+ }
+
@CheckForNull
List<ComponentDto> getComponents() {
return components;
private int componentCount;
private List<MetricDto> metrics;
private Measures.Period period;
+ private BranchDto branch;
+
private Table<String, MetricDto, Measure> measuresByComponentUuidAndMetric;
private Builder() {
return this;
}
+ public Builder setBranch(@Nullable BranchDto branch) {
+ this.branch = branch;
+ return this;
+ }
+
public Builder setMetrics(List<MetricDto> metrics) {
this.metrics = metrics;
return this;
.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)
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)
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())));
}
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;
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();
}
}
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) {
}
/**
- * 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);
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) {
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);
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;
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;
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()) {
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)) {
}
}
- @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");
}
}
}
- 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;
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())
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 {
}
@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;
}
}