Browse Source

SONAR-9616 Write main branch to DB even if plugin is not installed

tags/6.6-RC1
Duarte Meneses 6 years ago
parent
commit
9f5272cac1
16 changed files with 516 additions and 49 deletions
  1. 1
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v66/DbVersion66.java
  2. 67
    0
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v66/PopulateMainProjectBranches.java
  3. 1
    1
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v66/DbVersion66Test.java
  4. 109
    0
      server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v66/PopulateMainProjectBranchesTest.java
  5. 60
    0
      server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v66/PopulateMainProjectBranchesTest/initial.sql
  6. 26
    0
      server/sonar-server/src/main/java/org/sonar/server/component/ComponentUpdater.java
  7. 114
    0
      server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/BranchPersister.java
  8. 0
    30
      server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/BranchPersisterDelegate.java
  9. 1
    1
      server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/DefaultBranchImpl.java
  10. 2
    0
      server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java
  11. 4
    11
      server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistComponentsStep.java
  12. 18
    0
      server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java
  13. 105
    0
      server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/BranchPersisterTest.java
  14. 2
    2
      server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistComponentsStepTest.java
  15. 3
    2
      server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ReportPersistComponentsStepTest.java
  16. 3
    2
      server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ViewsPersistComponentsStepTest.java

+ 1
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v66/DbVersion66.java View File

@@ -36,6 +36,7 @@ public class DbVersion66 implements DbVersion {
.add(1806, "Create table project_branches", CreateTableProjectBranches.class)
.add(1807, "Add on project_branches key", AddIndexOnProjectBranchesKey.class)
.add(1808, "Add branch column to projects table", AddBranchColumnToProjectsTable.class)
.add(1809, "Populate project_branches with existing main branches", PopulateMainProjectBranches.class)
;
}
}

+ 67
- 0
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v66/PopulateMainProjectBranches.java View File

@@ -0,0 +1,67 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v66;

import java.sql.SQLException;
import org.sonar.api.utils.System2;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.step.DataChange;
import org.sonar.server.platform.db.migration.step.MassUpdate;

import static org.apache.commons.lang.StringUtils.repeat;

public class PopulateMainProjectBranches extends DataChange {
private static final int KEE_MAX_LENGTH = 255;
static final String NULL_KEY = repeat("_", KEE_MAX_LENGTH);
private static final String INSERT_MAIN_PROJECT_BRANCHES = "INSERT INTO project_branches (uuid, project_uuid, kee_type, kee, branch_type, "
+ "merge_branch_uuid, pull_request_title, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";

private final System2 system2;

public PopulateMainProjectBranches(Database db, System2 system2) {
super(db);
this.system2 = system2;
}

@Override
protected void execute(Context context) throws SQLException {
long now = system2.now();
MassUpdate massUpdate = context.prepareMassUpdate();
massUpdate.select("SELECT uuid FROM projects p "
+ "WHERE p.scope='PRJ' AND p.qualifier='TRK' AND p.main_branch_project_uuid IS NULL "
+ "AND NOT EXISTS (SELECT uuid FROM project_branches b WHERE b.uuid = p.uuid)");
massUpdate.update(INSERT_MAIN_PROJECT_BRANCHES);
massUpdate.rowPluralName("projects");
massUpdate.execute((row, update) -> {
String uuid = row.getString(1);
update.setString(1, uuid);
update.setString(2, uuid);
update.setString(3, "BRANCH");
update.setString(4, NULL_KEY);
update.setString(5, "LONG");
update.setString(6, null);
update.setString(7, null);
update.setLong(8, now);
update.setLong(9, now);
return true;
});
}

}

+ 1
- 1
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v66/DbVersion66Test.java View File

@@ -36,7 +36,7 @@ public class DbVersion66Test {

@Test
public void verify_migration_count() {
verifyMigrationCount(underTest, 9);
verifyMigrationCount(underTest, 10);
}

}

+ 109
- 0
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v66/PopulateMainProjectBranchesTest.java View File

@@ -0,0 +1,109 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.platform.db.migration.version.v66;

import java.sql.SQLException;
import java.util.Map;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
import org.sonar.db.CoreDbTester;

import static org.assertj.core.api.Assertions.assertThat;

public class PopulateMainProjectBranchesTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();

@Rule
public CoreDbTester db = CoreDbTester.createForSchema(PopulateMainProjectBranchesTest.class, "initial.sql");

private System2 system2 = new AlwaysIncreasingSystem2();
private PopulateMainProjectBranches underTest = new PopulateMainProjectBranches(db.database(), system2);

