diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComponentUuidsCache.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComponentUuidsCache.java new file mode 100644 index 000000000000..e7f60c6def8e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComponentUuidsCache.java @@ -0,0 +1,56 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.step; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import org.sonar.batch.protocol.output.BatchReportReader; + +import java.util.concurrent.ExecutionException; + +/** + * Waiting for having all components persisted by the Compute Engine, this class contains a cache of component uuids by their report reference + */ +public class ComponentUuidsCache { + + private final Cache componentRefToUuidCache; + + public ComponentUuidsCache(final BatchReportReader reader) { + this.componentRefToUuidCache = CacheBuilder.newBuilder() + .maximumSize(500_000) + .build( + new CacheLoader() { + @Override + public String load(Integer ref) { + return reader.readComponent(ref).getUuid(); + } + }); + } + + public String getUuidFromRef(int componentRef) { + try { + return componentRefToUuidCache.get(componentRef); + } catch (ExecutionException e) { + throw new IllegalStateException(String.format("Error while retrieving uuid of component ref '%d'", componentRef), e); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java index a10c5c6e2c9c..30c26cb844db 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java @@ -48,6 +48,7 @@ public static List> orderedStepClasses() { PersistEventsStep.class, PersistDuplicationMeasuresStep.class, PersistFileSourcesStep.class, + PersistFileDependenciesStep.class, // Switch snapshot and purge SwitchSnapshotStep.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistFileDependenciesStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistFileDependenciesStep.java new file mode 100644 index 000000000000..7d81e2a472fd --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistFileDependenciesStep.java @@ -0,0 +1,143 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.step; + +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.utils.System2; +import org.sonar.batch.protocol.Constants; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReportReader; +import org.sonar.core.design.FileDependencyDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.server.computation.ComputationContext; +import org.sonar.server.computation.source.ReportIterator; +import org.sonar.server.db.DbClient; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +public class PersistFileDependenciesStep implements ComputationStep { + + private final DbClient dbClient; + private final System2 system2; + + public PersistFileDependenciesStep(DbClient dbClient, System2 system2) { + this.dbClient = dbClient; + this.system2 = system2; + } + + @Override + public String[] supportedProjectQualifiers() { + return new String[] {Qualifiers.PROJECT}; + } + + @Override + public void execute(ComputationContext context) { + DbSession session = dbClient.openSession(true); + try { + FileDependenciesContext fileDependenciesContext = new FileDependenciesContext(context, session); + int rootComponentRef = context.getReportMetadata().getRootComponentRef(); + recursivelyProcessComponent(fileDependenciesContext, rootComponentRef, rootComponentRef); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + private void recursivelyProcessComponent(FileDependenciesContext fileDependenciesContext, int componentRef, int parentModuleRef) { + BatchReportReader reportReader = fileDependenciesContext.context.getReportReader(); + BatchReport.Component component = reportReader.readComponent(componentRef); + if (component.getType().equals(Constants.ComponentType.FILE)) { + processFileDependenciesReport(fileDependenciesContext, component); + } + + for (Integer childRef : component.getChildRefList()) { + recursivelyProcessComponent(fileDependenciesContext, childRef, componentRef); + } + } + + private void processFileDependenciesReport(FileDependenciesContext fileDependenciesContext, BatchReport.Component component){ + File fileDependencyReport = fileDependenciesContext.context.getReportReader().readFileDependencies(component.getRef()); + if (fileDependencyReport != null) { + ReportIterator fileDependenciesIterator = new ReportIterator<>(fileDependencyReport, BatchReport.FileDependency.PARSER); + try { + while (fileDependenciesIterator.hasNext()) { + BatchReport.FileDependency fileDependency = fileDependenciesIterator.next(); + persistFileDependency(fileDependenciesContext, fileDependency, component.getRef()); + } + } finally { + fileDependenciesIterator.close(); + } + } + } + + private void persistFileDependency(FileDependenciesContext fileDependenciesContext, BatchReport.FileDependency fileDependency, int fromRef){ + int toFileRef = fileDependency.getToFileRef(); + String fromComponentUuid = fileDependenciesContext.uuidsByRef.getUuidFromRef(fromRef); + String toComponentUuid = fileDependenciesContext.uuidsByRef.getUuidFromRef(toFileRef); + dbClient.fileDependencyDao().insert(fileDependenciesContext.session, new FileDependencyDto() + .setFromComponentUuid(fileDependenciesContext.uuidsByRef.getUuidFromRef(fromRef)) + .setToComponentUuid(fileDependenciesContext.uuidsByRef.getUuidFromRef(toFileRef)) + .setFromParentUuid(fileDependenciesContext.parentUuidsByComponentUuid.get(fromComponentUuid)) + .setToParentUuid(fileDependenciesContext.parentUuidsByComponentUuid.get(toComponentUuid)) + .setRootProjectSnapshotId(fileDependenciesContext.rootSnapshotId) + .setWeight(fileDependency.getWeight()) + .setCreatedAt(system2.now()) + ); + } + + private static class FileDependenciesContext { + private final Long rootSnapshotId; + private final ComponentUuidsCache uuidsByRef; + private final ComputationContext context; + private final Map parentUuidsByComponentUuid = new HashMap<>(); + private final DbSession session; + + public FileDependenciesContext(ComputationContext context, DbSession session) { + this.context = context; + this.rootSnapshotId = context.getReportMetadata().getSnapshotId(); + this.session = session; + this.uuidsByRef = new ComponentUuidsCache(context.getReportReader()); + int rootComponentRef = context.getReportMetadata().getRootComponentRef(); + recursivelyProcessParentByComponentCache(rootComponentRef, rootComponentRef); + } + + private void recursivelyProcessParentByComponentCache(int componentRef, int parentModuleRef){ + BatchReportReader reportReader = context.getReportReader(); + BatchReport.Component component = reportReader.readComponent(componentRef); + BatchReport.Component parent = reportReader.readComponent(parentModuleRef); + if (component.getType().equals(Constants.ComponentType.FILE)) { + parentUuidsByComponentUuid.put(component.getUuid(), parent.getUuid()); + } + + for (Integer childRef : component.getChildRefList()) { + recursivelyProcessParentByComponentCache(childRef, componentRef); + } + } + } + + @Override + public String getDescription() { + return "Persist file dependencies"; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistTestsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistTestsStep.java index 8be0e1c5d2ed..0d955de040ee 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistTestsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistTestsStep.java @@ -21,9 +21,6 @@ package org.sonar.server.computation.step; import com.google.common.base.Joiner; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.HashBasedTable; import com.google.common.collect.ImmutableMap; @@ -55,7 +52,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.ExecutionException; public class PersistTestsStep implements ComputationStep { @@ -245,7 +241,7 @@ private static class TestContext { final DbSession session; final ComputationContext context; final BatchReportReader reader; - final Cache componentRefToUuidCache; + final ComponentUuidsCache componentRefToUuidCache; final Map existingFileSourcesByUuid; boolean hasUnprocessedCoverageDetails = false; @@ -253,16 +249,8 @@ private static class TestContext { this.session = session; this.context = context; this.reader = context.getReportReader(); - this.componentRefToUuidCache = CacheBuilder.newBuilder() - .maximumSize(500_000) - .build( - new CacheLoader() { - @Override - public String load(Integer key) { - return reader.readComponent(key).getUuid(); - } - }); - existingFileSourcesByUuid = new HashMap<>(); + this.componentRefToUuidCache = new ComponentUuidsCache(context.getReportReader()); + this.existingFileSourcesByUuid = new HashMap<>(); session.select("org.sonar.core.source.db.FileSourceMapper.selectHashesForProject", ImmutableMap.of("projectUuid", context.getProject().uuid(), "dataType", Type.TEST), new ResultHandler() { @@ -275,11 +263,7 @@ public void handleResult(ResultContext context) { } public String getUuid(int fileRef) { - try { - return componentRefToUuidCache.get(fileRef); - } catch (ExecutionException e) { - throw new IllegalStateException(String.format("Error while retrieving uuid of component file ref '%d'", fileRef), e); - } + return componentRefToUuidCache.getUuidFromRef(fileRef); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/design/db/FileDependencyDao.java b/server/sonar-server/src/main/java/org/sonar/server/design/db/FileDependencyDao.java index 0a7bfcd4d684..9cae760f3a87 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/design/db/FileDependencyDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/design/db/FileDependencyDao.java @@ -34,6 +34,11 @@ public List selectFromParents(DbSession session, String fromP return session.getMapper(FileDependencyMapper.class).selectFromParents(fromParentUuid, toParentUuid, projectId); } + public List selectAll(DbSession session) { + return session.getMapper(FileDependencyMapper.class).selectAll(); + } + + public void insert(DbSession session, FileDependencyDto dto) { session.getMapper(FileDependencyMapper.class).insert(dto); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/design/db/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/design/db/package-info.java new file mode 100644 index 000000000000..4cd7fad5bb4e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/design/db/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ + +@ParametersAreNonnullByDefault +package org.sonar.server.design.db; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/design/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/design/package-info.java new file mode 100644 index 000000000000..f0cbe012a174 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/design/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ + +@ParametersAreNonnullByDefault +package org.sonar.server.design; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComponentUuidsCacheTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComponentUuidsCacheTest.java new file mode 100644 index 000000000000..23c124698a6e --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComponentUuidsCacheTest.java @@ -0,0 +1,60 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.step; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.batch.protocol.Constants; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReportReader; +import org.sonar.batch.protocol.output.BatchReportWriter; + +import java.io.File; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ComponentUuidsCacheTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + File reportDir; + + @Before + public void setUp() throws Exception { + reportDir = temp.newFolder(); + } + + @Test + public void get_uuid_from_ref() throws Exception { + BatchReportWriter writer = new BatchReportWriter(reportDir); + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(1) + .setType(Constants.ComponentType.PROJECT) + .setUuid("ABCD") + .build()); + + ComponentUuidsCache cache = new ComponentUuidsCache(new BatchReportReader(reportDir)); + assertThat(cache.getUuidFromRef(1)).isEqualTo("ABCD"); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java index 9fb4ecb52096..d36e4cb24126 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java @@ -48,12 +48,13 @@ public void ordered_steps() throws Exception { mock(PersistEventsStep.class), mock(PersistDuplicationMeasuresStep.class), mock(PersistNumberOfDaysSinceLastCommitStep.class), - mock(PersistFileSourcesStep.class) + mock(PersistFileSourcesStep.class), + mock(PersistFileDependenciesStep.class) ); - assertThat(registry.orderedSteps()).hasSize(17); + assertThat(registry.orderedSteps()).hasSize(18); assertThat(registry.orderedSteps().get(0)).isInstanceOf(ParseReportStep.class); - assertThat(registry.orderedSteps().get(16)).isInstanceOf(SendIssueNotificationsStep.class); + assertThat(registry.orderedSteps().get(17)).isInstanceOf(SendIssueNotificationsStep.class); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistFileDependenciesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistFileDependenciesStepTest.java new file mode 100644 index 000000000000..b22b133334ed --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistFileDependenciesStepTest.java @@ -0,0 +1,190 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.step; + +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.utils.System2; +import org.sonar.batch.protocol.Constants; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReportReader; +import org.sonar.batch.protocol.output.BatchReportWriter; +import org.sonar.core.design.FileDependencyDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.DbTester; +import org.sonar.server.component.ComponentTesting; +import org.sonar.server.computation.ComputationContext; +import org.sonar.server.db.DbClient; +import org.sonar.server.design.db.FileDependencyDao; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class PersistFileDependenciesStepTest extends BaseStepTest { + + static final String PROJECT_UUID = "PROJECT"; + static final long PROJECT_SNAPSHOT_ID = 10L; + static final long now = 123456789L; + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @ClassRule + public static DbTester dbTester = new DbTester(); + + DbClient dbClient; + + System2 system2 = mock(System2.class); + + DbSession session; + + BatchReportWriter writer; + + ComputationContext context; + + PersistFileDependenciesStep sut; + + @Before + public void setup() throws Exception { + dbTester.truncateTables(); + session = dbTester.myBatis().openSession(false); + dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new FileDependencyDao()); + + system2 = mock(System2.class); + when(system2.now()).thenReturn(now); + + File reportDir = temp.newFolder(); + writer = new BatchReportWriter(reportDir); + writer.writeMetadata(BatchReport.Metadata.newBuilder() + .setRootComponentRef(1) + .setSnapshotId(PROJECT_SNAPSHOT_ID) + .build()); + context = new ComputationContext(new BatchReportReader(reportDir), ComponentTesting.newProjectDto(PROJECT_UUID)); + + sut = new PersistFileDependenciesStep(dbClient, system2); + } + + @After + public void tearDown() throws Exception { + session.close(); + } + + @Override + protected ComputationStep step() throws IOException { + return new PersistFileDependenciesStep(dbClient, system2); + } + + @Test + public void supported_project_qualifiers() throws Exception { + assertThat(step().supportedProjectQualifiers()).containsOnly(Qualifiers.PROJECT); + } + + @Test + public void persist_file_dependencies() throws Exception { + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(1) + .setType(Constants.ComponentType.PROJECT) + .setUuid(PROJECT_UUID) + .addChildRef(2) + .addChildRef(4) + .build()); + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(2) + .setType(Constants.ComponentType.DIRECTORY) + .setUuid("DIRECTORY_A") + .addChildRef(3) + .build()); + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(3) + .setType(Constants.ComponentType.FILE) + .setUuid("FILE_A") + .build()); + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(4) + .setType(Constants.ComponentType.DIRECTORY) + .setUuid("DIRECTORY_B") + .addChildRef(5) + .build()); + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(5) + .setType(Constants.ComponentType.FILE) + .setUuid("FILE_B") + .build()); + + writer.writeFileDependencies(3, Collections.singletonList( + BatchReport.FileDependency.newBuilder() + .setToFileRef(5) + .setWeight(1) + .build() + )); + + sut.execute(context); + + List dtos = dbClient.fileDependencyDao().selectAll(session); + assertThat(dtos).hasSize(1); + + FileDependencyDto dto = dtos.get(0); + assertThat(dto.getId()).isNotNull(); + assertThat(dto.getFromComponentUuid()).isEqualTo("FILE_A"); + assertThat(dto.getFromParentUuid()).isEqualTo("DIRECTORY_A"); + assertThat(dto.getToComponentUuid()).isEqualTo("FILE_B"); + assertThat(dto.getToParentUuid()).isEqualTo("DIRECTORY_B"); + assertThat(dto.getRootProjectSnapshotId()).isEqualTo(PROJECT_SNAPSHOT_ID); + assertThat(dto.getWeight()).isEqualTo(1); + assertThat(dto.getCreatedAt()).isEqualTo(now); + } + + @Test + public void nothing_to_persist() throws Exception { + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(1) + .setType(Constants.ComponentType.PROJECT) + .setUuid(PROJECT_UUID) + .addChildRef(2) + .build()); + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(2) + .setType(Constants.ComponentType.DIRECTORY) + .setUuid("DIRECTORY_A") + .addChildRef(3) + .build()); + writer.writeComponent(BatchReport.Component.newBuilder() + .setRef(3) + .setType(Constants.ComponentType.FILE) + .setUuid("FILE_A") + .build()); + + sut.execute(context); + + assertThat(dbClient.fileDependencyDao().selectAll(session)).isEmpty(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/design/db/FileDependencyDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/design/db/FileDependencyDaoTest.java index e7877bfd3860..e9b515b0c0d0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/design/db/FileDependencyDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/design/db/FileDependencyDaoTest.java @@ -75,6 +75,13 @@ public void select_from_parents() throws Exception { assertThat(dao.selectFromParents(session, "MNOP", "QRST", 123L)).isEmpty(); } + @Test + public void select_all() throws Exception { + dbTester.prepareDbUnit(getClass(), "shared.xml"); + + assertThat(dao.selectAll(session)).hasSize(3); + } + @Test public void insert() throws Exception { dao.insert(session, new FileDependencyDto() diff --git a/sonar-core/src/main/java/org/sonar/core/design/FileDependencyMapper.java b/sonar-core/src/main/java/org/sonar/core/design/FileDependencyMapper.java index 1db9580520e2..5bed50d09fb3 100644 --- a/sonar-core/src/main/java/org/sonar/core/design/FileDependencyMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/design/FileDependencyMapper.java @@ -27,6 +27,8 @@ public interface FileDependencyMapper { List selectFromParents(@Param("fromParentUuid") String fromParentUuid, @Param("toParentUuid") String toParentUuid, @Param("projectId") Long projectId); + List selectAll(); + void insert(FileDependencyDto dto); } diff --git a/sonar-core/src/main/resources/org/sonar/core/design/FileDependencyMapper.xml b/sonar-core/src/main/resources/org/sonar/core/design/FileDependencyMapper.xml index e738132b7045..2d66c12a62ce 100644 --- a/sonar-core/src/main/resources/org/sonar/core/design/FileDependencyMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/design/FileDependencyMapper.xml @@ -24,6 +24,11 @@ + + INSERT INTO dependencies (from_component_uuid, to_component_uuid, from_parent_uuid, to_parent_uuid, root_project_snapshot_id, dep_weight, created_at) VALUES (#{fromComponentUuid,jdbcType=VARCHAR}, #{toComponentUuid,jdbcType=VARCHAR}, #{fromParentUuid,jdbcType=VARCHAR}, #{toParentUuid,jdbcType=BOOLEAN},