import java.util.Optional;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
import org.sonar.api.server.ServerSide;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
-import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
import static com.google.common.base.Preconditions.checkState;
-import static java.util.Objects.requireNonNull;
/**
* Branch code for {@link ReportSubmitter}.
public abstract String getDbKey();
- public abstract Optional<Branch> getBranch();
+ public abstract Optional<String> getBranchName();
public abstract Optional<String> getPullRequestKey();
public final boolean isMainBranch() {
- return !getBranch().isPresent() && !getPullRequestKey().isPresent();
+ return !getBranchName().isPresent() && !getPullRequestKey().isPresent();
}
/**
public abstract ComponentKey getMainBranchComponentKey();
}
- @Immutable
- public static final class Branch {
- private final String name;
- private final BranchType type;
-
- public Branch(String name, BranchType type) {
- this.name = requireNonNull(name, "name can't be null");
- this.type = requireNonNull(type, "type can't be null");
- }
-
- public String getName() {
- return name;
- }
-
- public BranchType getType() {
- return type;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- Branch branch = (Branch) o;
- return name.equals(branch.name) && type == branch.type;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(name, type);
- }
-
- @Override
- public String toString() {
- return "Branch{" +
- "name='" + name + '\'' +
- ", type=" + type +
- '}';
- }
- }
private static final class ComponentKeyImpl extends ComponentKey {
private final String key;
}
@Override
- public Optional<Branch> getBranch() {
+ public Optional<String> getBranchName() {
return Optional.empty();
}
* @throws NotFoundException if the organization with the specified key does not exist
* @throws IllegalArgumentException if the organization with the specified key is not the organization of the specified project (when it already exists in DB)
*/
- public CeTask submit(String organizationKey, String projectKey, @Nullable String projectName,
- Map<String, String> characteristics, InputStream reportInput) {
+ public CeTask submit(String organizationKey, String projectKey, @Nullable String projectName, Map<String, String> characteristics, InputStream reportInput) {
try (DbSession dbSession = dbClient.openSession(false)) {
+ boolean projectCreated = false;
OrganizationDto organizationDto = getOrganizationDtoOrFail(dbSession, organizationKey);
+ // Note: when the main branch is analyzed, the characteristics may or may not have the branch name, so componentKey#isMainBranch is not reliable!
BranchSupport.ComponentKey componentKey = branchSupport.createComponentKey(projectKey, characteristics);
- Optional<ComponentDto> existingComponent = dbClient.componentDao().selectByKey(dbSession, componentKey.getDbKey());
- ComponentDto component;
- if (existingComponent.isPresent()) {
- component = existingComponent.get();
- validateProject(dbSession, component, projectKey);
- ensureOrganizationIsConsistent(component, organizationDto);
+ Optional<ComponentDto> mainBranchComponentOpt = dbClient.componentDao().selectByKey(dbSession, componentKey.getKey());
+ ComponentDto mainBranchComponent;
+
+ if (mainBranchComponentOpt.isPresent()) {
+ mainBranchComponent = mainBranchComponentOpt.get();
+ validateProject(dbSession, mainBranchComponent, projectKey);
+ ensureOrganizationIsConsistent(mainBranchComponent, organizationDto);
} else {
- component = createComponent(dbSession, organizationDto, componentKey, projectName);
+ mainBranchComponent = createProject(dbSession, organizationDto, componentKey.getMainBranchComponentKey(), projectName);
+ projectCreated = true;
}
- checkScanPermission(component);
- return submitReport(dbSession, reportInput, component, characteristics);
+ BranchDto mainBranch = dbClient.branchDao().selectByUuid(dbSession, mainBranchComponent.projectUuid())
+ .orElseThrow(() -> new IllegalStateException("Couldn't find the main branch of the project"));
+ ComponentDto branchComponent;
+ if (isMainBranch(componentKey, mainBranch)) {
+ branchComponent = mainBranchComponent;
+ } else {
+ branchComponent = dbClient.componentDao().selectByKey(dbSession, componentKey.getDbKey())
+ .orElseGet(() -> branchSupport.createBranchComponent(dbSession, componentKey, organizationDto, mainBranchComponent, mainBranch));
+ }
+
+ if (projectCreated) {
+ componentUpdater.commitAndIndex(dbSession, mainBranchComponent);
+ } else {
+ dbSession.commit();
+ }
+
+ checkScanPermission(branchComponent);
+ return submitReport(dbSession, reportInput, branchComponent, characteristics);
+ }
+ }
+
+ private static boolean isMainBranch(BranchSupport.ComponentKey componentKey, BranchDto mainBranch) {
+ if (componentKey.isMainBranch()) {
+ return true;
}
+
+ return componentKey.getBranchName().isPresent() && componentKey.getBranchName().get().equals(mainBranch.getKey());
}
private void checkScanPermission(ComponentDto project) {
// they don't have the direct permission on the project.
// That means that dropping the permission on the project does not have any effects
// if user has still the permission on the organization
- if (!userSession.hasComponentPermission(UserRole.SCAN, project) &&
- !userSession.hasPermission(OrganizationPermission.SCAN, project.getOrganizationUuid())) {
+ if (!userSession.hasComponentPermission(UserRole.SCAN, project) && !userSession.hasPermission(OrganizationPermission.SCAN, project.getOrganizationUuid())) {
throw insufficientPrivilegesException();
}
}
project.getDbKey(), organizationDto.getKey());
}
- private ComponentDto createComponent(DbSession dbSession, OrganizationDto organization, BranchSupport.ComponentKey componentKey, @Nullable String projectName) {
- if (componentKey.isMainBranch()) {
- ComponentDto project = createProject(dbSession, organization, componentKey, projectName);
- componentUpdater.commitAndIndex(dbSession, project);
- return project;
- }
-
- Optional<ComponentDto> existingMainComponent = dbClient.componentDao().selectByKey(dbSession, componentKey.getKey());
- ComponentDto mainComponentDto = existingMainComponent
- .orElseGet(() -> createProject(dbSession, organization, componentKey.getMainBranchComponentKey(), projectName));
- BranchDto mainComponentBranchDto = dbClient.branchDao().selectByUuid(dbSession, mainComponentDto.uuid())
- .orElseThrow(() -> new IllegalStateException("Branch of main component does not exist"));
- ComponentDto branchComponent = branchSupport.createBranchComponent(dbSession, componentKey, organization, mainComponentDto, mainComponentBranchDto);
- if (existingMainComponent.isPresent()) {
- dbSession.commit();
- } else {
- componentUpdater.commitAndIndex(dbSession, mainComponentDto);
- }
- return branchComponent;
- }
-
- private ComponentDto createProject(DbSession dbSession, OrganizationDto organization, BranchSupport.ComponentKey componentKey,
- @Nullable String projectName) {
+ private ComponentDto createProject(DbSession dbSession, OrganizationDto organization, BranchSupport.ComponentKey componentKey, @Nullable String projectName) {
userSession.checkPermission(OrganizationPermission.PROVISION_PROJECTS, organization);
String userUuid = userSession.getUuid();
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
underTest.submit(organization.getKey(), project.getDbKey(), project.name(), emptyMap(), reportInput);
- verifyZeroInteractions(branchSupportDelegate);
+ verifyNoInteractions(branchSupportDelegate);
}
@Test
underTest.submit(organization.getKey(), project.getDbKey(), project.name(), randomCharacteristics, reportInput);
- verifyZeroInteractions(permissionTemplateService);
- verifyZeroInteractions(favoriteUpdater);
+ verifyNoInteractions(permissionTemplateService);
+ verifyNoInteractions(favoriteUpdater);
verify(branchSupport, times(0)).createBranchComponent(any(), any(), any(), any(), any());
verify(branchSupportDelegate).createComponentKey(project.getDbKey(), randomCharacteristics);
verify(branchSupportDelegate, times(0)).createBranchComponent(any(), any(), any(), any(), any());
underTest.submit(organization.getKey(), existingProject.getDbKey(), existingProject.name(), randomCharacteristics, reportInput);
- verifyZeroInteractions(permissionTemplateService);
- verifyZeroInteractions(favoriteUpdater);
+ verifyNoInteractions(permissionTemplateService);
+ verifyNoInteractions(favoriteUpdater);
verify(branchSupport).createBranchComponent(any(DbSession.class), same(componentKey), eq(organization), eq(existingProject), eq(exitingProjectMainBranch));
verify(branchSupportDelegate).createComponentKey(existingProject.getDbKey(), randomCharacteristics);
verify(branchSupportDelegate).createBranchComponent(any(DbSession.class), same(componentKey), eq(organization), eq(existingProject), eq(exitingProjectMainBranch));
when(mainComponentKey.getMainBranchComponentKey()).thenReturn(mainComponentKey);
BranchSupport.ComponentKey componentKey = mockComponentKey(branch.getKey(), branch.getDbKey());
- when(componentKey.getBranch()).thenReturn(Optional.ofNullable(branch).map(b -> new BranchSupport.Branch(b.name(), BranchType.BRANCH)));
+ when(componentKey.getBranchName()).thenReturn(Optional.of(branch).map(ComponentDto::name));
when(componentKey.getMainBranchComponentKey()).thenReturn(mainComponentKey);
return componentKey;