@Test
public void populate_with_existing_project() throws SQLException {
insertProject("project1");
insertProject("project2", "project1", "PRJ");
insertProject("project3", null, "XXX");

underTest.execute();

assertThat(db.countRowsOfTable("project_branches")).isEqualTo(1);

Map<String, Object> row = db.selectFirst("select * from project_branches");
assertThat(row.get("UUID")).isEqualTo("project1");
assertThat(row.get("PROJECT_UUID")).isEqualTo("project1");
assertThat(row.get("KEE")).isEqualTo(PopulateMainProjectBranches.NULL_KEY);
assertThat(row.get("BRANCH_TYPE")).isEqualTo("LONG");

}

@Test
public void do_nothing_if_no_project() throws SQLException {
insertProject("project2", "project1", "PRJ");
insertProject("project3", null, "XXX");

underTest.execute();
assertThat(db.countRowsOfTable("project_branches")).isEqualTo(0);
}

@Test
public void do_not_populate_if_already_exists() throws SQLException {
insertProject("project1");
insertBranch("project1");

assertThat(db.countRowsOfTable("project_branches")).isEqualTo(1);
underTest.execute();
assertThat(db.countRowsOfTable("project_branches")).isEqualTo(1);
}

private void insertProject(String uuid) {
insertProject(uuid, null, "PRJ");
}

private void insertProject(String uuid, @Nullable String mainBranchUuid, String scope) {
db.executeInsert("PROJECTS",
"ORGANIZATION_UUID", "default-org",
"KEE", uuid + "-key",
"UUID", uuid,
"PROJECT_UUID", uuid,
"main_branch_project_uuid", mainBranchUuid,
"UUID_PATH", ".",
"ROOT_UUID", uuid,
"PRIVATE", "true",
"qualifier", "TRK",
"scope", scope);
}

private void insertBranch(String uuid) {
db.executeInsert("PROJECT_BRANCHES",
"uuid", uuid,
"project_uuid", uuid,
"kee_type", "BRANCH",
"kee", PopulateMainProjectBranches.NULL_KEY,
"branch_type", "LONG",
"created_at", 0,
"updated_at", 0);
}
}

+ 60
- 0
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v66/PopulateMainProjectBranchesTest/initial.sql View File

@@ -0,0 +1,60 @@
CREATE TABLE "PROJECTS" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
"KEE" VARCHAR(400),
"UUID" VARCHAR(50) NOT NULL,
"UUID_PATH" VARCHAR(1500) NOT NULL,
"ROOT_UUID" VARCHAR(50) NOT NULL,
"PROJECT_UUID" VARCHAR(50) NOT NULL,
"MODULE_UUID" VARCHAR(50),
"MODULE_UUID_PATH" VARCHAR(1500),
"MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
"NAME" VARCHAR(2000),
"DESCRIPTION" VARCHAR(2000),
"PRIVATE" BOOLEAN NOT NULL,
"TAGS" VARCHAR(500),
"ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
"SCOPE" VARCHAR(3),
"QUALIFIER" VARCHAR(10),
"DEPRECATED_KEE" VARCHAR(400),
"PATH" VARCHAR(2000),
"LANGUAGE" VARCHAR(20),
"COPY_COMPONENT_UUID" VARCHAR(50),
"LONG_NAME" VARCHAR(2000),
"DEVELOPER_UUID" VARCHAR(50),
"CREATED_AT" TIMESTAMP,
"AUTHORIZATION_UPDATED_AT" BIGINT,
"B_CHANGED" BOOLEAN,
"B_COPY_COMPONENT_UUID" VARCHAR(50),
"B_DESCRIPTION" VARCHAR(2000),
"B_ENABLED" BOOLEAN,
"B_UUID_PATH" VARCHAR(1500),
"B_LANGUAGE" VARCHAR(20),
"B_LONG_NAME" VARCHAR(500),
"B_MODULE_UUID" VARCHAR(50),
"B_MODULE_UUID_PATH" VARCHAR(1500),
"B_NAME" VARCHAR(500),
"B_PATH" VARCHAR(2000),
"B_QUALIFIER" VARCHAR(10)
);
CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID");
CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");

CREATE TABLE "PROJECT_BRANCHES" (
"UUID" VARCHAR(50) NOT NULL PRIMARY KEY,
"PROJECT_UUID" VARCHAR(50) NOT NULL,
"KEE_TYPE" VARCHAR(6) NOT NULL,
"KEE" VARCHAR(255) NOT NULL,
"BRANCH_TYPE" VARCHAR(5),
"MERGE_BRANCH_UUID" VARCHAR(50),
"PULL_REQUEST_TITLE" VARCHAR(4000),
"CREATED_AT" BIGINT NOT NULL,
"UPDATED_AT" BIGINT NOT NULL
);
CREATE UNIQUE INDEX "PK_PROJECT_BRANCHES" ON "PROJECT_BRANCHES" ("UUID");
CREATE UNIQUE INDEX "PROJECT_BRANCHES_KEE" ON "PROJECT_BRANCHES" ("PROJECT_UUID", "KEE_TYPE", "KEE");

+ 26
- 0
server/sonar-server/src/main/java/org/sonar/server/component/ComponentUpdater.java View File

@@ -24,12 +24,16 @@ import java.util.List;
import java.util.Locale;
import javax.annotation.Nullable;
import org.sonar.api.i18n.I18n;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.System2;
import org.sonar.core.component.ComponentKeys;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchKeyType;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.server.es.ProjectIndexer.Cause;
import org.sonar.server.es.ProjectIndexers;
@@ -70,6 +74,9 @@ public class ComponentUpdater {
public ComponentDto create(DbSession dbSession, NewComponent newComponent, @Nullable Integer userId) {
checkKeyFormat(newComponent.qualifier(), newComponent.key());
ComponentDto componentDto = createRootComponent(dbSession, newComponent);
if (isRootProject(componentDto)) {
createBranch(dbSession, componentDto.uuid());
}
removeDuplicatedProjects(dbSession, componentDto.getDbKey());
handlePermissionTemplate(dbSession, componentDto, newComponent.getOrganizationUuid(), userId);
projectIndexers.commitAndIndex(dbSession, singletonList(componentDto), Cause.PROJECT_CREATION);
@@ -100,9 +107,28 @@ public class ComponentUpdater {
.setPrivate(newComponent.isPrivate())
.setCreatedAt(new Date(system2.now()));
dbClient.componentDao().insert(session, component);

return component;
}

private static boolean isRootProject(ComponentDto componentDto) {
return Scopes.PROJECT.equals(componentDto.scope()) && Qualifiers.PROJECT.equals(componentDto.qualifier());
}

private BranchDto createBranch(DbSession session, String componentUuid) {
BranchDto branch = new BranchDto()
.setBranchType(BranchType.LONG)
.setKeeType(BranchKeyType.BRANCH)
.setUuid(componentUuid)
.setKey(null)
.setMergeBranchUuid(null)
.setPullRequestTitle(null)
.setProjectUuid(componentUuid);

dbClient.branchDao().upsert(session, branch);
return branch;
}

/**
* On MySQL, as PROJECTS.KEE is not unique, if the same project is provisioned multiple times, then it will be duplicated in the database.
* So, after creating a project, we commit, and we search in the db if their are some duplications and we remove them.

+ 114
- 0
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/BranchPersister.java View File

@@ -0,0 +1,114 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.computation.task.projectanalysis.component;

import java.util.Date;
import java.util.Optional;
import javax.annotation.Nullable;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchKeyType;
import org.sonar.db.component.ComponentDto;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.analysis.Branch;

import static org.sonar.db.component.ComponentDto.UUID_PATH_OF_ROOT;
import static org.sonar.db.component.ComponentDto.UUID_PATH_SEPARATOR;

public class BranchPersister {
private final DbClient dbClient;
private final System2 system2;
private final TreeRootHolder treeRootHolder;
private final AnalysisMetadataHolder analysisMetadataHolder;

public BranchPersister(DbClient dbClient, System2 system2, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder) {
this.dbClient = dbClient;
this.system2 = system2;
this.treeRootHolder = treeRootHolder;
this.analysisMetadataHolder = analysisMetadataHolder;
}

public void persist(DbSession dbSession) {
Optional<Branch> branchOpt = analysisMetadataHolder.getBranch();
if (!branchOpt.isPresent()) {
return;
}

Branch branch = branchOpt.get();
String branchUuid = treeRootHolder.getRoot().getUuid();

com.google.common.base.Optional<ComponentDto> branchComponentDtoOpt = dbClient.componentDao().selectByUuid(dbSession, branchUuid);

ComponentDto branchComponentDto;
if (branch.isMain()) {
checkState(branchComponentDtoOpt.isPresent(), "Project has been deleted by end-user during analysis");
branchComponentDto = branchComponentDtoOpt.get();

} else {
// inserts new row in table projects if it's the first time branch is analyzed
branchComponentDto = branchComponentDtoOpt.or(() -> insertIntoProjectsTable(dbSession, branchUuid));

}
// insert or update in table project_branches
dbClient.branchDao().upsert(dbSession, toBranchDto(branchComponentDto, branch));
}

private static void checkState(boolean condition, String msg) {
if (!condition) {
throw new IllegalStateException(msg);
}
}

private static <T> T firstNonNull(@Nullable T first, T second) {
return (first != null) ? first : second;
}

private static BranchDto toBranchDto(ComponentDto componentDto, Branch branch) {
BranchDto dto = new BranchDto();
dto.setUuid(componentDto.uuid());
// MainBranchProjectUuid will be null if it's a main branch
dto.setProjectUuid(firstNonNull(componentDto.getMainBranchProjectUuid(), componentDto.projectUuid()));
dto.setKeeType(BranchKeyType.BRANCH);
dto.setKey(branch.getName().orElse(null));
dto.setBranchType(branch.getType());
// merge branch is only present if it's a short living branch
dto.setMergeBranchUuid(branch.getMergeBranchUuid().orElse(null));
dto.setPullRequestTitle(null);
return dto;
}

private ComponentDto insertIntoProjectsTable(DbSession dbSession, String branchUuid) {
String mainBranchProjectUuid = analysisMetadataHolder.getProject().getUuid();
ComponentDto project = dbClient.componentDao().selectOrFailByUuid(dbSession, mainBranchProjectUuid);
ComponentDto branchDto = project.copy();
branchDto.setUuid(branchUuid);
branchDto.setProjectUuid(branchUuid);
branchDto.setRootUuid(branchUuid);
branchDto.setUuidPath(UUID_PATH_OF_ROOT);
branchDto.setModuleUuidPath(UUID_PATH_SEPARATOR + branchUuid + UUID_PATH_SEPARATOR);
branchDto.setMainBranchProjectUuid(mainBranchProjectUuid);
branchDto.setDbKey(treeRootHolder.getRoot().getKey());
branchDto.setCreatedAt(new Date(system2.now()));
dbClient.componentDao().insert(dbSession, branchDto);
return branchDto;
}
}

+ 0
- 30
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/BranchPersisterDelegate.java View File

@@ -1,30 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.computation.task.projectanalysis.component;

import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.db.DbSession;

@ComputeEngineSide
public interface BranchPersisterDelegate {

void persist(DbSession dbSession);

}

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/DefaultBranchImpl.java View File

@@ -71,7 +71,7 @@ public class DefaultBranchImpl implements Branch {

@Override
public boolean isLegacyFeature() {
return true;
return isLegacyBranch;
}

@Override

+ 2
- 0
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java View File

@@ -36,6 +36,7 @@ import org.sonar.server.computation.task.projectanalysis.api.posttask.PostProjec
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportDirectoryHolderImpl;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderImpl;
import org.sonar.server.computation.task.projectanalysis.component.BranchLoader;
import org.sonar.server.computation.task.projectanalysis.component.BranchPersister;
import org.sonar.server.computation.task.projectanalysis.component.ConfigurationRepositoryImpl;
import org.sonar.server.computation.task.projectanalysis.component.DbIdsRepositoryImpl;
import org.sonar.server.computation.task.projectanalysis.component.DisabledComponentsHolderImpl;
@@ -244,6 +245,7 @@ public final class ProjectAnalysisTaskContainerPopulator implements ContainerPop
ComponentIssuesLoader.class,
BaseIssuesLoader.class,
IssueTrackingDelegator.class,
BranchPersister.class,

// filemove
SourceSimilarityImpl.class,

+ 4
- 11
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistComponentsStep.java View File

@@ -50,7 +50,7 @@ import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentUpdateDto;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
import org.sonar.server.computation.task.projectanalysis.component.BranchPersisterDelegate;
import org.sonar.server.computation.task.projectanalysis.component.BranchPersister;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
import org.sonar.server.computation.task.projectanalysis.component.DbIdsRepositoryImpl;
@@ -75,19 +75,12 @@ public class PersistComponentsStep implements ComputationStep {
private final System2 system2;
private final MutableDisabledComponentsHolder disabledComponentsHolder;
private final AnalysisMetadataHolder analysisMetadataHolder;
@Nullable
private final BranchPersisterDelegate branchPersister;

public PersistComponentsStep(DbClient dbClient, TreeRootHolder treeRootHolder,
MutableDbIdsRepository dbIdsRepository, System2 system2,
MutableDisabledComponentsHolder disabledComponentsHolder, AnalysisMetadataHolder analysisMetadataHolder) {
this(dbClient, treeRootHolder, dbIdsRepository, system2, disabledComponentsHolder, analysisMetadataHolder, null);
}
private final BranchPersister branchPersister;

public PersistComponentsStep(DbClient dbClient, TreeRootHolder treeRootHolder,
MutableDbIdsRepository dbIdsRepository, System2 system2,
MutableDisabledComponentsHolder disabledComponentsHolder, AnalysisMetadataHolder analysisMetadataHolder,
@Nullable BranchPersisterDelegate branchPersister) {
BranchPersister branchPersister) {
this.dbClient = dbClient;
this.treeRootHolder = treeRootHolder;
this.dbIdsRepository = dbIdsRepository;
@@ -105,7 +98,7 @@ public class PersistComponentsStep implements ComputationStep {
@Override
public void execute() {
try (DbSession dbSession = dbClient.openSession(false)) {
ofNullable(branchPersister).ifPresent(p -> p.persist(dbSession));
branchPersister.persist(dbSession);

String projectUuid = treeRootHolder.getRoot().getUuid();


+ 18
- 0
server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java View File

@@ -19,6 +19,7 @@
*/
package org.sonar.server.component;

import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -26,6 +27,9 @@ import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchKeyType;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.UserDto;
@@ -94,6 +98,16 @@ public class ComponentUpdaterTest {
assertThat(db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY)).isNotNull();

assertThat(projectIndexers.hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION)).isTrue();

Optional<BranchDto> branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), returned.uuid());
assertThat(branch).isPresent();
assertThat(branch.get().getKeeType()).isEqualTo(BranchKeyType.BRANCH);
assertThat(branch.get().getKey()).isNull();
assertThat(branch.get().getMergeBranchUuid()).isNull();
assertThat(branch.get().getPullRequestTitle()).isNull();
assertThat(branch.get().getBranchType()).isEqualTo(BranchType.LONG);
assertThat(branch.get().getUuid()).isEqualTo(returned.uuid());
assertThat(branch.get().getProjectUuid()).isEqualTo(returned.uuid());
}

@Test
@@ -154,6 +168,8 @@ public class ComponentUpdaterTest {
assertThat(loaded.name()).isEqualTo("view-name");
assertThat(loaded.qualifier()).isEqualTo("VW");
assertThat(projectIndexers.hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION)).isTrue();
Optional<BranchDto> branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), returned.uuid());
assertThat(branch).isNotPresent();
}

@Test
@@ -172,6 +188,8 @@ public class ComponentUpdaterTest {
assertThat(loaded.name()).isEqualTo("app-name");
assertThat(loaded.qualifier()).isEqualTo("APP");
assertThat(projectIndexers.hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION)).isTrue();
Optional<BranchDto> branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), returned.uuid());
assertThat(branch).isNotPresent();
}

@Test

+ 105
- 0
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/BranchPersisterTest.java View File

@@ -0,0 +1,105 @@
/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.computation.task.projectanalysis.component;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;

import java.util.Optional;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
import org.sonar.server.computation.task.projectanalysis.analysis.Project;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;

public class BranchPersisterTest {
private final static Component MAIN = builder(PROJECT, 1).setUuid("PROJECT_UUID").setKey("PROJECT_KEY").build();
private final static Component BRANCH = builder(PROJECT, 1).setUuid("BRANCH_UUID").setKey("BRANCH_KEY").build();

@Rule
public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@Rule
public ExpectedException exception = ExpectedException.none();

BranchPersister underTest = new BranchPersister(dbTester.getDbClient(), System2.INSTANCE, treeRootHolder, analysisMetadataHolder);

@Test
public void fail_if_no_component_for_main_branches() {
analysisMetadataHolder.setBranch(createBranch(BranchType.LONG, true, null));
treeRootHolder.setRoot(MAIN);

exception.expect(IllegalStateException.class);
exception.expectMessage("Project has been deleted by end-user during analysis");

underTest.persist(dbTester.getSession());
}

@Test
public void skip_if_no_branch() {
analysisMetadataHolder.setBranch(null);
underTest.persist(dbTester.getSession());
dbTester.assertTableDoesNotExist("project_branch");
}

@Test
public void persist_secondary_branch() {
analysisMetadataHolder.setBranch(createBranch(BranchType.LONG, false, "branch"));
treeRootHolder.setRoot(BRANCH);

// add main branch in project table and in metadata
ComponentDto dto = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert(), MAIN.getUuid()).setDbKey(MAIN.getKey());
analysisMetadataHolder.setProject(Project.copyOf(dto));
dbTester.getDbClient().componentDao().insert(dbTester.getSession(), dto);

// this should add new columns in project and project_branches
underTest.persist(dbTester.getSession());

dbTester.getSession().commit();

assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(2);
assertThat(dbTester.countRowsOfTable("project_branches")).isEqualTo(1);

}

private static Branch createBranch(BranchType type, boolean isMain, @Nullable String name) {
Branch branch = mock(Branch.class);
when(branch.getType()).thenReturn(type);
when(branch.getName()).thenReturn(Optional.ofNullable(name));
when(branch.isMain()).thenReturn(isMain);
when(branch.getMergeBranchUuid()).thenReturn(Optional.empty());
return branch;
}
}

+ 2
- 2
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/PersistComponentsStepTest.java View File

@@ -28,7 +28,7 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDao;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.component.BranchPersisterDelegate;
import org.sonar.server.computation.task.projectanalysis.component.BranchPersister;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.MutableDbIdsRepository;
import org.sonar.server.computation.task.projectanalysis.component.MutableDisabledComponentsHolder;
@@ -69,6 +69,6 @@ public class PersistComponentsStepTest {
System2.INSTANCE,
mock(MutableDisabledComponentsHolder.class),
mock(AnalysisMetadataHolder.class),
mock(BranchPersisterDelegate.class)).execute();
mock(BranchPersister.class)).execute();
}
}

+ 3
- 2
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ReportPersistComponentsStepTest.java View File

@@ -40,7 +40,7 @@ import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
import org.sonar.server.computation.task.projectanalysis.analysis.Project;
import org.sonar.server.computation.task.projectanalysis.component.BranchPersisterDelegate;
import org.sonar.server.computation.task.projectanalysis.component.BranchPersister;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.FileAttributes;
import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
@@ -88,7 +88,7 @@ public class ReportPersistComponentsStepTest extends BaseStepTest {
private Date now;
private MutableDisabledComponentsHolder disabledComponentsHolder = mock(MutableDisabledComponentsHolder.class, RETURNS_DEEP_STUBS);
private PersistComponentsStep underTest;
private BranchPersisterDelegate branchPersister;
private BranchPersister branchPersister;

@Before
public void setup() throws Exception {
@@ -96,6 +96,7 @@ public class ReportPersistComponentsStepTest extends BaseStepTest {
when(system2.now()).thenReturn(now.getTime());

db.organizations().insertForUuid(ORGANIZATION_UUID);
branchPersister = mock(BranchPersister.class);
underTest = new PersistComponentsStep(dbClient, treeRootHolder, dbIdsRepository, system2, disabledComponentsHolder, analysisMetadataHolder, branchPersister);
}


+ 3
- 2
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ViewsPersistComponentsStepTest.java View File

@@ -37,7 +37,7 @@ import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.BranchPersisterDelegate;
import org.sonar.server.computation.task.projectanalysis.component.BranchPersister;
import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
import org.sonar.server.computation.task.projectanalysis.component.MutableDbIdsRepositoryRule;
import org.sonar.server.computation.task.projectanalysis.component.MutableDisabledComponentsHolder;
@@ -95,7 +95,7 @@ public class ViewsPersistComponentsStepTest extends BaseStepTest {
private ComponentDbTester componentDbTester = new ComponentDbTester(dbTester);
private MutableDisabledComponentsHolder disabledComponentsHolder = mock(MutableDisabledComponentsHolder.class, RETURNS_DEEP_STUBS);
private PersistComponentsStep underTest;
private BranchPersisterDelegate branchPersister;
private BranchPersister branchPersister;

@Before
public void setup() throws Exception {
@@ -104,6 +104,7 @@ public class ViewsPersistComponentsStepTest extends BaseStepTest {

dbTester.organizations().insertForUuid(ORGANIZATION_UUID);
analysisMetadataHolder.setBranch(new DefaultBranchImpl(null));
branchPersister = mock(BranchPersister.class);
underTest = new PersistComponentsStep(dbClient, treeRootHolder, dbIdsRepository, system2, disabledComponentsHolder, analysisMetadataHolder, branchPersister);
}


Loading…
Cancel
Save